Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions apps/meteor/client/components/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { Component, ReactNode } from 'react';
import { Component, ReactNode, ErrorInfo } from 'react';

export class ErrorBoundary extends Component<{}, { hasError: boolean }> {
export class ErrorBoundary extends Component<{ fallback?: ReactNode }, { hasError: boolean }> {
state = { hasError: false };

static getDerivedStateFromError(): { hasError: boolean } {
return { hasError: true };
}

componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
console.error('Uncaught Error:', error, errorInfo);
}

render(): ReactNode {
if (this.state.hasError) {
return null;
return this.props.fallback || null;
}

return this.props.children;
Expand Down
113 changes: 58 additions & 55 deletions apps/meteor/client/views/room/MessageList/MessageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useUserSubscription } from '../../../contexts/UserContext';
import { useFormatDate } from '../../../hooks/useFormatDate';
import { MessageProvider } from '../providers/MessageProvider';
import { SelectedMessagesProvider } from '../providers/SelectedMessagesProvider';
import MessageListErrorBoundary from './MessageListErrorBoundary';
import Message from './components/Message';
import MessageSystem from './components/MessageSystem';
import { ThreadMessagePreview } from './components/ThreadMessagePreview';
Expand All @@ -29,69 +30,71 @@ export const MessageList: FC<{ rid: IRoom['_id'] }> = ({ rid }) => {
const format = useFormatDate();

return (
<MessageListProvider rid={rid}>
<MessageProvider rid={rid} broadcast={isBroadcast}>
<SelectedMessagesProvider>
<MessageHighlightProvider>
{messages.map((message, index, arr) => {
const previous = arr[index - 1];
<MessageListErrorBoundary>
<MessageListProvider rid={rid}>
<MessageProvider rid={rid} broadcast={isBroadcast}>
<SelectedMessagesProvider>
<MessageHighlightProvider>
{messages.map((message, index, arr) => {
const previous = arr[index - 1];

const isSequential = isMessageSequential(message, previous, messageGroupingPeriod);
const isSequential = isMessageSequential(message, previous, messageGroupingPeriod);

const isNewDay = isMessageNewDay(message, previous);
const isFirstUnread = isMessageFirstUnread(subscription, message, previous);
const isUserOwnMessage = isOwnUserMessage(message, subscription);
const shouldShowDivider = isNewDay || isFirstUnread;
const isNewDay = isMessageNewDay(message, previous);
const isFirstUnread = isMessageFirstUnread(subscription, message, previous);
const isUserOwnMessage = isOwnUserMessage(message, subscription);
const shouldShowDivider = isNewDay || isFirstUnread;

const shouldShowAsSequential = isSequential && !isNewDay;
const shouldShowAsSequential = isSequential && !isNewDay;

const isSystemMessage = MessageTypes.isSystemMessage(message);
const shouldShowMessage = !isThreadMessage(message) && !isSystemMessage;
const isSystemMessage = MessageTypes.isSystemMessage(message);
const shouldShowMessage = !isThreadMessage(message) && !isSystemMessage;

return (
<Fragment key={message._id}>
{shouldShowDivider && (
<MessageDivider unreadLabel={isFirstUnread ? t('Unread_Messages').toLowerCase() : undefined}>
{isNewDay && format(message.ts)}
</MessageDivider>
)}
return (
<Fragment key={message._id}>
{shouldShowDivider && (
<MessageDivider unreadLabel={isFirstUnread ? t('Unread_Messages').toLowerCase() : undefined}>
{isNewDay && format(message.ts)}
</MessageDivider>
)}

{shouldShowMessage && (
<Message
id={message._id}
data-id={message._id}
data-system-message={Boolean(message.t)}
data-mid={message._id}
data-unread={isFirstUnread}
data-sequential={isSequential}
data-own={isUserOwnMessage}
data-qa-type='message'
sequential={shouldShowAsSequential}
message={message}
subscription={subscription}
/>
)}
{shouldShowMessage && (
<Message
id={message._id}
data-id={message._id}
data-system-message={Boolean(message.t)}
data-mid={message._id}
data-unread={isFirstUnread}
data-sequential={isSequential}
data-own={isUserOwnMessage}
data-qa-type='message'
sequential={shouldShowAsSequential}
message={message}
subscription={subscription}
/>
)}

{isThreadMessage(message) && (
<ThreadMessagePreview
data-system-message={Boolean(message.t)}
data-mid={message._id}
data-tmid={message.tmid}
data-unread={isFirstUnread}
data-sequential={isSequential}
sequential={shouldShowAsSequential}
message={message as IThreadMessage}
/>
)}
{isThreadMessage(message) && (
<ThreadMessagePreview
data-system-message={Boolean(message.t)}
data-mid={message._id}
data-tmid={message.tmid}
data-unread={isFirstUnread}
data-sequential={isSequential}
sequential={shouldShowAsSequential}
message={message as IThreadMessage}
/>
)}

{isSystemMessage && <MessageSystem message={message} />}
</Fragment>
);
})}
</MessageHighlightProvider>
</SelectedMessagesProvider>
</MessageProvider>
</MessageListProvider>
{isSystemMessage && <MessageSystem message={message} />}
</Fragment>
);
})}
</MessageHighlightProvider>
</SelectedMessagesProvider>
</MessageProvider>
</MessageListProvider>
</MessageListErrorBoundary>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { States, StatesIcon, StatesTitle, StatesSubtitle, StatesActions, StatesAction, Icon } from '@rocket.chat/fuselage';
import React, { ReactElement, ReactNode } from 'react';

import { ErrorBoundary } from '../../../components/ErrorBoundary';
import { useTranslation } from '../../../contexts/TranslationContext';

const MessageListErrorBoundary = ({ children }: { children: ReactNode }): ReactElement => {
const t = useTranslation();
return (
<ErrorBoundary
children={children}
fallback={
<States>
<StatesIcon name='circle-exclamation' variation='danger' />
<StatesTitle>{t('Error')}</StatesTitle>
<StatesSubtitle>{t('Error_something_went_wrong')}</StatesSubtitle>
<StatesActions>
<StatesAction
onClick={(): void => {
location.reload();
}}
>
<Icon name='reload' /> {t('Reload')}
</StatesAction>
</StatesActions>
</States>
}
/>
);
};

export default MessageListErrorBoundary;
1 change: 1 addition & 0 deletions apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -1679,6 +1679,7 @@
"Enterprise_License_Description": "If your workspace is registered and license is provided by Rocket.Chat Cloud you don't need to manually update the license here.",
"Entertainment": "Entertainment",
"Error": "Error",
"Error_something_went_wrong": "Oops! Something went wrong. Please reload the page or contact an administrator.",
"Error_404": "Error:404",
"Error_changing_password": "Error changing password",
"Error_loading_pages": "Error loading pages",
Expand Down