diff --git a/src/CONST.ts b/src/CONST.ts index b27923465a1f..6234009a1a01 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -100,6 +100,10 @@ const CONST = { MAX_LENGTH: 40, }, + REPORT_DESCRIPTION: { + MAX_LENGTH: 1024, + }, + PULL_REQUEST_NUMBER, MERCHANT_NAME_MAX_LENGTH: 255, @@ -1588,7 +1592,6 @@ const CONST = { INVITE: 'invite', SETTINGS: 'settings', LEAVE_ROOM: 'leaveRoom', - WELCOME_MESSAGE: 'welcomeMessage', PRIVATE_NOTES: 'privateNotes', }, EDIT_REQUEST_FIELD: { diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 83b6d1b31e4a..6f75cf2eacb6 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -313,8 +313,8 @@ const ONYXKEYS = { DISPLAY_NAME_FORM_DRAFT: 'displayNameFormDraft', ROOM_NAME_FORM: 'roomNameForm', ROOM_NAME_FORM_DRAFT: 'roomNameFormDraft', - WELCOME_MESSAGE_FORM: 'welcomeMessageForm', - WELCOME_MESSAGE_FORM_DRAFT: 'welcomeMessageFormDraft', + REPORT_DESCRIPTION_FORM: 'reportDescriptionForm', + REPORT_DESCRIPTION_FORM_DRAFT: 'reportDescriptionFormDraft', LEGAL_NAME_FORM: 'legalNameForm', LEGAL_NAME_FORM_DRAFT: 'legalNameFormDraft', WORKSPACE_INVITE_MESSAGE_FORM: 'workspaceInviteMessageForm', @@ -501,8 +501,8 @@ type OnyxValues = { [ONYXKEYS.FORMS.DISPLAY_NAME_FORM_DRAFT]: OnyxTypes.DisplayNameForm; [ONYXKEYS.FORMS.ROOM_NAME_FORM]: OnyxTypes.RoomNameForm; [ONYXKEYS.FORMS.ROOM_NAME_FORM_DRAFT]: OnyxTypes.RoomNameForm; - [ONYXKEYS.FORMS.WELCOME_MESSAGE_FORM]: OnyxTypes.Form; - [ONYXKEYS.FORMS.WELCOME_MESSAGE_FORM_DRAFT]: OnyxTypes.Form; + [ONYXKEYS.FORMS.REPORT_DESCRIPTION_FORM]: OnyxTypes.Form; + [ONYXKEYS.FORMS.REPORT_DESCRIPTION_FORM_DRAFT]: OnyxTypes.Form; [ONYXKEYS.FORMS.LEGAL_NAME_FORM]: OnyxTypes.Form; [ONYXKEYS.FORMS.LEGAL_NAME_FORM_DRAFT]: OnyxTypes.Form; [ONYXKEYS.FORMS.WORKSPACE_INVITE_MESSAGE_FORM]: OnyxTypes.Form; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 78b97f8dcde0..016e4267803b 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -214,10 +214,6 @@ const ROUTES = { route: 'r/:reportID/settings/who-can-post', getRoute: (reportID: string) => `r/${reportID}/settings/who-can-post` as const, }, - REPORT_WELCOME_MESSAGE: { - route: 'r/:reportID/welcomeMessage', - getRoute: (reportID: string) => `r/${reportID}/welcomeMessage` as const, - }, SPLIT_BILL_DETAILS: { route: 'r/:reportID/split/:reportActionID', getRoute: (reportID: string, reportActionID: string) => `r/${reportID}/split/${reportActionID}` as const, @@ -235,7 +231,7 @@ const ROUTES = { route: 'r/:reportID/title', getRoute: (reportID: string) => `r/${reportID}/title` as const, }, - TASK_DESCRIPTION: { + REPORT_DESCRIPTION: { route: 'r/:reportID/description', getRoute: (reportID: string) => `r/${reportID}/description` as const, }, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index a64bf328ff28..e2f0e9745561 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -100,7 +100,7 @@ const SCREENS = { PROFILE: 'Profile', REPORT_DETAILS: 'Report_Details', REPORT_SETTINGS: 'Report_Settings', - REPORT_WELCOME_MESSAGE: 'Report_WelcomeMessage', + REPORT_DESCRIPTION: 'Report_Description', PARTICIPANTS: 'Participants', MONEY_REQUEST: 'MoneyRequest', NEW_TASK: 'NewTask', @@ -183,7 +183,6 @@ const SCREENS = { TASK: { TITLE: 'Task_Title', - DESCRIPTION: 'Task_Description', ASSIGNEE: 'Task_Assignee', }, @@ -242,7 +241,7 @@ const SCREENS = { DETAILS_ROOT: 'Details_Root', PROFILE_ROOT: 'Profile_Root', PROCESS_MONEY_REQUEST_HOLD_ROOT: 'ProcessMoneyRequestHold_Root', - REPORT_WELCOME_MESSAGE_ROOT: 'Report_WelcomeMessage_Root', + REPORT_DESCRIPTION_ROOT: 'Report_Description_Root', REPORT_PARTICIPANTS_ROOT: 'ReportParticipants_Root', ROOM_MEMBERS_ROOT: 'RoomMembers_Root', ROOM_INVITE_ROOT: 'RoomInvite_Root', diff --git a/src/components/DisplayNames/DisplayNamesWithTooltip.tsx b/src/components/DisplayNames/DisplayNamesWithTooltip.tsx index 1cacb0e20c5d..86fa8f475664 100644 --- a/src/components/DisplayNames/DisplayNamesWithTooltip.tsx +++ b/src/components/DisplayNames/DisplayNamesWithTooltip.tsx @@ -11,7 +11,7 @@ import type DisplayNamesProps from './types'; type HTMLElementWithText = HTMLElement & RNText; -function DisplayNamesWithToolTip({shouldUseFullTitle, fullTitle, displayNamesWithTooltips, textStyles = [], numberOfLines = 1}: DisplayNamesProps) { +function DisplayNamesWithToolTip({shouldUseFullTitle, fullTitle, displayNamesWithTooltips, textStyles = [], numberOfLines = 1, renderAdditionalText}: DisplayNamesProps) { const styles = useThemeStyles(); const containerRef = useRef(null); const childRefs = useRef([]); @@ -72,6 +72,7 @@ function DisplayNamesWithToolTip({shouldUseFullTitle, fullTitle, displayNamesWit {index < displayNamesWithTooltips.length - 1 && } ))} + {renderAdditionalText?.()} {Boolean(isEllipsisActive) && ( diff --git a/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx b/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx index 177bdb6a9fc4..c66d1698bbd6 100644 --- a/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx +++ b/src/components/DisplayNames/DisplayNamesWithoutTooltip.tsx @@ -12,9 +12,12 @@ type DisplayNamesWithoutTooltipProps = { /** Number of lines before wrapping */ numberOfLines?: number; + + /** Additional Text component to render after the displayNames */ + renderAdditionalText?: () => React.ReactNode; }; -function DisplayNamesWithoutTooltip({textStyles = [], numberOfLines = 1, fullTitle = ''}: DisplayNamesWithoutTooltipProps) { +function DisplayNamesWithoutTooltip({textStyles = [], numberOfLines = 1, fullTitle = '', renderAdditionalText}: DisplayNamesWithoutTooltipProps) { const styles = useThemeStyles(); return ( {fullTitle} + {renderAdditionalText?.()} ); } diff --git a/src/components/DisplayNames/index.native.tsx b/src/components/DisplayNames/index.native.tsx index b3eceb794bcb..ceee34586e8b 100644 --- a/src/components/DisplayNames/index.native.tsx +++ b/src/components/DisplayNames/index.native.tsx @@ -4,7 +4,7 @@ import useLocalize from '@hooks/useLocalize'; import type DisplayNamesProps from './types'; // As we don't have to show tooltips of the Native platform so we simply render the full display names list. -function DisplayNames({accessibilityLabel, fullTitle, textStyles = [], numberOfLines = 1}: DisplayNamesProps) { +function DisplayNames({accessibilityLabel, fullTitle, textStyles = [], numberOfLines = 1, renderAdditionalText}: DisplayNamesProps) { const {translate} = useLocalize(); return ( {fullTitle || translate('common.hidden')} + {renderAdditionalText?.()} ); } diff --git a/src/components/DisplayNames/index.tsx b/src/components/DisplayNames/index.tsx index 5b8844eb4e99..28e4d131d6de 100644 --- a/src/components/DisplayNames/index.tsx +++ b/src/components/DisplayNames/index.tsx @@ -4,7 +4,7 @@ import DisplayNamesWithoutTooltip from './DisplayNamesWithoutTooltip'; import DisplayNamesWithToolTip from './DisplayNamesWithTooltip'; import type DisplayNamesProps from './types'; -function DisplayNames({fullTitle, tooltipEnabled, textStyles, numberOfLines, shouldUseFullTitle, displayNamesWithTooltips}: DisplayNamesProps) { +function DisplayNames({fullTitle, tooltipEnabled, textStyles, numberOfLines, shouldUseFullTitle, displayNamesWithTooltips, renderAdditionalText}: DisplayNamesProps) { const {translate} = useLocalize(); const title = fullTitle || translate('common.hidden'); @@ -14,6 +14,7 @@ function DisplayNames({fullTitle, tooltipEnabled, textStyles, numberOfLines, sho textStyles={textStyles} numberOfLines={numberOfLines} fullTitle={title} + renderAdditionalText={renderAdditionalText} /> ); } @@ -35,6 +36,7 @@ function DisplayNames({fullTitle, tooltipEnabled, textStyles, numberOfLines, sho displayNamesWithTooltips={displayNamesWithTooltips} textStyles={textStyles} numberOfLines={numberOfLines} + renderAdditionalText={renderAdditionalText} /> ); } diff --git a/src/components/DisplayNames/types.ts b/src/components/DisplayNames/types.ts index 7da1819c9f01..8e7d711e04f8 100644 --- a/src/components/DisplayNames/types.ts +++ b/src/components/DisplayNames/types.ts @@ -39,6 +39,9 @@ type DisplayNamesProps = { /** If the full title needs to be displayed */ shouldUseFullTitle?: boolean; + + /** Additional Text component to render after the displayNames */ + renderAdditionalText?: () => React.ReactNode; }; export default DisplayNamesProps; diff --git a/src/components/Form/FormWrapper.tsx b/src/components/Form/FormWrapper.tsx index d5b47761e4c0..aa3aa5b40b5a 100644 --- a/src/components/Form/FormWrapper.tsx +++ b/src/components/Form/FormWrapper.tsx @@ -54,6 +54,7 @@ function FormWrapper({ formID, scrollContextEnabled = false, shouldHideFixErrorsAlert = false, + disablePressOnEnter = true, }: FormWrapperProps) { const styles = useThemeStyles(); const formRef = useRef(null); @@ -112,7 +113,7 @@ function FormWrapper({ containerStyles={[styles.mh0, styles.mt5, styles.flex1, submitButtonStyles]} enabledWhenOffline={enabledWhenOffline} isSubmitActionDangerous={isSubmitActionDangerous} - disablePressOnEnter + disablePressOnEnter={disablePressOnEnter} /> )} @@ -137,6 +138,7 @@ function FormWrapper({ submitButtonText, shouldHideFixErrorsAlert, onFixTheErrorsLinkPressed, + disablePressOnEnter, ], ); diff --git a/src/components/Form/types.ts b/src/components/Form/types.ts index 447f3205ad68..b2c7aea3f3cf 100644 --- a/src/components/Form/types.ts +++ b/src/components/Form/types.ts @@ -84,6 +84,9 @@ type FormProps = { /** Custom content to display in the footer after submit button */ footerContent?: ReactNode; + + /** Disable press on enter for submit button */ + disablePressOnEnter?: boolean; }; type RegisterInput = (inputID: keyof Form, inputProps: TInputProps) => TInputProps; diff --git a/src/components/ReportActionItem/TaskView.tsx b/src/components/ReportActionItem/TaskView.tsx index bdcc4d01b1a8..0d450e46568d 100644 --- a/src/components/ReportActionItem/TaskView.tsx +++ b/src/components/ReportActionItem/TaskView.tsx @@ -142,7 +142,7 @@ function TaskView({report, shouldShowHorizontalRule, ...props}: TaskViewProps) { shouldParseTitle description={translate('task.description')} title={report.description ?? ''} - onPress={() => Navigation.navigate(ROUTES.TASK_DESCRIPTION.getRoute(report.reportID))} + onPress={() => Navigation.navigate(ROUTES.REPORT_DESCRIPTION.getRoute(report.reportID))} shouldShowRightIcon={isOpen} disabled={disableState} wrapperStyle={[styles.pv2, styles.taskDescriptionMenuItem]} diff --git a/src/components/ReportWelcomeText.tsx b/src/components/ReportWelcomeText.tsx index 7c7364cc58f0..5e39e0adb93d 100644 --- a/src/components/ReportWelcomeText.tsx +++ b/src/components/ReportWelcomeText.tsx @@ -12,6 +12,8 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {PersonalDetailsList, Policy, Report} from '@src/types/onyx'; +import {PressableWithoutFeedback} from './Pressable'; +import RenderHTML from './RenderHTML'; import Text from './Text'; import UserDetailsTooltip from './UserDetailsTooltip'; @@ -57,29 +59,47 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP {isChatRoom ? translate('reportActionsView.welcomeToRoom', {roomName: ReportUtils.getReportName(report)}) : translate('reportActionsView.sayHello')} - + {isPolicyExpenseChat && ( - <> + {translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartOne')} {ReportUtils.getDisplayNameForParticipant(report?.ownerAccountID)} {translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartTwo')} {ReportUtils.getPolicyName(report)} {translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatPartThree')} - + )} {isChatRoom && ( <> - {roomWelcomeMessage.phrase1} - {roomWelcomeMessage.showReportName && ( - { + if (ReportUtils.canEditReportDescription(report, policy)) { + Navigation.navigate(ROUTES.REPORT_DESCRIPTION.getRoute(report.reportID)); + return; + } + Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID)); + }} + style={styles.renderHTML} + accessibilityLabel={translate('reportDescriptionPage.roomDescription')} > - {ReportUtils.getReportName(report)} + + + ) : ( + + {roomWelcomeMessage.phrase1} + {roomWelcomeMessage.showReportName && ( + + {ReportUtils.getReportName(report)} + + )} + {roomWelcomeMessage.phrase2 !== undefined && {roomWelcomeMessage.phrase2}} )} - {roomWelcomeMessage.phrase2 !== undefined && {roomWelcomeMessage.phrase2}} )} {isDefault && ( @@ -112,7 +132,7 @@ function ReportWelcomeText({report, policy, personalDetails}: ReportWelcomeTextP {(moneyRequestOptions.includes(CONST.IOU.TYPE.SEND) || moneyRequestOptions.includes(CONST.IOU.TYPE.REQUEST)) && ( {translate('reportActionsView.usePlusButton', {additionalText})} )} - + ); } diff --git a/src/languages/en.ts b/src/languages/en.ts index 95c8379aa4d5..860c38358b89 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -489,7 +489,7 @@ export default { chatWithAccountManager: 'Chat with your account manager here', sayHello: 'Say hello!', welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `Welcome to ${roomName}!`, - usePlusButton: ({additionalText}: UsePlusButtonParams) => `\n\nYou can also use the + button to ${additionalText}, or assign a task!`, + usePlusButton: ({additionalText}: UsePlusButtonParams) => `\nYou can also use the + button to ${additionalText}, or assign a task!`, iouTypes: { send: 'send money', split: 'split a bill', @@ -1054,10 +1054,10 @@ export default { }, }, }, - welcomeMessagePage: { - welcomeMessage: 'Welcome message', - welcomeMessageOptional: 'Welcome message (optional)', - explainerText: 'Set a custom welcome message that will be sent to users when they join this room.', + reportDescriptionPage: { + roomDescription: 'Room description', + roomDescriptionOptional: 'Room description (optional)', + explainerText: 'Set a custom decription for the room.', }, languagePage: { language: 'Language', @@ -1970,7 +1970,7 @@ export default { replies: 'Replies', reply: 'Reply', from: 'From', - in: 'In', + in: 'in', parentNavigationSummary: ({rootReportName, workspaceName}: ParentNavigationSummaryParams) => `From ${rootReportName}${workspaceName ? ` in ${workspaceName}` : ''}`, }, qrCodes: { diff --git a/src/languages/es.ts b/src/languages/es.ts index 3926f074f653..0dedf3dcdd34 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -481,7 +481,7 @@ export default { chatWithAccountManager: 'Chatea con tu gestor de cuenta aquí', sayHello: '¡Saluda!', welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `¡Bienvenido a ${roomName}!`, - usePlusButton: ({additionalText}: UsePlusButtonParams) => `\n\n¡También puedes usar el botón + de abajo para ${additionalText}, o asignar una tarea!`, + usePlusButton: ({additionalText}: UsePlusButtonParams) => `\n¡También puedes usar el botón + de abajo para ${additionalText}, o asignar una tarea!`, iouTypes: { send: 'enviar dinero', split: 'dividir una factura', @@ -1052,10 +1052,10 @@ export default { }, }, }, - welcomeMessagePage: { - welcomeMessage: 'Mensaje de bienvenida', - welcomeMessageOptional: 'Mensaje de bienvenida (opcional)', - explainerText: 'Configura un mensaje de bienvenida privado y personalizado que se enviará cuando los usuarios se unan a esta sala de chat.', + reportDescriptionPage: { + roomDescription: 'Descripción de la sala de chat', + roomDescriptionOptional: 'Descripción de la sala de chat (opcional)', + explainerText: 'Establece una descripción personalizada para la sala de chat.', }, languagePage: { language: 'Idioma', diff --git a/src/libs/API/parameters/AddWorkspaceRoomParams.ts b/src/libs/API/parameters/AddWorkspaceRoomParams.ts index f7cbff9565ef..847324586cb5 100644 --- a/src/libs/API/parameters/AddWorkspaceRoomParams.ts +++ b/src/libs/API/parameters/AddWorkspaceRoomParams.ts @@ -9,7 +9,7 @@ type AddWorkspaceRoomParams = { reportName?: string; visibility?: ValueOf; writeCapability?: WriteCapability; - welcomeMessage?: string; + description?: string; }; export default AddWorkspaceRoomParams; diff --git a/src/libs/API/parameters/UpdateRoomDescriptionParams.ts b/src/libs/API/parameters/UpdateRoomDescriptionParams.ts new file mode 100644 index 000000000000..4d78d07a9189 --- /dev/null +++ b/src/libs/API/parameters/UpdateRoomDescriptionParams.ts @@ -0,0 +1,6 @@ +type UpdateRoomDescriptionParams = { + reportID: string; + description: string; +}; + +export default UpdateRoomDescriptionParams; diff --git a/src/libs/API/parameters/UpdateWelcomeMessageParams.ts b/src/libs/API/parameters/UpdateWelcomeMessageParams.ts deleted file mode 100644 index a2d3b59fe3fa..000000000000 --- a/src/libs/API/parameters/UpdateWelcomeMessageParams.ts +++ /dev/null @@ -1,6 +0,0 @@ -type UpdateWelcomeMessageParams = { - reportID: string; - welcomeMessage: string; -}; - -export default UpdateWelcomeMessageParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index b7c3dff7c342..8103b54f8d81 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -84,7 +84,7 @@ export type {default as TogglePinnedChatParams} from './TogglePinnedChatParams'; export type {default as DeleteCommentParams} from './DeleteCommentParams'; export type {default as UpdateCommentParams} from './UpdateCommentParams'; export type {default as UpdateReportNotificationPreferenceParams} from './UpdateReportNotificationPreferenceParams'; -export type {default as UpdateWelcomeMessageParams} from './UpdateWelcomeMessageParams'; +export type {default as UpdateRoomDescriptionParams} from './UpdateRoomDescriptionParams'; export type {default as UpdateReportWriteCapabilityParams} from './UpdateReportWriteCapabilityParams'; export type {default as AddWorkspaceRoomParams} from './AddWorkspaceRoomParams'; export type {default as UpdatePolicyRoomNameParams} from './UpdatePolicyRoomNameParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index c011fa395f0f..7e6a8a8e3f13 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -85,7 +85,7 @@ const WRITE_COMMANDS = { DELETE_COMMENT: 'DeleteComment', UPDATE_COMMENT: 'UpdateComment', UPDATE_REPORT_NOTIFICATION_PREFERENCE: 'UpdateReportNotificationPreference', - UPDATE_WELCOME_MESSAGE: 'UpdateWelcomeMessage', + UPDATE_ROOM_DESCRIPTION: 'UpdateRoomDescription', UPDATE_REPORT_WRITE_CAPABILITY: 'UpdateReportWriteCapability', ADD_WORKSPACE_ROOM: 'AddWorkspaceRoom', UPDATE_POLICY_ROOM_NAME: 'UpdatePolicyRoomName', @@ -196,7 +196,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.DELETE_COMMENT]: Parameters.DeleteCommentParams; [WRITE_COMMANDS.UPDATE_COMMENT]: Parameters.UpdateCommentParams; [WRITE_COMMANDS.UPDATE_REPORT_NOTIFICATION_PREFERENCE]: Parameters.UpdateReportNotificationPreferenceParams; - [WRITE_COMMANDS.UPDATE_WELCOME_MESSAGE]: Parameters.UpdateWelcomeMessageParams; + [WRITE_COMMANDS.UPDATE_ROOM_DESCRIPTION]: Parameters.UpdateRoomDescriptionParams; [WRITE_COMMANDS.UPDATE_REPORT_WRITE_CAPABILITY]: Parameters.UpdateReportWriteCapabilityParams; [WRITE_COMMANDS.ADD_WORKSPACE_ROOM]: Parameters.AddWorkspaceRoomParams; [WRITE_COMMANDS.UPDATE_POLICY_ROOM_NAME]: Parameters.UpdatePolicyRoomNameParams; diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index 8753c1e277f9..110c13fa07bf 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -17,9 +17,9 @@ import type { ProfileNavigatorParamList, ReferralDetailsNavigatorParamList, ReimbursementAccountNavigatorParamList, + ReportDescriptionNavigatorParamList, ReportDetailsNavigatorParamList, ReportSettingsNavigatorParamList, - ReportWelcomeMessageNavigatorParamList, RoomInviteNavigatorParamList, RoomMembersNavigatorParamList, SearchNavigatorParamList, @@ -138,12 +138,11 @@ const ReportSettingsModalStackNavigator = createModalStackNavigator({ [SCREENS.TASK.TITLE]: () => require('../../../pages/tasks/TaskTitlePage').default as React.ComponentType, - [SCREENS.TASK.DESCRIPTION]: () => require('../../../pages/tasks/TaskDescriptionPage').default as React.ComponentType, [SCREENS.TASK.ASSIGNEE]: () => require('../../../pages/tasks/TaskAssigneeSelectorModal').default as React.ComponentType, }); -const ReportWelcomeMessageModalStackNavigator = createModalStackNavigator({ - [SCREENS.REPORT_WELCOME_MESSAGE_ROOT]: () => require('../../../pages/ReportWelcomeMessagePage').default as React.ComponentType, +const ReportDescriptionModalStackNavigator = createModalStackNavigator({ + [SCREENS.REPORT_DESCRIPTION_ROOT]: () => require('../../../pages/ReportDescriptionPage').default as React.ComponentType, }); const ReportParticipantsModalStackNavigator = createModalStackNavigator({ @@ -308,7 +307,7 @@ export { ReportDetailsModalStackNavigator, ReportParticipantsModalStackNavigator, ReportSettingsModalStackNavigator, - ReportWelcomeMessageModalStackNavigator, + ReportDescriptionModalStackNavigator, RoomInviteModalStackNavigator, RoomMembersModalStackNavigator, SearchModalStackNavigator, diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx index 7721a64adea9..93d2f8fba989 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx @@ -62,8 +62,8 @@ function RightModalNavigator({navigation}: RightModalNavigatorProps) { component={ModalStackNavigators.ReportSettingsModalStackNavigator} /> ['config'] = { }, }, }, - [SCREENS.RIGHT_MODAL.REPORT_WELCOME_MESSAGE]: { + [SCREENS.RIGHT_MODAL.REPORT_DESCRIPTION]: { screens: { - [SCREENS.REPORT_WELCOME_MESSAGE_ROOT]: ROUTES.REPORT_WELCOME_MESSAGE.route, + [SCREENS.REPORT_DESCRIPTION_ROOT]: ROUTES.REPORT_DESCRIPTION.route, }, }, [SCREENS.RIGHT_MODAL.NEW_CHAT]: { @@ -424,7 +424,6 @@ const config: LinkingOptions['config'] = { [SCREENS.RIGHT_MODAL.TASK_DETAILS]: { screens: { [SCREENS.TASK.TITLE]: ROUTES.TASK_TITLE.route, - [SCREENS.TASK.DESCRIPTION]: ROUTES.TASK_DESCRIPTION.route, [SCREENS.TASK.ASSIGNEE]: ROUTES.TASK_ASSIGNEE.route, }, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index d9f7197df887..48ef69f27768 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -176,8 +176,8 @@ type ReportSettingsNavigatorParamList = { [SCREENS.REPORT_SETTINGS.WRITE_CAPABILITY]: undefined; }; -type ReportWelcomeMessageNavigatorParamList = { - [SCREENS.REPORT_WELCOME_MESSAGE_ROOT]: {reportID: string}; +type ReportDescriptionNavigatorParamList = { + [SCREENS.REPORT_DESCRIPTION_ROOT]: {reportID: string}; }; type ParticipantsNavigatorParamList = { @@ -287,7 +287,6 @@ type TeachersUniteNavigatorParamList = { type TaskDetailsNavigatorParamList = { [SCREENS.TASK.TITLE]: undefined; - [SCREENS.TASK.DESCRIPTION]: undefined; [SCREENS.TASK.ASSIGNEE]: { reportID: string; }; @@ -369,7 +368,7 @@ type RightModalNavigatorParamList = { [SCREENS.RIGHT_MODAL.PROFILE]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.REPORT_DETAILS]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.REPORT_SETTINGS]: NavigatorScreenParams; - [SCREENS.RIGHT_MODAL.REPORT_WELCOME_MESSAGE]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.REPORT_DESCRIPTION]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.PARTICIPANTS]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.ROOM_MEMBERS]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.ROOM_INVITE]: NavigatorScreenParams; @@ -503,7 +502,7 @@ export type { ReportDetailsNavigatorParamList, ReportSettingsNavigatorParamList, TaskDetailsNavigatorParamList, - ReportWelcomeMessageNavigatorParamList, + ReportDescriptionNavigatorParamList, ParticipantsNavigatorParamList, RoomMembersNavigatorParamList, RoomInviteNavigatorParamList, diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 568ce49ff961..b5f567f7e5f1 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -244,7 +244,7 @@ type OptimisticChatReport = Pick< | 'stateNum' | 'statusNum' | 'visibility' - | 'welcomeMessage' + | 'description' | 'writeCapability' >; @@ -2604,6 +2604,15 @@ function getParsedComment(text: string): string { return text.length <= CONST.MAX_MARKUP_LENGTH ? parser.replace(text) : lodashEscape(text); } +function getReportDescriptionText(report: Report): string { + if (!report.description) { + return ''; + } + + const parser = new ExpensiMark(); + return parser.htmlToText(report.description); +} + function buildOptimisticAddCommentReportAction(text?: string, file?: File, actorAccountID?: number): OptimisticReportAction { const parser = new ExpensiMark(); const commentText = getParsedComment(text ?? ''); @@ -3296,7 +3305,7 @@ function buildOptimisticChatReport( notificationPreference: NotificationPreference = CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, parentReportActionID = '', parentReportID = '', - welcomeMessage = '', + description = '', ): OptimisticChatReport { const currentTime = DateUtils.getDBTime(); const isNewlyCreatedWorkspaceChat = chatType === CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT && isOwnPolicyExpenseChat; @@ -3325,7 +3334,7 @@ function buildOptimisticChatReport( stateNum: 0, statusNum: 0, visibility, - welcomeMessage, + description, writeCapability, }; } @@ -3854,7 +3863,7 @@ function canFlagReportAction(reportAction: OnyxEntry, reportID: st reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CHRONOSOOOLIST; if (ReportActionsUtils.isWhisperAction(reportAction)) { // Allow flagging welcome message whispers as they can be set by any room creator - if (report?.welcomeMessage && !isCurrentUserAction && isOriginalMessageHaveHtml && reportAction?.originalMessage?.html === report.welcomeMessage) { + if (report?.description && !isCurrentUserAction && isOriginalMessageHaveHtml && reportAction?.originalMessage?.html === report.description) { return true; } @@ -4585,10 +4594,17 @@ function getRoom(type: ValueOf, policyID: string) } /** - * We only want policy owners and admins to be able to modify the welcome message, but not in thread chat. + * We only want policy members who are members of the report to be able to modify the report description, but not in thread chat. */ -function shouldDisableWelcomeMessage(report: OnyxEntry, policy: OnyxEntry): boolean { - return isMoneyRequestReport(report) || isArchivedRoom(report) || !isChatRoom(report) || isChatThread(report) || !PolicyUtils.isPolicyAdmin(policy); +function canEditReportDescription(report: OnyxEntry, policy: OnyxEntry | undefined): boolean { + return ( + !isMoneyRequestReport(report) && + !isArchivedRoom(report) && + isChatRoom(report) && + !isChatThread(report) && + !isEmpty(policy) && + (getVisibleMemberIDs(report).includes(currentUserAccountID ?? 0) || getParticipantsIDs(report).includes(currentUserAccountID ?? 0)) + ); } /** * Checks if report action has error when smart scanning @@ -4931,9 +4947,9 @@ export { getReimbursementDeQueuedActionMessage, getPersonalDetailsForAccountID, getRoom, + canEditReportDescription, doesTransactionThreadHaveViolations, hasViolations, - shouldDisableWelcomeMessage, navigateToPrivateNotes, canEditWriteCapability, hasSmartscanError, @@ -4945,6 +4961,7 @@ export { getAllAncestorReportActions, isReportParticipant, isValidReport, + getReportDescriptionText, isReportFieldOfTypeTitle, isReportFieldDisabled, getAvailableReportFields, diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 4bff826ceb3a..5b4fb8160894 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -38,7 +38,7 @@ import type { UpdateReportNotificationPreferenceParams, UpdateReportPrivateNoteParams, UpdateReportWriteCapabilityParams, - UpdateWelcomeMessageParams, + UpdateRoomDescriptionParams, } from '@libs/API/parameters'; import {READ_COMMANDS, SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import * as CollectionUtils from '@libs/CollectionUtils'; @@ -1614,34 +1614,41 @@ function updateReportField(reportID: string, reportField: PolicyReportField, pre API.write(WRITE_COMMANDS.SET_REPORT_FIELD, parameters, {optimisticData, failureData, successData}); } -function updateWelcomeMessage(reportID: string, previousValue: string, newValue: string) { +function updateDescription(reportID: string, previousValue: string, newValue: string) { // No change needed, navigate back if (previousValue === newValue) { - Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(reportID)); + Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID)); return; } - const parsedWelcomeMessage = ReportUtils.getParsedComment(newValue); + const parsedDescription = ReportUtils.getParsedComment(newValue); const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, - value: {welcomeMessage: parsedWelcomeMessage}, + value: {description: parsedDescription, pendingFields: {description: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}, }, ]; const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, - value: {welcomeMessage: previousValue}, + value: {description: previousValue, pendingFields: {description: null}}, + }, + ]; + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: {pendingFields: {description: null}}, }, ]; - const parameters: UpdateWelcomeMessageParams = {reportID, welcomeMessage: parsedWelcomeMessage}; + const parameters: UpdateRoomDescriptionParams = {reportID, description: parsedDescription}; - API.write(WRITE_COMMANDS.UPDATE_WELCOME_MESSAGE, parameters, {optimisticData, failureData}); - Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(reportID)); + API.write(WRITE_COMMANDS.UPDATE_ROOM_DESCRIPTION, parameters, {optimisticData, failureData, successData}); + Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID)); } function updateWriteCapabilityAndNavigate(report: Report, newValue: WriteCapability) { @@ -1774,7 +1781,7 @@ function addPolicyReport(policyReport: ReportUtils.OptimisticChatReport) { reportID: policyReport.reportID, createdReportActionID: createdReportAction.reportActionID, writeCapability: policyReport.writeCapability, - welcomeMessage: policyReport.welcomeMessage, + description: policyReport.description, }; API.write(WRITE_COMMANDS.ADD_WORKSPACE_ROOM, parameters, {optimisticData, successData, failureData}); @@ -2821,7 +2828,7 @@ export { addComment, addAttachment, reconnect, - updateWelcomeMessage, + updateDescription, updateWriteCapabilityAndNavigate, updateNotificationPreference, subscribeToReportTypingEvents, diff --git a/src/libs/updateMultilineInputRange/types.ts b/src/libs/updateMultilineInputRange/types.ts index ce8f553c51f8..3646c64e4845 100644 --- a/src/libs/updateMultilineInputRange/types.ts +++ b/src/libs/updateMultilineInputRange/types.ts @@ -1,5 +1,6 @@ import type {TextInput} from 'react-native'; +import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; -type UpdateMultilineInputRange = (input: HTMLInputElement | TextInput | null, shouldAutoFocus?: boolean) => void; +type UpdateMultilineInputRange = (input: HTMLInputElement | BaseTextInputRef | TextInput | null, shouldAutoFocus?: boolean) => void; export default UpdateMultilineInputRange; diff --git a/src/pages/ReportDescriptionPage.tsx b/src/pages/ReportDescriptionPage.tsx new file mode 100644 index 000000000000..3ccabf30c1b7 --- /dev/null +++ b/src/pages/ReportDescriptionPage.tsx @@ -0,0 +1,35 @@ +import type {RouteProp} from '@react-navigation/native'; +import React from 'react'; +import type {OnyxCollection} from 'react-native-onyx'; +import * as ReportUtils from '@libs/ReportUtils'; +import type * as OnyxTypes from '@src/types/onyx'; +import withReportOrNotFound from './home/report/withReportOrNotFound'; +import RoomDescriptionPage from './RoomDescriptionPage'; +import TaskDescriptionPage from './tasks/TaskDescriptionPage'; + +type ReportDescriptionPageProps = { + /** The report currently being looked at */ + report: OnyxTypes.Report; + + /** Policy for the current report */ + policies: OnyxCollection; + + /** Route params */ + route: RouteProp<{params: {reportID: string}}>; +}; + +function ReportDescriptionPage(props: ReportDescriptionPageProps) { + const isTask = ReportUtils.isTaskReport(props.report); + + if (isTask) { + // eslint-disable-next-line react/jsx-props-no-spreading + return ; + } + + // eslint-disable-next-line react/jsx-props-no-spreading + return ; +} + +ReportDescriptionPage.displayName = 'ReportDescriptionPage'; + +export default withReportOrNotFound()(ReportDescriptionPage); diff --git a/src/pages/ReportDetailsPage.js b/src/pages/ReportDetailsPage.js index 513ccbbe307c..99e1cea8280a 100644 --- a/src/pages/ReportDetailsPage.js +++ b/src/pages/ReportDetailsPage.js @@ -8,7 +8,9 @@ import DisplayNames from '@components/DisplayNames'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; import MenuItem from '@components/MenuItem'; +import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import MultipleAvatars from '@components/MultipleAvatars'; +import OfflineWithFeedback from '@components/OfflineWithFeedback'; import {withNetwork} from '@components/OnyxProvider'; import ParentNavigationSubtitle from '@components/ParentNavigationSubtitle'; import participantPropTypes from '@components/participantPropTypes'; @@ -69,6 +71,8 @@ function ReportDetailsPage(props) { const isUserCreatedPolicyRoom = useMemo(() => ReportUtils.isUserCreatedPolicyRoom(props.report), [props.report]); const isArchivedRoom = useMemo(() => ReportUtils.isArchivedRoom(props.report), [props.report]); const isMoneyRequestReport = useMemo(() => ReportUtils.isMoneyRequestReport(props.report), [props.report]); + const canEditReportDescription = useMemo(() => ReportUtils.canEditReportDescription(props.report, policy), [props.report, policy]); + const shouldShowReportDescription = isChatRoom && (canEditReportDescription || !_.isEmpty(props.report.description)); // 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(props.report), [props.report, policy]); @@ -238,6 +242,19 @@ function ReportDetailsPage(props) { )} + {shouldShowReportDescription && ( + + Navigation.navigate(ROUTES.REPORT_DESCRIPTION.getRoute(props.report.reportID))} + /> + + )} {_.map(menuItems, (item) => { const brickRoadIndicator = ReportUtils.hasReportNameError(props.report) && item.key === CONST.REPORT_DETAILS_MENU_ITEM.SETTINGS ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''; diff --git a/src/pages/ReportWelcomeMessagePage.tsx b/src/pages/ReportWelcomeMessagePage.tsx deleted file mode 100644 index 53f3e7fcadda..000000000000 --- a/src/pages/ReportWelcomeMessagePage.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import {useFocusEffect} from '@react-navigation/native'; -import type {StackScreenProps} from '@react-navigation/stack'; -import ExpensiMark from 'expensify-common/lib/ExpensiMark'; -import React, {useCallback, useRef, useState} from 'react'; -import {View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; -import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; -import FormProvider from '@components/Form/FormProvider'; -import InputWrapper from '@components/Form/InputWrapper'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import type {AnimatedTextInputRef} from '@components/RNTextInput'; -import ScreenWrapper from '@components/ScreenWrapper'; -import Text from '@components/Text'; -import TextInput from '@components/TextInput'; -import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; -import Navigation from '@libs/Navigation/Navigation'; -import * as ReportUtils from '@libs/ReportUtils'; -import updateMultilineInputRange from '@libs/updateMultilineInputRange'; -import type {ReportWelcomeMessageNavigatorParamList} from '@navigation/types'; -import * as Report from '@userActions/Report'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type SCREENS from '@src/SCREENS'; -import type {Policy} from '@src/types/onyx'; -import type {WithReportOrNotFoundProps} from './home/report/withReportOrNotFound'; -import withReportOrNotFound from './home/report/withReportOrNotFound'; - -type ReportWelcomeMessagePageOnyxProps = { - /** The policy object for the current route */ - policy: OnyxEntry; -}; - -type ReportWelcomeMessagePageProps = ReportWelcomeMessagePageOnyxProps & - WithReportOrNotFoundProps & - StackScreenProps; - -function ReportWelcomeMessagePage({report, policy}: ReportWelcomeMessagePageProps) { - const styles = useThemeStyles(); - const {translate} = useLocalize(); - - const parser = new ExpensiMark(); - const [welcomeMessage, setWelcomeMessage] = useState(() => parser.htmlToMarkdown(report?.welcomeMessage ?? '')); - const welcomeMessageInputRef = useRef(null); - const focusTimeoutRef = useRef(null); - - const handleWelcomeMessageChange = useCallback((value: string) => { - setWelcomeMessage(value); - }, []); - - const submitForm = useCallback(() => { - Report.updateWelcomeMessage(report?.reportID ?? '', report?.welcomeMessage ?? '', welcomeMessage.trim()); - }, [report?.reportID, report?.welcomeMessage, welcomeMessage]); - - useFocusEffect( - useCallback(() => { - focusTimeoutRef.current = setTimeout(() => { - if (welcomeMessageInputRef.current) { - welcomeMessageInputRef.current.focus(); - } - return () => { - if (!focusTimeoutRef.current) { - return; - } - clearTimeout(focusTimeoutRef.current); - }; - }, CONST.ANIMATED_TRANSITION); - }, []), - ); - - return ( - - - Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(report?.reportID ?? ''))} - /> - - {translate('welcomeMessagePage.explainerText')} - - { - if (!element) { - return; - } - welcomeMessageInputRef.current = element; - updateMultilineInputRange(welcomeMessageInputRef.current); - }} - value={welcomeMessage} - onChangeText={handleWelcomeMessageChange} - autoCapitalize="none" - containerStyles={[styles.autoGrowHeightMultilineInput]} - /> - - - - - ); -} - -ReportWelcomeMessagePage.displayName = 'ReportWelcomeMessagePage'; - -export default withReportOrNotFound()( - withOnyx({ - policy: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`, - }, - })(ReportWelcomeMessagePage), -); diff --git a/src/pages/RoomDescriptionPage.tsx b/src/pages/RoomDescriptionPage.tsx new file mode 100644 index 000000000000..bc46587814e3 --- /dev/null +++ b/src/pages/RoomDescriptionPage.tsx @@ -0,0 +1,113 @@ +import {useFocusEffect} from '@react-navigation/native'; +import ExpensiMark from 'expensify-common/lib/ExpensiMark'; +import React, {useCallback, useRef, useState} from 'react'; +import {View} from 'react-native'; +import type {OnyxCollection} from 'react-native-onyx'; +import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; +import FormProvider from '@components/Form/FormProvider'; +import InputWrapper from '@components/Form/InputWrapper'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import Text from '@components/Text'; +import TextInput from '@components/TextInput'; +import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@libs/Navigation/Navigation'; +import * as ReportUtils from '@libs/ReportUtils'; +import updateMultilineInputRange from '@libs/updateMultilineInputRange'; +import * as Report from '@userActions/Report'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type * as OnyxTypes from '@src/types/onyx'; + +type RoomDescriptionPageProps = { + /** Policy for the current report */ + policies: OnyxCollection; + + /** The report currently being looked at */ + report: OnyxTypes.Report; +}; + +function RoomDescriptionPage({report, policies}: RoomDescriptionPageProps) { + const styles = useThemeStyles(); + const parser = new ExpensiMark(); + const [description, setDescription] = useState(() => parser.htmlToMarkdown(report?.description ?? '')); + const reportDescriptionInputRef = useRef(null); + const focusTimeoutRef = useRef | null>(null); + const {translate} = useLocalize(); + const policy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]; + + const handleReportDescriptionChange = useCallback((value: string) => { + setDescription(value); + }, []); + + const submitForm = useCallback(() => { + Report.updateDescription(report.reportID, report?.description ?? '', description.trim()); + }, [report.reportID, report.description, description]); + + useFocusEffect( + useCallback(() => { + focusTimeoutRef.current = setTimeout(() => { + reportDescriptionInputRef.current?.focus(); + return () => { + if (!focusTimeoutRef.current) { + return; + } + clearTimeout(focusTimeoutRef.current); + }; + }, CONST.ANIMATED_TRANSITION); + }, []), + ); + + return ( + + + Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID))} + /> + + {translate('reportDescriptionPage.explainerText')} + + { + if (!el) { + return; + } + reportDescriptionInputRef.current = el; + updateMultilineInputRange(el); + }} + value={description} + onChangeText={handleReportDescriptionChange} + autoCapitalize="none" + containerStyles={[styles.autoGrowHeightMultilineInput]} + /> + + + + + ); +} + +RoomDescriptionPage.displayName = 'RoomDescriptionPage'; + +export default RoomDescriptionPage; diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index e3185eea2731..7b299a18a030 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -27,6 +27,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import {getGroupChatName} from '@libs/GroupChatUtils'; import * as HeaderUtils from '@libs/HeaderUtils'; +import Navigation from '@libs/Navigation/Navigation'; import reportWithoutHasDraftSelector from '@libs/OnyxSelectors/reportWithoutHasDraftSelector'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; @@ -38,6 +39,7 @@ 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'; const propTypes = { /** Toggles the navigationMenu open and closed */ @@ -112,6 +114,8 @@ function HeaderView(props) { const isPolicyMember = useMemo(() => !_.isEmpty(props.policy), [props.policy]); const canLeaveRoom = ReportUtils.canLeaveRoom(props.report, isPolicyMember); const isArchivedRoom = ReportUtils.isArchivedRoom(props.report); + const reportDescription = ReportUtils.getReportDescriptionText(props.report); + const policyName = ReportUtils.getPolicyName(props.report); // We hide the button when we are chatting with an automated Expensify account since it's not possible to contact // these users via alternative means. It is possible to request a call with Concierge so we leave the option for them. @@ -176,6 +180,18 @@ function HeaderView(props) { /> ); + const renderAdditionalText = () => { + if (_.isEmpty(policyName) || _.isEmpty(reportDescription) || !_.isEmpty(parentNavigationSubtitleData)) { + return null; + } + return ( + <> + {translate('threads.in')} + {policyName} + + ); + }; + threeDotMenuItems.push(HeaderUtils.getPinMenuItem(props.report)); if (isConcierge && props.guideCalendarLink) { @@ -274,6 +290,7 @@ function HeaderView(props) { numberOfLines={1} textStyles={[styles.headerText, styles.pre]} shouldUseFullTitle={isChatRoom || isPolicyExpenseChat || isChatThread || isTaskReport} + renderAdditionalText={renderAdditionalText} /> {!_.isEmpty(parentNavigationSubtitleData) && ( )} - {!_.isEmpty(subtitle) && ( + {!_.isEmpty(subtitle) && _.isEmpty(reportDescription) && ( )} + {!_.isEmpty(reportDescription) && _.isEmpty(parentNavigationSubtitleData) && ( + { + if (ReportUtils.canEditReportDescription(props.report, props.policy)) { + Navigation.navigate(ROUTES.REPORT_DESCRIPTION.getRoute(props.reportID)); + return; + } + Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(props.reportID)); + }} + style={[styles.alignSelfStart, styles.mw100]} + accessibilityLabel={translate('reportDescriptionPage.roomDescription')} + > + + {reportDescription} + + + )} {brickRoadIndicator === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR && ( diff --git a/src/pages/home/report/ReportActionItemCreated.tsx b/src/pages/home/report/ReportActionItemCreated.tsx index f8345ca7d2d0..afe97b2b95c1 100644 --- a/src/pages/home/report/ReportActionItemCreated.tsx +++ b/src/pages/home/report/ReportActionItemCreated.tsx @@ -116,6 +116,7 @@ export default withOnyx; + + /** The report currently being looked at */ + report: OnyxTypes.Report; }; export default function ( diff --git a/src/pages/settings/Report/ReportSettingsPage.tsx b/src/pages/settings/Report/ReportSettingsPage.tsx index c1839b44553d..613dcd460e26 100644 --- a/src/pages/settings/Report/ReportSettingsPage.tsx +++ b/src/pages/settings/Report/ReportSettingsPage.tsx @@ -4,8 +4,6 @@ import {ScrollView, View} from 'react-native'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import DisplayNames from '@components/DisplayNames'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import * as Expensicons from '@components/Icon/Expensicons'; -import MenuItem from '@components/MenuItem'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -35,9 +33,6 @@ function ReportSettingsPage({report, policies}: ReportSettingsPageProps) { const shouldDisableRename = useMemo(() => ReportUtils.shouldDisableRename(report, linkedWorkspace), [report, linkedWorkspace]); const isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report); - // We only want policy owners and admins to be able to modify the welcome message, but not in thread chat - const shouldDisableWelcomeMessage = ReportUtils.shouldDisableWelcomeMessage(report, linkedWorkspace); - const shouldDisableSettings = isEmptyObject(report) || ReportUtils.isArchivedRoom(report); const shouldShowRoomName = !ReportUtils.isPolicyExpenseChat(report) && !ReportUtils.isChatThread(report); const notificationPreference = @@ -164,14 +159,6 @@ function ReportSettingsPage({report, policies}: ReportSettingsPageProps) { )} - {!shouldDisableWelcomeMessage && ( - Navigation.navigate(ROUTES.REPORT_WELCOME_MESSAGE.getRoute(reportID))} - shouldShowRightIcon - /> - )} diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index b616b519ff32..b32637e8e219 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -133,7 +133,7 @@ function WorkspaceNewRoomPage(props) { */ const submit = (values) => { const participants = [props.session.accountID]; - const parsedWelcomeMessage = ReportUtils.getParsedComment(values.welcomeMessage); + const parsedDescription = ReportUtils.getParsedComment(values.reportDescription); const policyReport = ReportUtils.buildOptimisticChatReport( participants, values.roomName, @@ -147,7 +147,7 @@ function WorkspaceNewRoomPage(props) { CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, '', '', - parsedWelcomeMessage, + parsedDescription, ); setNewRoomReportID(policyReport.reportID); Report.addPolicyReport(policyReport); @@ -289,6 +289,7 @@ function WorkspaceNewRoomPage(props) { validate={validate} onSubmit={submit} enabledWhenOffline + disablePressOnEnter={false} > diff --git a/src/styles/index.ts b/src/styles/index.ts index 0d4b420c00e4..2e16f1dbd7af 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -415,6 +415,10 @@ const styles = (theme: ThemeColors) => fontWeight: FontUtils.fontWeight.bold, }, + fontWeightNormal: { + fontWeight: FontUtils.fontWeight.normal, + }, + textHeadline: { ...headlineFont, ...whiteSpace.preWrap, @@ -1815,6 +1819,12 @@ const styles = (theme: ThemeColors) => ...wordBreak.breakWord, }, + renderHTML: { + maxWidth: '100%', + ...whiteSpace.preWrap, + ...wordBreak.breakWord, + }, + chatItemComposeWithFirstRow: { minHeight: 90, }, diff --git a/src/styles/utils/FontUtils/index.ts b/src/styles/utils/FontUtils/index.ts index ac07fdbf026e..b93655fdf63d 100644 --- a/src/styles/utils/FontUtils/index.ts +++ b/src/styles/utils/FontUtils/index.ts @@ -11,6 +11,7 @@ const FontUtils = { }, fontWeight: { bold: fontWeightBold, + normal: '400', }, }; diff --git a/src/types/onyx/Form.ts b/src/types/onyx/Form.ts index a73f8d4c9732..6938e17163d2 100644 --- a/src/types/onyx/Form.ts +++ b/src/types/onyx/Form.ts @@ -33,7 +33,7 @@ type DisplayNameForm = Form<{ type NewRoomForm = Form<{ roomName?: string; - welcomeMessage?: string; + reportDescription?: string; policyID?: string; writeCapability?: string; visibility?: string; diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index d26bdd4f282e..e392cb23384a 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -121,7 +121,6 @@ type Report = { lastVisibleActionLastModified?: string; displayName?: string; lastMessageHtml?: string; - welcomeMessage?: string; lastActorAccountID?: number; ownerAccountID?: number; ownerEmail?: string; diff --git a/tests/ui/UnreadIndicatorsTest.js b/tests/ui/UnreadIndicatorsTest.js index e4d4d877f66b..9bf5d9ef49e4 100644 --- a/tests/ui/UnreadIndicatorsTest.js +++ b/tests/ui/UnreadIndicatorsTest.js @@ -438,11 +438,11 @@ describe('Unread Indicators', () => { expect(displayNameTexts).toHaveLength(2); const firstReportOption = displayNameTexts[0]; expect(lodashGet(firstReportOption, ['props', 'style', 'fontWeight'])).toBe(FontUtils.fontWeight.bold); - expect(lodashGet(firstReportOption, ['props', 'children'])).toBe('C User'); + expect(lodashGet(firstReportOption, ['props', 'children', 0])).toBe('C User'); const secondReportOption = displayNameTexts[1]; expect(lodashGet(secondReportOption, ['props', 'style', 'fontWeight'])).toBe(FontUtils.fontWeight.bold); - expect(lodashGet(secondReportOption, ['props', 'children'])).toBe('B User'); + expect(lodashGet(secondReportOption, ['props', 'children', 0])).toBe('B User'); // Tap the new report option and navigate back to the sidebar again via the back button return navigateToSidebarOption(0); @@ -455,9 +455,9 @@ describe('Unread Indicators', () => { const displayNameTexts = screen.queryAllByLabelText(hintText); expect(displayNameTexts).toHaveLength(2); expect(lodashGet(displayNameTexts[0], ['props', 'style', 'fontWeight'])).toBe(undefined); - expect(lodashGet(displayNameTexts[0], ['props', 'children'])).toBe('C User'); + expect(lodashGet(displayNameTexts[0], ['props', 'children', 0])).toBe('C User'); expect(lodashGet(displayNameTexts[1], ['props', 'style', 'fontWeight'])).toBe(FontUtils.fontWeight.bold); - expect(lodashGet(displayNameTexts[1], ['props', 'children'])).toBe('B User'); + expect(lodashGet(displayNameTexts[1], ['props', 'children', 0])).toBe('B User'); })); xit('Manually marking a chat message as unread shows the new line indicator and updates the LHN', () => @@ -489,7 +489,7 @@ describe('Unread Indicators', () => { const displayNameTexts = screen.queryAllByLabelText(hintText); expect(displayNameTexts).toHaveLength(1); expect(lodashGet(displayNameTexts[0], ['props', 'style', 'fontWeight'])).toBe(FontUtils.fontWeight.bold); - expect(lodashGet(displayNameTexts[0], ['props', 'children'])).toBe('B User'); + expect(lodashGet(displayNameTexts[0], ['props', 'children', 0])).toBe('B User'); // Navigate to the report again and back to the sidebar return navigateToSidebarOption(0); @@ -501,7 +501,7 @@ describe('Unread Indicators', () => { const displayNameTexts = screen.queryAllByLabelText(hintText); expect(displayNameTexts).toHaveLength(1); expect(lodashGet(displayNameTexts[0], ['props', 'style', 'fontWeight'])).toBe(undefined); - expect(lodashGet(displayNameTexts[0], ['props', 'children'])).toBe('B User'); + expect(lodashGet(displayNameTexts[0], ['props', 'children', 0])).toBe('B User'); // Navigate to the report again and verify the new line indicator is missing return navigateToSidebarOption(0); diff --git a/tests/unit/SidebarFilterTest.js b/tests/unit/SidebarFilterTest.js index 55840ad24b6a..148710cb2d25 100644 --- a/tests/unit/SidebarFilterTest.js +++ b/tests/unit/SidebarFilterTest.js @@ -339,7 +339,7 @@ xdescribe('Sidebar', () => { const navigatesToChatHintText = Localize.translateLocal('accessibilityHints.navigatesToChat'); expect(screen.queryAllByAccessibilityHint(navigatesToChatHintText)).toHaveLength(1); expect(displayNames).toHaveLength(1); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Three, Four'); } else { // Both reports visible const navigatesToChatHintText = Localize.translateLocal('accessibilityHints.navigatesToChat'); @@ -380,8 +380,8 @@ xdescribe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(2); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('One, Two'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('One, Two'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('Three, Four'); }) // When report3 becomes unread @@ -450,8 +450,8 @@ xdescribe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(2); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Three, Four'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('One, Two'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Three, Four'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('One, Two'); }) ); }); @@ -663,7 +663,7 @@ xdescribe('Sidebar', () => { const navigatesToChatHintText = Localize.translateLocal('accessibilityHints.navigatesToChat'); expect(screen.queryAllByAccessibilityHint(navigatesToChatHintText)).toHaveLength(1); expect(displayNames).toHaveLength(1); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Three, Four'); } else { // Both reports visible const navigatesToChatHintText = Localize.translateLocal('accessibilityHints.navigatesToChat'); diff --git a/tests/unit/SidebarOrderTest.js b/tests/unit/SidebarOrderTest.js index ed0f210d1da6..7ae8c4e1e9b3 100644 --- a/tests/unit/SidebarOrderTest.js +++ b/tests/unit/SidebarOrderTest.js @@ -140,9 +140,9 @@ describe('Sidebar', () => { const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(3); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Three, Four'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('One, Two'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('Three, Four'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('One, Two'); }) ); }); @@ -189,9 +189,9 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(3); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('One, Two'); // this has `hasDraft` flag enabled so it will be on top - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('One, Two'); // this has `hasDraft` flag enabled so it will be on top + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Three, Four'); }) ); }); @@ -236,9 +236,9 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(3); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('One, Two'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('One, Two'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Three, Four'); }) ); }); @@ -286,10 +286,10 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(4); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe(taskReportName); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four'); - expect(lodashGet(displayNames, [3, 'props', 'children'])).toBe('One, Two'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe(taskReportName); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Three, Four'); + expect(lodashGet(displayNames, [3, 'props', 'children', 0])).toBe('One, Two'); }) ); }); @@ -346,10 +346,10 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(4); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Email Two owes $100.00'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four'); - expect(lodashGet(displayNames, [3, 'props', 'children'])).toBe('One, Two'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Email Two owes $100.00'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Three, Four'); + expect(lodashGet(displayNames, [3, 'props', 'children', 0])).toBe('One, Two'); }) ); }); @@ -410,10 +410,10 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(4); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Workspace owes $100.00'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Email Five'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four'); - expect(lodashGet(displayNames, [3, 'props', 'children'])).toBe('One, Two'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Workspace owes $100.00'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('Email Five'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Three, Four'); + expect(lodashGet(displayNames, [3, 'props', 'children', 0])).toBe('One, Two'); }) ); }); @@ -465,9 +465,9 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(3); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Three, Four'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('One, Two'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Three, Four'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('One, Two'); }) ); }); @@ -607,9 +607,9 @@ describe('Sidebar', () => { expect(displayNames).toHaveLength(3); expect(screen.queryAllByTestId('Pin Icon')).toHaveLength(1); expect(screen.queryAllByTestId('Pencil Icon')).toHaveLength(1); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Email Two owes $100.00'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('One, Two'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Email Two owes $100.00'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('One, Two'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Three, Four'); }) ); }); @@ -653,9 +653,9 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(3); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('One, Two'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('One, Two'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Three, Four'); }) // When a new report is added @@ -666,10 +666,10 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(4); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('One, Two'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Seven, Eight'); - expect(lodashGet(displayNames, [3, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('One, Two'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Seven, Eight'); + expect(lodashGet(displayNames, [3, 'props', 'children', 0])).toBe('Three, Four'); }) ); }); @@ -713,9 +713,9 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(3); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('One, Two'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('One, Two'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Three, Four'); }) // When a new report is added @@ -726,10 +726,10 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(4); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('One, Two'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Seven, Eight'); - expect(lodashGet(displayNames, [3, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('One, Two'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Seven, Eight'); + expect(lodashGet(displayNames, [3, 'props', 'children', 0])).toBe('Three, Four'); }) ); }); @@ -773,9 +773,9 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(3); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Three, Four'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Report (archived)'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('Three, Four'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Report (archived)'); }) ); }); @@ -810,9 +810,9 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(3); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('One, Two'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('One, Two'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Three, Four'); }) // When a new report is added @@ -823,10 +823,10 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(4); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('One, Two'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Seven, Eight'); - expect(lodashGet(displayNames, [3, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('One, Two'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Seven, Eight'); + expect(lodashGet(displayNames, [3, 'props', 'children', 0])).toBe('Three, Four'); }) ); }); @@ -865,9 +865,9 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(3); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Three, Four'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Report (archived)'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('Three, Four'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Report (archived)'); }) ); }); @@ -1000,11 +1000,11 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(5); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Email Five owes $100.00'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('Email Four owes $1,000.00'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Email Six owes $100.00'); - expect(lodashGet(displayNames, [3, 'props', 'children'])).toBe('Email Three owes $100.00'); - expect(lodashGet(displayNames, [4, 'props', 'children'])).toBe('Email Two owes $100.00'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Email Five owes $100.00'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('Email Four owes $1,000.00'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Email Six owes $100.00'); + expect(lodashGet(displayNames, [3, 'props', 'children', 0])).toBe('Email Three owes $100.00'); + expect(lodashGet(displayNames, [4, 'props', 'children', 0])).toBe('Email Two owes $100.00'); }) ); }); @@ -1050,9 +1050,9 @@ describe('Sidebar', () => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); expect(displayNames).toHaveLength(3); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Five, Six'); - expect(lodashGet(displayNames, [1, 'props', 'children'])).toBe('One, Two'); - expect(lodashGet(displayNames, [2, 'props', 'children'])).toBe('Three, Four'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Five, Six'); + expect(lodashGet(displayNames, [1, 'props', 'children', 0])).toBe('One, Two'); + expect(lodashGet(displayNames, [2, 'props', 'children', 0])).toBe('Three, Four'); }) ); }); diff --git a/tests/unit/SidebarTest.js b/tests/unit/SidebarTest.js index dba1365626ba..6a813ef1fa8c 100644 --- a/tests/unit/SidebarTest.js +++ b/tests/unit/SidebarTest.js @@ -83,7 +83,7 @@ describe('Sidebar', () => { .then(() => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Report (archived)'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Report (archived)'); const hintMessagePreviewText = Localize.translateLocal('accessibilityHints.lastChatMessagePreview'); const messagePreviewTexts = screen.queryAllByLabelText(hintMessagePreviewText); @@ -127,7 +127,7 @@ describe('Sidebar', () => { .then(() => { const hintText = Localize.translateLocal('accessibilityHints.chatUserDisplayNames'); const displayNames = screen.queryAllByLabelText(hintText); - expect(lodashGet(displayNames, [0, 'props', 'children'])).toBe('Report (archived)'); + expect(lodashGet(displayNames, [0, 'props', 'children', 0])).toBe('Report (archived)'); const hintMessagePreviewText = Localize.translateLocal('accessibilityHints.lastChatMessagePreview'); const messagePreviewTexts = screen.queryAllByLabelText(hintMessagePreviewText);