diff --git a/webapp/channels/src/components/custom_status/custom_status_modal.tsx b/webapp/channels/src/components/custom_status/custom_status_modal.tsx index 8106c51484..8852a20c96 100644 --- a/webapp/channels/src/components/custom_status/custom_status_modal.tsx +++ b/webapp/channels/src/components/custom_status/custom_status_modal.tsx @@ -138,13 +138,13 @@ const CustomStatusModal: React.FC = (props: Props) => { initialCustomExpiryTime = moment(currentCustomStatus.expires_at); } const [customExpiryTime, setCustomExpiryTime] = useState(initialCustomExpiryTime); - const [isDatePickerOpen, setIsDatePickerOpen] = useState(false); + const [isInteracting, setIsInteracting] = useState(false); const handleKeyDown = useCallback((event: KeyboardEvent) => { - if (isKeyPressed(event, Constants.KeyCodes.ESCAPE) && !isDatePickerOpen) { + if (isKeyPressed(event, Constants.KeyCodes.ESCAPE) && !isInteracting) { props.onExited(); } - }, [isDatePickerOpen, props.onExited]); + }, [isInteracting, props.onExited]); useEffect(() => { document.addEventListener('keydown', handleKeyDown); @@ -180,9 +180,13 @@ const CustomStatusModal: React.FC = (props: Props) => { if (inCustomEmojiPath) { dispatch(closeModal(ModalIdentifiers.CUSTOM_STATUS)); } - }, [inCustomEmojiPath]); + }, [dispatch, inCustomEmojiPath]); const handleSetStatus = () => { + if (isInteracting) { + return; + } + const expiresAt = calculateExpiryTime(); const customStatus: UserCustomStatus = { emoji: emoji || 'speech_balloon', @@ -193,8 +197,15 @@ const CustomStatusModal: React.FC = (props: Props) => { customStatus.expires_at = expiresAt; } dispatch(setCustomStatus(customStatus)); + dispatch(closeModal(ModalIdentifiers.CUSTOM_STATUS)); }; + const handleEnterKeyPressed = useCallback(() => { + if (!isInteracting) { + handleSetStatus(); + } + }, [isInteracting, handleSetStatus]); + const calculateExpiryTime = (): string => { switch (duration) { case DONT_CLEAR: @@ -404,12 +415,13 @@ const CustomStatusModal: React.FC = (props: Props) => { id='custom_status_modal' className={'StatusModal'} handleConfirm={handleSetStatus} - handleEnterKeyPress={handleSetStatus} + handleEnterKeyPress={handleEnterKeyPressed} handleCancel={handleClearStatus} confirmButtonClassName='btn btn-primary' ariaLabel={formatMessage({id: 'custom_status.set_status', defaultMessage: 'Set a status'})} keyboardEscape={false} tabIndex={-1} + autoCloseOnConfirmButton={false} >
@@ -469,7 +481,7 @@ const CustomStatusModal: React.FC = (props: Props) => { time={customExpiryTime} handleChange={setCustomExpiryTime} timezone={timezone} - setIsDatePickerOpen={setIsDatePickerOpen} + setIsInteracting={setIsInteracting} /> )}
diff --git a/webapp/channels/src/components/custom_status/date_time_input.tsx b/webapp/channels/src/components/custom_status/date_time_input.tsx index 1584a36226..a1b680cd46 100644 --- a/webapp/channels/src/components/custom_status/date_time_input.tsx +++ b/webapp/channels/src/components/custom_status/date_time_input.tsx @@ -23,8 +23,8 @@ import Input from 'components/widgets/inputs/input/input'; import Menu from 'components/widgets/menu/menu'; import MenuWrapper from 'components/widgets/menu/menu_wrapper'; -import type {A11yFocusEventDetail} from 'utils/constants'; import Constants, {A11yCustomEventTypes} from 'utils/constants'; +import type {A11yFocusEventDetail} from 'utils/constants'; import {relativeFormatDate} from 'utils/datetime'; import {isKeyPressed} from 'utils/keyboard'; import {getCurrentMomentForTimezone} from 'utils/timezone'; @@ -66,14 +66,20 @@ type Props = { time: Moment; handleChange: (date: Moment) => void; timezone?: string; - setIsDatePickerOpen?: (isDatePickerOpen: boolean) => void; + setIsInteracting?: (interacting: boolean) => void; relativeDate?: boolean; timePickerInterval?: number; } -const DateTimeInputContainer: React.FC = (props: Props) => { +const DateTimeInputContainer: React.FC = ({ + time, + handleChange, + timezone, + setIsInteracting, + relativeDate, + timePickerInterval, +}: Props) => { const locale = useSelector(getCurrentLocale); - const {time, handleChange, timezone} = props; const [timeOptions, setTimeOptions] = useState([]); const [isPopperOpen, setIsPopperOpen] = useState(false); const {formatMessage} = useIntl(); @@ -82,8 +88,8 @@ const DateTimeInputContainer: React.FC = (props: Props) => { const handlePopperOpenState = useCallback((isOpen: boolean) => { setIsPopperOpen(isOpen); - props.setIsDatePickerOpen?.(isOpen); - }, []); + setIsInteracting?.(isOpen); + }, [setIsInteracting]); const handleKeyDown = useCallback((event: KeyboardEvent) => { if (isKeyPressed(event, Constants.KeyCodes.ESCAPE) && isPopperOpen) { @@ -103,9 +109,9 @@ const DateTimeInputContainer: React.FC = (props: Props) => { const currentTime = getCurrentMomentForTimezone(timezone); let startTime = moment(time).startOf('day'); if (currentTime.isSame(time, 'date')) { - startTime = getRoundedTime(currentTime, props.timePickerInterval); + startTime = getRoundedTime(currentTime, timePickerInterval); } - setTimeOptions(getTimeInIntervals(startTime, props.timePickerInterval)); + setTimeOptions(getTimeInIntervals(startTime, timePickerInterval)); }; useEffect(setTimeAndOptions, [time]); @@ -113,7 +119,7 @@ const DateTimeInputContainer: React.FC = (props: Props) => { const handleDayChange = (day: Date, modifiers: DayModifiers) => { if (modifiers.today) { const currentTime = getCurrentMomentForTimezone(timezone); - const roundedTime = getRoundedTime(currentTime, props.timePickerInterval); + const roundedTime = getRoundedTime(currentTime, timePickerInterval); handleChange(roundedTime); } else { const dayWithTimezone = timezone ? moment(day).tz(timezone, true) : moment(day); @@ -142,7 +148,7 @@ const DateTimeInputContainer: React.FC = (props: Props) => { }, []); const formatDate = (date: Moment): string => { - return props.relativeDate ? relativeFormatDate(date, formatMessage, DATE_FORMAT) : DateTime.fromJSDate(date.toDate()).toFormat(DATE_FORMAT); + return relativeDate ? relativeFormatDate(date, formatMessage, DATE_FORMAT) : DateTime.fromJSDate(date.toDate()).toFormat(DATE_FORMAT); }; const inputIcon = ( @@ -192,6 +198,7 @@ const DateTimeInputContainer: React.FC = (props: Props) => {