diff --git a/.changeset/wet-penguins-end.md b/.changeset/wet-penguins-end.md new file mode 100644 index 0000000000000..b2a22d4a74130 --- /dev/null +++ b/.changeset/wet-penguins-end.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': minor +--- + +Separates voice call and video call room actions on room header. diff --git a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/index.ts b/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/index.ts deleted file mode 100644 index d01e5a6a5dffd..0000000000000 --- a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './useStartCallRoomAction'; diff --git a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useStartCallRoomAction.tsx b/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useStartCallRoomAction.tsx deleted file mode 100644 index a4db8c7eddd6c..0000000000000 --- a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useStartCallRoomAction.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { GenericMenu } from '@rocket.chat/ui-client'; -import { useMemo } from 'react'; - -import useVideoConfMenuOptions from './useVideoConfMenuOptions'; -import useVoipMenuOptions from './useVoipMenuOptions'; -import HeaderToolbarAction from '../../../components/Header/HeaderToolbarAction'; -import type { RoomToolboxActionConfig } from '../../../views/room/contexts/RoomToolboxContext'; - -export const useStartCallRoomAction = () => { - const videoCall = useVideoConfMenuOptions(); - const voipCall = useVoipMenuOptions(); - - return useMemo((): RoomToolboxActionConfig | undefined => { - if (!videoCall.allowed && !voipCall?.allowed) { - return undefined; - } - - return { - id: 'start-call', - title: 'Call', - icon: 'phone', - groups: [...videoCall.groups, ...(voipCall?.groups ?? [])], - disabled: videoCall.disabled && (voipCall?.disabled ?? true), - full: true, - order: Math.max(voipCall?.order ?? Number.NEGATIVE_INFINITY, videoCall.order), - featured: true, - renderToolboxItem: ({ id, icon, title, disabled, className }) => ( - } - key={id} - title={title} - disabled={disabled} - items={[...(voipCall?.allowed ? voipCall.items : []), ...videoCall.items]} - className={className} - placement='bottom-start' - icon={icon} - /> - ), - }; - }, [videoCall, voipCall]); -}; diff --git a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useVideoConfMenuOptions.tsx b/apps/meteor/client/hooks/roomActions/useVideoCallRoomAction.tsx similarity index 70% rename from apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useVideoConfMenuOptions.tsx rename to apps/meteor/client/hooks/roomActions/useVideoCallRoomAction.tsx index 2281e02bbac71..9146a2fc651a0 100644 --- a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useVideoConfMenuOptions.tsx +++ b/apps/meteor/client/hooks/roomActions/useVideoCallRoomAction.tsx @@ -1,7 +1,5 @@ -import { isOmnichannelRoom, isRoomFederated } from '@rocket.chat/core-typings'; -import { Box } from '@rocket.chat/fuselage'; +import { isRoomFederated } from '@rocket.chat/core-typings'; import { useEffectEvent, useStableArray } from '@rocket.chat/fuselage-hooks'; -import type { GenericMenuItemProps } from '@rocket.chat/ui-client'; import { usePermission, useSetting, useUser } from '@rocket.chat/ui-contexts'; import { useVideoConfDispatchOutgoing, @@ -12,11 +10,11 @@ import { import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { useRoom } from '../../../views/room/contexts/RoomContext'; -import type { RoomToolboxActionConfig } from '../../../views/room/contexts/RoomToolboxContext'; -import { useVideoConfWarning } from '../../../views/room/contextualBar/VideoConference/hooks/useVideoConfWarning'; +import { useRoom } from '../../views/room/contexts/RoomContext'; +import type { RoomToolboxActionConfig } from '../../views/room/contexts/RoomToolboxContext'; +import { useVideoConfWarning } from '../../views/room/contextualBar/VideoConference/hooks/useVideoConfWarning'; -const useVideoConfMenuOptions = () => { +export const useVideoCallRoomAction = () => { const { t } = useTranslation(); const room = useRoom(); const user = useUser(); @@ -54,7 +52,6 @@ const useVideoConfMenuOptions = () => { const allowed = visible && permittedToCallManagement && (!user?.username || !room.muted?.includes(user.username)) && !ownUser; const disabled = federated || (!!room.ro && !permittedToPostReadonly); const tooltip = disabled ? t('core.Video_Call_unavailable_for_this_type_of_room') : ''; - const order = isOmnichannelRoom(room) ? -1 : 4; const handleOpenVideoConf = useEffectEvent(async () => { if (isCalling || isRinging) { @@ -69,29 +66,21 @@ const useVideoConfMenuOptions = () => { } }); - return useMemo(() => { - const items: GenericMenuItemProps[] = [ - { - id: 'start-video-call', - icon: 'video', - disabled, - onClick: handleOpenVideoConf, - content: ( - - {t('Video_call')} - - ), - }, - ]; + return useMemo((): RoomToolboxActionConfig | undefined => { + if (!allowed) { + return undefined; + } return { - items, - disabled, - allowed, - order, + id: 'start-video-call', + title: 'Video_call', + icon: 'video', + featured: true, + action: handleOpenVideoConf, + order: -1, groups, + disabled, + tooltip, }; - }, [allowed, disabled, groups, handleOpenVideoConf, order, t, tooltip]); + }, [allowed, groups, disabled, handleOpenVideoConf, tooltip]); }; - -export default useVideoConfMenuOptions; diff --git a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useVoipMenuOptions.tsx b/apps/meteor/client/hooks/roomActions/useVoiceCallRoomAction.tsx similarity index 64% rename from apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useVoipMenuOptions.tsx rename to apps/meteor/client/hooks/roomActions/useVoiceCallRoomAction.tsx index b6f31ff5cedf2..c858a591387a7 100644 --- a/apps/meteor/client/hooks/roomActions/useStartCallRoomAction/useVoipMenuOptions.tsx +++ b/apps/meteor/client/hooks/roomActions/useVoiceCallRoomAction.tsx @@ -1,17 +1,16 @@ -import { Box } from '@rocket.chat/fuselage'; import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; -import type { GenericMenuItemProps } from '@rocket.chat/ui-client'; import { usePermission, useUserId } from '@rocket.chat/ui-contexts'; import { useVoipAPI, useVoipState } from '@rocket.chat/ui-voip'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { useMediaPermissions } from '../../../views/room/composer/messageBox/hooks/useMediaPermissions'; -import { useRoom } from '../../../views/room/contexts/RoomContext'; -import { useUserInfoQuery } from '../../useUserInfoQuery'; -import { useVoipWarningModal } from '../../useVoipWarningModal'; +import { useMediaPermissions } from '../../views/room/composer/messageBox/hooks/useMediaPermissions'; +import { useRoom } from '../../views/room/contexts/RoomContext'; +import type { RoomToolboxActionConfig } from '../../views/room/contexts/RoomToolboxContext'; +import { useUserInfoQuery } from '../useUserInfoQuery'; +import { useVoipWarningModal } from '../useVoipWarningModal'; -const useVoipMenuOptions = () => { +export const useVoiceCallRoomAction = () => { const { t } = useTranslation(); const { uids = [] } = useRoom(); const ownUserId = useUserId(); @@ -32,10 +31,10 @@ const useVoipMenuOptions = () => { const isDM = members.length === 1; const disabled = isMicPermissionDenied || !isDM || isInCall || isPending; - const allowed = isDM && !isInCall && !isPending; + const allowed = canStartVoiceCall && isDM && !isInCall && !isPending; const canMakeVoipCall = allowed && isRemoteRegistered && isRegistered && isEnabled && !isMicPermissionDenied; - const title = useMemo(() => { + const tooltip = useMemo(() => { if (isMicPermissionDenied) { return t('Microphone_access_not_allowed'); } @@ -54,33 +53,20 @@ const useVoipMenuOptions = () => { dispatchWarning(); }); - return useMemo(() => { - if (!canStartVoiceCall) { + return useMemo((): RoomToolboxActionConfig | undefined => { + if (!allowed) { return undefined; } - const items: GenericMenuItemProps[] = [ - { - id: 'start-voip-call', - icon: 'phone', - disabled, - onClick: handleOnClick, - content: ( - - {t('Voice_call')} - - ), - }, - ]; - return { - items, + id: 'start-voice-call', + title: 'Voice_Call', + icon: 'phone', + featured: true, + action: handleOnClick, groups: ['direct'] as const, disabled, - order: 4, - allowed, + tooltip, }; - }, [disabled, title, t, handleOnClick, allowed, canStartVoiceCall]); + }, [allowed, disabled, handleOnClick, tooltip]); }; - -export default useVoipMenuOptions; diff --git a/apps/meteor/client/ui.ts b/apps/meteor/client/ui.ts index f5e55d64833b5..2bad21ebd2fae 100644 --- a/apps/meteor/client/ui.ts +++ b/apps/meteor/client/ui.ts @@ -25,14 +25,15 @@ import { usePushNotificationsRoomAction } from './hooks/roomActions/usePushNotif import { useRocketSearchRoomAction } from './hooks/roomActions/useRocketSearchRoomAction'; import { useRoomInfoRoomAction } from './hooks/roomActions/useRoomInfoRoomAction'; import { useStarredMessagesRoomAction } from './hooks/roomActions/useStarredMessagesRoomAction'; -import { useStartCallRoomAction } from './hooks/roomActions/useStartCallRoomAction'; import { useTeamChannelsRoomAction } from './hooks/roomActions/useTeamChannelsRoomAction'; import { useTeamInfoRoomAction } from './hooks/roomActions/useTeamInfoRoomAction'; import { useThreadRoomAction } from './hooks/roomActions/useThreadRoomAction'; import { useUploadedFilesListRoomAction } from './hooks/roomActions/useUploadedFilesListRoomAction'; import { useUserInfoGroupRoomAction } from './hooks/roomActions/useUserInfoGroupRoomAction'; import { useUserInfoRoomAction } from './hooks/roomActions/useUserInfoRoomAction'; +import { useVideoCallRoomAction } from './hooks/roomActions/useVideoCallRoomAction'; import { useVoIPRoomInfoRoomAction } from './hooks/roomActions/useVoIPRoomInfoRoomAction'; +import { useVoiceCallRoomAction } from './hooks/roomActions/useVoiceCallRoomAction'; import { useWebRTCVideoRoomAction } from './hooks/roomActions/useWebRTCVideoRoomAction'; import type { RoomToolboxActionConfig } from './views/room/contexts/RoomToolboxContext'; import type { QuickActionsActionConfig } from './views/room/lib/quickActions'; @@ -63,12 +64,13 @@ export const roomActionHooks = [ useRocketSearchRoomAction, useRoomInfoRoomAction, useStarredMessagesRoomAction, - useStartCallRoomAction, useTeamChannelsRoomAction, useUploadedFilesListRoomAction, useVoIPRoomInfoRoomAction, useWebRTCVideoRoomAction, useAppsRoomStarActions, + useVideoCallRoomAction, + useVoiceCallRoomAction, ] satisfies (() => RoomToolboxActionConfig | undefined)[]; export const quickActionHooks = [ diff --git a/apps/meteor/tests/e2e/federation/page-objects/fragments/home-flextab.ts b/apps/meteor/tests/e2e/federation/page-objects/fragments/home-flextab.ts index 4c62a1199ac07..ad343b5b2a56d 100644 --- a/apps/meteor/tests/e2e/federation/page-objects/fragments/home-flextab.ts +++ b/apps/meteor/tests/e2e/federation/page-objects/fragments/home-flextab.ts @@ -44,6 +44,10 @@ export class FederationHomeFlextab { return this.page.locator('[data-qa-id="ToolBoxAction-phone"]'); } + get btnVideoCall(): Locator { + return this.page.locator('[role=toolbar][aria-label="Primary Room actions"]').getByRole('button', { name: 'Video call' }); + } + get btnDiscussion(): Locator { return this.page.locator('[data-qa-id="ToolBoxAction-discussion"]'); } diff --git a/apps/meteor/tests/e2e/federation/tests/channel/dm.spec.ts b/apps/meteor/tests/e2e/federation/tests/channel/dm.spec.ts index c724d8a39ded3..4d01e00f76435 100644 --- a/apps/meteor/tests/e2e/federation/tests/channel/dm.spec.ts +++ b/apps/meteor/tests/e2e/federation/tests/channel/dm.spec.ts @@ -770,9 +770,11 @@ test.describe.parallel('Federation - Direct Messages', () => { await poFederationChannelServer1.content.sendMessage('hello world'); await expect(poFederationChannelServer1.tabs.btnCall).toBeDisabled(); + await expect(poFederationChannelServer1.tabs.btnVideoCall).toBeDisabled(); await poFederationChannelServer2.sidenav.openChat(usernameWithDomainFromServer1); await expect(poFederationChannelServer2.tabs.btnCall).toBeDisabled(); + await expect(poFederationChannelServer1.tabs.btnVideoCall).toBeDisabled(); await pageForServer2.close(); }); diff --git a/apps/meteor/tests/e2e/federation/tests/channel/private.spec.ts b/apps/meteor/tests/e2e/federation/tests/channel/private.spec.ts index 1fcf6882bd393..29570e0372cb1 100644 --- a/apps/meteor/tests/e2e/federation/tests/channel/private.spec.ts +++ b/apps/meteor/tests/e2e/federation/tests/channel/private.spec.ts @@ -883,6 +883,8 @@ test.describe.parallel('Federation - Group Creation', () => { await expect(poFederationChannelServer1.tabs.btnCall).toBeDisabled(); await expect(poFederationChannelServer2.tabs.btnCall).toBeDisabled(); + await expect(poFederationChannelServer1.tabs.btnVideoCall).toBeDisabled(); + await expect(poFederationChannelServer2.tabs.btnVideoCall).toBeDisabled(); await pageForServer2.close(); }); diff --git a/apps/meteor/tests/e2e/federation/tests/channel/public.spec.ts b/apps/meteor/tests/e2e/federation/tests/channel/public.spec.ts index 0c79a309faba6..237a154c0d72c 100644 --- a/apps/meteor/tests/e2e/federation/tests/channel/public.spec.ts +++ b/apps/meteor/tests/e2e/federation/tests/channel/public.spec.ts @@ -889,6 +889,8 @@ test.describe.parallel('Federation - Channel Creation', () => { await expect(poFederationChannelServer1.tabs.btnCall).toBeDisabled(); await expect(poFederationChannelServer2.tabs.btnCall).toBeDisabled(); + await expect(poFederationChannelServer1.tabs.btnVideoCall).toBeDisabled(); + await expect(poFederationChannelServer2.tabs.btnVideoCall).toBeDisabled(); await pageForServer2.close(); }); diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts index cab59e8430693..905be5aa9c530 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts @@ -375,12 +375,8 @@ export class HomeContent { return this.page.locator('[data-qa-id="ToolBoxAction-pause-unfilled"]'); } - get btnCall(): Locator { - return this.page.locator('[data-qa-id="ToolBoxAction-phone"]'); - } - - get menuItemVideoCall(): Locator { - return this.page.locator('role=menuitem[name="Video call"]'); + get btnVideoCall(): Locator { + return this.page.locator('[role=toolbar][aria-label="Primary Room actions"]').getByRole('button', { name: 'Video call' }); } get btnStartVideoCall(): Locator { diff --git a/apps/meteor/tests/e2e/video-conference-ring.spec.ts b/apps/meteor/tests/e2e/video-conference-ring.spec.ts index d489e1a258ac0..49b7d15a751a1 100644 --- a/apps/meteor/tests/e2e/video-conference-ring.spec.ts +++ b/apps/meteor/tests/e2e/video-conference-ring.spec.ts @@ -34,8 +34,7 @@ test.describe('video conference ringing', () => { await auxContext.poHomeChannel.sidenav.openChat('user1'); await test.step('should user1 calls user2', async () => { - await poHomeChannel.content.btnCall.click(); - await poHomeChannel.content.menuItemVideoCall.click(); + await poHomeChannel.content.btnVideoCall.click(); await poHomeChannel.content.btnStartVideoCall.click(); await expect(poHomeChannel.content.getVideoConfPopupByName('Calling user2')).toBeVisible(); diff --git a/apps/meteor/tests/e2e/video-conference.spec.ts b/apps/meteor/tests/e2e/video-conference.spec.ts index 63ebdd2966dc0..2c81b7b66159f 100644 --- a/apps/meteor/tests/e2e/video-conference.spec.ts +++ b/apps/meteor/tests/e2e/video-conference.spec.ts @@ -29,8 +29,7 @@ test.describe('video conference', () => { test('expect create video conference in a "targetChannel"', async () => { await poHomeChannel.sidenav.openChat(targetChannel); - await poHomeChannel.content.btnCall.click(); - await poHomeChannel.content.menuItemVideoCall.click(); + await poHomeChannel.content.btnVideoCall.click(); await poHomeChannel.content.btnStartVideoCall.click(); await expect(poHomeChannel.content.videoConfMessageBlock.last()).toBeVisible(); }); @@ -64,8 +63,7 @@ test.describe('video conference', () => { test('expect create video conference in a direct', async () => { await poHomeChannel.sidenav.openChat('user2'); - await poHomeChannel.content.btnCall.click(); - await poHomeChannel.content.menuItemVideoCall.click(); + await poHomeChannel.content.btnVideoCall.click(); await poHomeChannel.content.btnStartVideoCall.click(); await expect(poHomeChannel.content.videoConfMessageBlock.last()).toBeVisible(); }); @@ -81,8 +79,7 @@ test.describe('video conference', () => { test('expect create video conference in a "targetTeam"', async () => { await poHomeChannel.sidenav.openChat(targetTeam); - await poHomeChannel.content.btnCall.click(); - await poHomeChannel.content.menuItemVideoCall.click(); + await poHomeChannel.content.btnVideoCall.click(); await poHomeChannel.content.btnStartVideoCall.click(); await expect(poHomeChannel.content.videoConfMessageBlock.last()).toBeVisible(); }); @@ -98,8 +95,7 @@ test.describe('video conference', () => { test('expect create video conference in a direct multiple', async () => { await poHomeChannel.sidenav.openChat('rocketchat.internal.admin.test, user2'); - await poHomeChannel.content.btnCall.click(); - await poHomeChannel.content.menuItemVideoCall.click(); + await poHomeChannel.content.btnVideoCall.click(); await poHomeChannel.content.btnStartVideoCall.click(); await expect(poHomeChannel.content.videoConfMessageBlock.last()).toBeVisible(); }); @@ -115,6 +111,6 @@ test.describe('video conference', () => { test('expect create video conference not available in a "targetReadOnlyChannel"', async () => { await poHomeChannel.sidenav.openChat(targetReadOnlyChannel); - await expect(poHomeChannel.content.btnCall).hasAttribute('disabled'); + await expect(poHomeChannel.content.btnVideoCall).hasAttribute('disabled'); }); });