Skip to content

Commit

Permalink
Merge branch 'develop' into test/decouple-apps
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcosSpessatto committed Feb 20, 2024
2 parents d473ba6 + 51f90dc commit cadab4a
Show file tree
Hide file tree
Showing 25 changed files with 291 additions and 115 deletions.
5 changes: 5 additions & 0 deletions .changeset/spicy-wombats-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': minor
---

Introduces message navigability, allowing users to navigate on messages through keyboard
31 changes: 15 additions & 16 deletions apps/meteor/client/components/message/MessageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
MessageNameContainer,
} from '@rocket.chat/fuselage';
import { useTranslation } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import type { KeyboardEvent, ReactElement } from 'react';
import React, { memo } from 'react';

import { getUserDisplayName } from '../../../lib/getUserDisplayName';
Expand Down Expand Up @@ -45,31 +45,30 @@ const MessageHeader = ({ message }: MessageHeaderProps): ReactElement => {

return (
<FuselageMessageHeader>
<MessageNameContainer>
<MessageNameContainer
tabIndex={0}
role='button'
aria-label={getUserDisplayName(user.name, user.username, showRealName)}
{...(user.username !== undefined &&
chat?.userCard && {
onClick: (e) => chat?.userCard.openUserCard(e, message.u.username),
onKeyDown: (e: KeyboardEvent<HTMLSpanElement>) => {
(e.code === 'Enter' || e.code === 'Space') && chat?.userCard.openUserCard(e, message.u.username);
},
style: { cursor: 'pointer' },
})}
>
<MessageName
{...(!showUsername && { 'data-qa-type': 'username' })}
title={!showUsername && !usernameAndRealNameAreSame ? `@${user.username}` : undefined}
data-username={user.username}
{...(user.username !== undefined &&
chat?.userCard && {
onClick: (e) => chat?.userCard.openUserCard(e, message.u.username),
style: { cursor: 'pointer' },
})}
>
{message.alias || getUserDisplayName(user.name, user.username, showRealName)}
</MessageName>
{showUsername && (
<>
{' '}
<MessageUsername
data-username={user.username}
data-qa-type='username'
{...(user.username !== undefined &&
chat?.userCard && {
onClick: (e) => chat?.userCard.openUserCard(e, message.u.username),
style: { cursor: 'pointer' },
})}
>
<MessageUsername data-username={user.username} data-qa-type='username'>
@{user.username}
</MessageUsername>
</>
Expand Down
13 changes: 9 additions & 4 deletions apps/meteor/client/components/message/toolbar/MessageToolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useToolbar } from '@react-aria/toolbar';
import type { IMessage, IRoom, ISubscription, ITranslatedMessage } from '@rocket.chat/core-typings';
import { isThreadMessage, isRoomFederated, isVideoConfMessage } from '@rocket.chat/core-typings';
import { MessageToolbar as FuselageMessageToolbar, MessageToolbarItem } from '@rocket.chat/fuselage';
import { useFeaturePreview } from '@rocket.chat/ui-client';
import { useUser, useSettings, useTranslation, useMethod, useLayoutHiddenActions } from '@rocket.chat/ui-contexts';
import { useQuery } from '@tanstack/react-query';
import type { ReactElement } from 'react';
import React, { memo, useMemo } from 'react';
import type { ComponentProps, ReactElement } from 'react';
import React, { memo, useMemo, useRef } from 'react';

import type { MessageActionContext } from '../../../../app/ui-utils/client/lib/MessageAction';
import { MessageAction } from '../../../../app/ui-utils/client/lib/MessageAction';
Expand Down Expand Up @@ -45,19 +46,23 @@ type MessageToolbarProps = {
room: IRoom;
subscription?: ISubscription;
onChangeMenuVisibility: (visible: boolean) => void;
};
} & ComponentProps<typeof FuselageMessageToolbar>;

const MessageToolbar = ({
message,
messageContext,
room,
subscription,
onChangeMenuVisibility,
...props
}: MessageToolbarProps): ReactElement | null => {
const t = useTranslation();
const user = useUser() ?? undefined;
const settings = useSettings();

const toolbarRef = useRef(null);
const { toolbarProps } = useToolbar(props, toolbarRef);

const quickReactionsEnabled = useFeaturePreview('quickReactions');

const setReaction = useMethod('setReaction');
Expand Down Expand Up @@ -106,7 +111,7 @@ const MessageToolbar = ({
};

return (
<FuselageMessageToolbar>
<FuselageMessageToolbar ref={toolbarRef} {...toolbarProps} aria-label={t('Message_actions')} {...props}>
{quickReactionsEnabled &&
isReactionAllowed &&
quickReactions.slice(0, 3).map(({ emoji, image }) => {
Expand Down
11 changes: 7 additions & 4 deletions apps/meteor/client/components/message/variants/RoomMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Message, MessageLeftContainer, MessageContainer, CheckBox } from '@rock
import { useToggle } from '@rocket.chat/fuselage-hooks';
import { MessageAvatar } from '@rocket.chat/ui-avatar';
import { useUserId } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import type { ComponentProps, ReactElement } from 'react';
import React, { useRef, memo } from 'react';

import type { MessageActionContext } from '../../../../app/ui-utils/client/lib/MessageAction';
Expand Down Expand Up @@ -33,7 +33,7 @@ type RoomMessageProps = {
context?: MessageActionContext;
ignoredUser?: boolean;
searchText?: string;
};
} & ComponentProps<typeof Message>;

const RoomMessage = ({
message,
Expand All @@ -45,6 +45,7 @@ const RoomMessage = ({
context,
ignoredUser,
searchText,
...props
}: RoomMessageProps): ReactElement => {
const uid = useUserId();
const editing = useIsMessageHighlight(message._id);
Expand All @@ -60,10 +61,13 @@ const RoomMessage = ({
useCountSelected();

useJumpToMessage(message._id, messageRef);

return (
<Message
ref={messageRef}
id={message._id}
role='listitem'
tabIndex={0}
onClick={selecting ? toggleSelected : undefined}
isSelected={selected}
isEditing={editing}
Expand All @@ -78,6 +82,7 @@ const RoomMessage = ({
data-own={message.u._id === uid}
data-qa-type='message'
aria-busy={message.temp}
{...props}
>
<MessageLeftContainer>
{!sequential && message.u.username && !selecting && showUserAvatar && (
Expand All @@ -95,10 +100,8 @@ const RoomMessage = ({
{selecting && <CheckBox checked={selected} onChange={toggleSelected} />}
{sequential && <StatusIndicators message={message} />}
</MessageLeftContainer>

<MessageContainer>
{!sequential && <MessageHeader message={message} />}

{ignored ? (
<IgnoredContent onShowMessageIgnored={toggleDisplayIgnoredMessage} />
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { UserAvatar } from '@rocket.chat/ui-avatar';
import type { TranslationKey } from '@rocket.chat/ui-contexts';
import { useTranslation } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import type { ComponentProps, ReactElement } from 'react';
import React, { memo } from 'react';

import { MessageTypes } from '../../../../app/ui-utils/client';
Expand All @@ -37,9 +37,9 @@ import { useMessageListShowRealName, useMessageListShowUsername } from '../list/
type SystemMessageProps = {
message: IMessage;
showUserAvatar: boolean;
};
} & ComponentProps<typeof MessageSystem>;

const SystemMessage = ({ message, showUserAvatar }: SystemMessageProps): ReactElement => {
const SystemMessage = ({ message, showUserAvatar, ...props }: SystemMessageProps): ReactElement => {
const t = useTranslation();
const formatTime = useFormatTime();
const formatDateAndTime = useFormatDateAndTime();
Expand All @@ -59,11 +59,14 @@ const SystemMessage = ({ message, showUserAvatar }: SystemMessageProps): ReactEl

return (
<MessageSystem
role='listitem'
tabIndex={0}
onClick={isSelecting ? toggleSelected : undefined}
isSelected={isSelected}
data-qa-selected={isSelected}
data-qa='system-message'
data-system-message-type={message.t}
{...props}
>
<MessageSystemLeftContainer>
{!isSelecting && showUserAvatar && <UserAvatar username={message.u.username} size='x18' />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const ThreadMessage = ({ message, sequential, unread, showUserAvatar }: ThreadMe

return (
<Message
role='listitem'
tabIndex={0}
id={message._id}
ref={messageRef}
isEditing={editing}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from '@rocket.chat/fuselage';
import { MessageAvatar } from '@rocket.chat/ui-avatar';
import { useTranslation } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import type { ComponentProps, ReactElement } from 'react';
import React, { memo } from 'react';

import { MessageTypes } from '../../../../app/ui-utils/client';
Expand All @@ -36,7 +36,7 @@ type ThreadMessagePreviewProps = {
message: IThreadMessage;
showUserAvatar: boolean;
sequential: boolean;
};
} & ComponentProps<typeof ThreadMessage>;

const ThreadMessagePreview = ({ message, showUserAvatar, sequential, ...props }: ThreadMessagePreviewProps): ReactElement => {
const parentMessage = useParentMessage(message.tmid);
Expand All @@ -56,23 +56,30 @@ const ThreadMessagePreview = ({ message, showUserAvatar, sequential, ...props }:

const goToThread = useGoToThread();

const handleThreadClick = () => {
if (!isSelecting) {
if (!sequential) {
return parentMessage.isSuccess && goToThread({ rid: message.rid, tmid: message.tmid, msg: parentMessage.data?._id });
}

return goToThread({ rid: message.rid, tmid: message.tmid, msg: message._id });
}

return toggleSelected();
};

return (
<ThreadMessage
{...props}
onClick={isSelecting ? toggleSelected : undefined}
tabIndex={0}
onClick={handleThreadClick}
onKeyDown={(e) => e.code === 'Enter' && handleThreadClick()}
isSelected={isSelected}
data-qa-selected={isSelected}
role='link'
{...props}
>
{!sequential && (
<ThreadMessageRow
role='link'
onClick={
!isSelecting && parentMessage.isSuccess
? () => goToThread({ rid: message.rid, tmid: message.tmid, msg: parentMessage.data?._id })
: undefined
}
>
<ThreadMessageRow>
<ThreadMessageLeftContainer>
<ThreadMessageIconThread />
</ThreadMessageLeftContainer>
Expand Down Expand Up @@ -100,7 +107,7 @@ const ThreadMessagePreview = ({ message, showUserAvatar, sequential, ...props }:
</ThreadMessageContainer>
</ThreadMessageRow>
)}
<ThreadMessageRow onClick={!isSelecting ? () => goToThread({ rid: message.rid, tmid: message.tmid, msg: message._id }) : undefined}>
<ThreadMessageRow>
<ThreadMessageLeftContainer>
{!isSelecting && showUserAvatar && (
<MessageAvatar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ const EmojiElement = ({ emoji, image, onClick, small = false, ...props }: EmojiE

return (
<IconButton
{...props}
{...(small && { className: emojiSmallClass })}
small={small}
medium={!small}
Expand All @@ -40,6 +39,7 @@ const EmojiElement = ({ emoji, image, onClick, small = false, ...props }: EmojiE
data-emoji={emoji}
aria-label={emoji}
icon={emojiElement}
{...props}
/>
);
};
Expand Down
55 changes: 31 additions & 24 deletions apps/meteor/client/views/room/Room.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useTranslation } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import React, { createElement, lazy, memo, Suspense } from 'react';
import { FocusScope } from 'react-aria';
import { ErrorBoundary } from 'react-error-boundary';

import { ContextualbarSkeleton } from '../../components/Contextualbar';
Expand All @@ -25,30 +26,36 @@ const Room = (): ReactElement => {
return (
<ChatProvider>
<MessageHighlightProvider>
<RoomLayout
aria-label={t('Channel')}
data-qa-rc-room={room._id}
header={<Header room={room} />}
body={<RoomBody />}
aside={
(toolbox.tab?.tabComponent && (
<ErrorBoundary fallback={null}>
<SelectedMessagesProvider>
<Suspense fallback={<ContextualbarSkeleton />}>{createElement(toolbox.tab.tabComponent)}</Suspense>
</SelectedMessagesProvider>
</ErrorBoundary>
)) ||
(contextualBarView && (
<ErrorBoundary fallback={null}>
<SelectedMessagesProvider>
<Suspense fallback={<ContextualbarSkeleton />}>
<UiKitContextualBar key={contextualBarView.id} initialView={contextualBarView} />
</Suspense>
</SelectedMessagesProvider>
</ErrorBoundary>
))
}
/>
<FocusScope>
<RoomLayout
data-qa-rc-room={room._id}
aria-label={
room.t === 'd'
? t('Conversation_with__roomName__', { roomName: room.name })
: t('Channel__roomName__', { roomName: room.name })
}
header={<Header room={room} />}
body={<RoomBody />}
aside={
(toolbox.tab?.tabComponent && (
<ErrorBoundary fallback={null}>
<SelectedMessagesProvider>
<Suspense fallback={<ContextualbarSkeleton />}>{createElement(toolbox.tab.tabComponent)}</Suspense>
</SelectedMessagesProvider>
</ErrorBoundary>
)) ||
(contextualBarView && (
<ErrorBoundary fallback={null}>
<SelectedMessagesProvider>
<Suspense fallback={<ContextualbarSkeleton />}>
<UiKitContextualBar key={contextualBarView.id} initialView={contextualBarView} />
</Suspense>
</SelectedMessagesProvider>
</ErrorBoundary>
))
}
/>
</FocusScope>
</MessageHighlightProvider>
</ChatProvider>
);
Expand Down
Loading

0 comments on commit cadab4a

Please sign in to comment.