Skip to content

Commit

Permalink
feat: add MessageListMainPanel to ComponentContext (#2528)
Browse files Browse the repository at this point in the history
### 🎯 Goal

Allows to override `MessageListMainPanel` component especially for
integrators migrating to `v12` where `MessageListMainPanel` now always
renders a `div` since the theming v2 is now a default.

#### Additional changs:

- Added new class name to the default component to correct naming
(`str-chat__message-list-main-panel`), ideally the styling would be
moved too and the existing class name deprecated.
- Simplified `ChannelPropsForwardedToComponentContext` type by picking
types from the `ComponentContextValue` type directly.
  • Loading branch information
arnautov-anton authored Oct 2, 2024
1 parent 08e38e5 commit 32928f3
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 118 deletions.
157 changes: 54 additions & 103 deletions src/components/Channel/Channel.tsx

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/components/MessageList/MessageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { InfiniteScroll, InfiniteScrollProps } from '../InfiniteScrollPaginator/
import { LoadingIndicator as DefaultLoadingIndicator } from '../Loading';
import { defaultPinPermissions, MESSAGE_ACTIONS } from '../Message/utils';
import { TypingIndicator as DefaultTypingIndicator } from '../TypingIndicator';
import { MessageListMainPanel } from './MessageListMainPanel';
import { MessageListMainPanel as DefaultMessageListMainPanel } from './MessageListMainPanel';

import { defaultRenderMessages, MessageRenderer } from './renderMessages';

Expand Down Expand Up @@ -104,6 +104,7 @@ const MessageListWithContext = <
MessageNotification = DefaultMessageNotification,
TypingIndicator = DefaultTypingIndicator,
UnreadMessagesNotification = DefaultUnreadMessagesNotification,
MessageListMainPanel = DefaultMessageListMainPanel,
} = useComponentContext<StreamChatGenerics>('MessageList');

const {
Expand Down
2 changes: 1 addition & 1 deletion src/components/MessageList/MessageListMainPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import type { PropsWithChildrenOnly } from '../../types/types';

export const MESSAGE_LIST_MAIN_PANEL_CLASS = 'str-chat__main-panel-inner' as const;
export const MESSAGE_LIST_MAIN_PANEL_CLASS = 'str-chat__main-panel-inner str-chat__message-list-main-panel' as const;

export const MessageListMainPanel = ({ children }: PropsWithChildrenOnly) => (
<div className={MESSAGE_LIST_MAIN_PANEL_CLASS}>{children}</div>
Expand Down
3 changes: 2 additions & 1 deletion src/components/MessageList/VirtualizedMessageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { useMarkRead } from './hooks/useMarkRead';

import { MessageNotification as DefaultMessageNotification } from './MessageNotification';
import { MessageListNotifications as DefaultMessageListNotifications } from './MessageListNotifications';
import { MessageListMainPanel } from './MessageListMainPanel';
import { MessageListMainPanel as DefaultMessageListMainPanel } from './MessageListMainPanel';
import {
getGroupStyles,
getLastReceived,
Expand Down Expand Up @@ -235,6 +235,7 @@ const VirtualizedMessageListWithContext = <
MessageListNotifications = DefaultMessageListNotifications,
MessageNotification = DefaultMessageNotification,
MessageSystem = DefaultMessageSystem,
MessageListMainPanel = DefaultMessageListMainPanel,
UnreadMessagesNotification = DefaultUnreadMessagesNotification,
UnreadMessagesSeparator = DefaultUnreadMessagesSeparator,
VirtualMessage: MessageUIComponentFromContext = MessageSimple,
Expand Down
31 changes: 23 additions & 8 deletions src/components/MessageList/__tests__/MessageList.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { EmptyStateIndicator as EmptyStateIndicatorMock } from '../../EmptyState
import { ScrollToBottomButton } from '../ScrollToBottomButton';
import { MessageListNotifications } from '../MessageListNotifications';
import { mockedApiResponse } from '../../../mock-builders/api/utils';
import { nanoid } from 'nanoid';

expect.extend(toHaveNoViolations);

Expand Down Expand Up @@ -326,7 +327,11 @@ describe('MessageList', () => {
});

describe('unread messages', () => {
const messages = Array.from({ length: 5 }, generateMessage);
const timestamp = new Date().getTime();
const messages = Array.from({ length: 5 }, (_, index) =>
generateMessage({ created_at: new Date(timestamp + index * 1000).toISOString() }),
);

const unread_messages = 2;
const lastReadMessage = messages[unread_messages];
const separatorText = `Unread messages`;
Expand Down Expand Up @@ -668,24 +673,34 @@ describe('MessageList', () => {
msgListProps,
});
if (expected === 'should') {
expect(screen.queryByTestId(UNREAD_MESSAGES_NOTIFICATION_TEST_ID)).toBeInTheDocument();
await waitFor(() =>
expect(
screen.queryByTestId(UNREAD_MESSAGES_NOTIFICATION_TEST_ID),
).toBeInTheDocument(),
);
} else {
expect(
screen.queryByTestId(UNREAD_MESSAGES_NOTIFICATION_TEST_ID),
).not.toBeInTheDocument();
await waitFor(() =>
expect(
screen.queryByTestId(UNREAD_MESSAGES_NOTIFICATION_TEST_ID),
).not.toBeInTheDocument(),
);
}
},
);

it('should display custom unread messages notification', async () => {
const customUnreadMessagesNotificationText = 'customUnreadMessagesNotificationText';
const UnreadMessagesNotification = () => <div>{customUnreadMessagesNotificationText}</div>;
const customUnreadMessagesNotificationText = nanoid();
const UnreadMessagesNotification = () => (
<div data-testid={customUnreadMessagesNotificationText}>aaa</div>
);
await setupTest({
channelProps: { UnreadMessagesNotification },
entries: observerEntriesScrolledBelowSeparator,
});

expect(screen.getByText(customUnreadMessagesNotificationText)).toBeInTheDocument();
await waitFor(() =>
expect(screen.getByTestId(customUnreadMessagesNotificationText)).toBeInTheDocument(),
);
});

it('should not display unread messages notification when unread count is 0', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ exports[`VirtualizedMessageList should render the list without any message 1`] =
className="str-chat__container"
>
<div
className="str-chat__main-panel-inner"
className="str-chat__main-panel-inner str-chat__message-list-main-panel"
>
<div
className="str-chat__virtual-list"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ export const useUnreadMessagesNotification = ({
return;
}

const msgListPanel = document.querySelector(`.${MESSAGE_LIST_MAIN_PANEL_CLASS}`);
const [msgListPanel] = document.getElementsByClassName(MESSAGE_LIST_MAIN_PANEL_CLASS);
if (!msgListPanel) return;

const observedTarget = document.querySelector(`.${UNREAD_MESSAGE_SEPARATOR_CLASS}`);
const [observedTarget] = document.getElementsByClassName(UNREAD_MESSAGE_SEPARATOR_CLASS);
if (!observedTarget) {
setShow(true);
return;
Expand Down
Loading

0 comments on commit 32928f3

Please sign in to comment.