From c98f2e75fb12bd81168d4dae6983d5a7792ecfdf Mon Sep 17 00:00:00 2001 From: Harshil Sharma <18575143+harshilsharma63@users.noreply.github.com> Date: Thu, 21 Nov 2024 13:30:34 +0530 Subject: [PATCH] Scheduled post option bot time exclusion (#29330) * Not displaying users timezone if user is a bot * Added test * Added the case of dm with self --- .../core_menu_options.test.tsx | 36 ++++++++++++++ .../send_post_options/core_menu_options.tsx | 4 +- .../use_post_box_indicator.tsx | 48 +++++++++++-------- 3 files changed, 67 insertions(+), 21 deletions(-) diff --git a/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.test.tsx b/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.test.tsx index 465b3885b8..3e9f565b0c 100644 --- a/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.test.tsx +++ b/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.test.tsx @@ -64,6 +64,8 @@ describe('CoreMenuOptions Component', () => { mockedUseTimePostBoxIndicator.mockReturnValue({ ...defaultUseTimePostBoxIndicatorReturnValue, isDM: false, + isSelfDM: false, + isBot: false, }); }); @@ -120,6 +122,8 @@ describe('CoreMenuOptions Component', () => { mockedUseTimePostBoxIndicator.mockReturnValue({ ...defaultUseTimePostBoxIndicatorReturnValue, isDM: true, + isSelfDM: false, + isBot: false, }); renderComponent(); @@ -152,4 +156,36 @@ describe('CoreMenuOptions Component', () => { expect(handleOnSelect).toHaveBeenCalledWith(expect.anything(), expectedTimestamp); }); + + it('should NOT include trailing element when isDM and isBot are true', () => { + setMockDate(2); // Tuesday + + mockedUseTimePostBoxIndicator.mockReturnValue({ + ...defaultUseTimePostBoxIndicatorReturnValue, + isDM: true, + isSelfDM: false, + isBot: true, + }); + + renderComponent(); + + // Check the trailing element is NOT rendered in the component as this is a bot + expect(screen.queryByText(/John Doe/)).toBeNull(); + }); + + it('should NOT include trailing element when the DM is with oneself', () => { + setMockDate(2); // Tuesday + + mockedUseTimePostBoxIndicator.mockReturnValue({ + ...defaultUseTimePostBoxIndicatorReturnValue, + isDM: true, + isSelfDM: true, + isBot: false, + }); + + renderComponent(); + + // Check the trailing element is NOT rendered in the component as this is a bot + expect(screen.queryByText(/John Doe/)).toBeNull(); + }); }); diff --git a/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.tsx b/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.tsx index c36126f651..1a171f1567 100644 --- a/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.tsx +++ b/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.tsx @@ -46,6 +46,8 @@ function CoreMenuOptions({handleOnSelect, channelId}: Props) { teammateTimezone, teammateDisplayName, isDM, + isSelfDM, + isBot, } = useTimePostBoxIndicator(channelId); const currentUserId = useSelector(getCurrentUserId); @@ -87,7 +89,7 @@ function CoreMenuOptions({handleOnSelect, channelId}: Props) { const extraProps: Partial = {}; - if (isDM) { + if (isDM && !isBot && !isSelfDM) { const teammateTimezoneString = teammateTimezone.useAutomaticTimezone ? teammateTimezone.automaticTimezone : teammateTimezone.manualTimezone || 'UTC'; const scheduledTimeInTeammateTimezone = getScheduledTimeInTeammateTimezone(tomorrow9amTime, teammateTimezoneString); const teammateTimeDisplay = ( diff --git a/webapp/channels/src/components/advanced_text_editor/use_post_box_indicator.tsx b/webapp/channels/src/components/advanced_text_editor/use_post_box_indicator.tsx index 7fa0139ba5..0de15c3cfa 100644 --- a/webapp/channels/src/components/advanced_text_editor/use_post_box_indicator.tsx +++ b/webapp/channels/src/components/advanced_text_editor/use_post_box_indicator.tsx @@ -5,10 +5,17 @@ import {DateTime} from 'luxon'; import {useState, useEffect, useMemo} from 'react'; import {useSelector} from 'react-redux'; +import type {UserProfile} from '@mattermost/types/users'; + import {getDirectChannel} from 'mattermost-redux/selectors/entities/channels'; import {isScheduledPostsEnabled} from 'mattermost-redux/selectors/entities/scheduled_posts'; import {getTimezoneForUserProfile, getCurrentTimezone} from 'mattermost-redux/selectors/entities/timezone'; -import {getStatusForUserId, getUser, makeGetDisplayName} from 'mattermost-redux/selectors/entities/users'; +import { + getCurrentUserId, + getStatusForUserId, + getUser, + makeGetDisplayName, +} from 'mattermost-redux/selectors/entities/users'; import Constants, {UserStatuses} from 'utils/constants'; @@ -43,27 +50,27 @@ function useTimePostBoxIndicator(channelId: string) { const [timestamp, setTimestamp] = useState(0); const [showIt, setShowIt] = useState(false); - // get teammate timezone information - const teammateTimezone = useSelector( - (state: GlobalState) => { - if (!teammateId) { - return DEFAULT_TIMEZONE; - } + const teammate: UserProfile | undefined = useSelector((state: GlobalState) => getUser(state, teammateId)); + const teammateTimezone = useMemo(() => { + if (!teammate) { + return DEFAULT_TIMEZONE; + } - const teammate = getUser(state, teammateId); - return getTimezoneForUserProfile(teammate); - }, - (a, b) => - a.automaticTimezone === b.automaticTimezone && - a.manualTimezone === b.manualTimezone && - a.useAutomaticTimezone === b.useAutomaticTimezone, - ); + return getTimezoneForUserProfile(teammate); + }, [teammate]); // current user timezone const userCurrentTimezone = useSelector((state: GlobalState) => getCurrentTimezone(state)); // UseEffect to update the timestamp and the visibility for the time indicator useEffect(() => { + if (isDM && teammate?.is_bot) { + // returning an empty cleanup function as we need to return a genuine cleanup + // function at if teammate is not a bot and useEffect functions need to + // have consistent return types. So, we have to return a () => void function everywhere. + return () => {}; + } + function updateTime() { const timezone = teammateTimezone.useAutomaticTimezone ? teammateTimezone.automaticTimezone : teammateTimezone.manualTimezone || 'UTC'; @@ -85,16 +92,15 @@ function useTimePostBoxIndicator(channelId: string) { const interval = setInterval(updateTime, MINUTE); return () => clearInterval(interval); - }, [ - teammateTimezone.useAutomaticTimezone, - teammateTimezone.automaticTimezone, - teammateTimezone.manualTimezone, - ]); + }, [teammate, teammateTimezone.useAutomaticTimezone, teammateTimezone.automaticTimezone, teammateTimezone.manualTimezone, isDM]); const isScheduledPostEnabledValue = useSelector(isScheduledPostsEnabled); const showRemoteUserHour = isDM && showIt && timestamp !== 0; + const currentUserId = useSelector(getCurrentUserId); + const isSelfDM = isDM && teammateId === currentUserId; + return { showRemoteUserHour, isDM, @@ -105,6 +111,8 @@ function useTimePostBoxIndicator(channelId: string) { showDndWarning, teammateId, teammateDisplayName, + isSelfDM, + isBot: isDM && teammate.is_bot, }; }