diff --git a/docusaurus/docs/React/components/utility-components/channel-preview-ui.mdx b/docusaurus/docs/React/components/utility-components/channel-preview-ui.mdx index 9487dea94..70f202d27 100644 --- a/docusaurus/docs/React/components/utility-components/channel-preview-ui.mdx +++ b/docusaurus/docs/React/components/utility-components/channel-preview-ui.mdx @@ -109,22 +109,6 @@ Latest message preview to display. Will be either a string or a JSX.Element rend | --------------------- | | string \| JSX.Element | -### markActiveChannelReadOn - -Configuration that determines when and whether a channel is marked read upon clicking ChannelPreview. -1. `MarkChannelReadOn.never`: Prevents a channel from being marked read when any ChannelPreview is clicked. -2. `MarkChannelReadOn.leave`: Marks active channel read before switching the active channel state to the clicked preview's channel. -This means that active channel being left is marked read before navigating to another channel. -3. `MarkChannelReadOn.reenter`: Channel, which is re-entered by clicking the preview, is marked read. That means: -- an active channel can be marked unread, left and on return marked read. -- a non-active channel receives a new message, is entered, left and re-entered and marked read. - -The default configuration is set to `MarkChannelReadOn.reenter`. - -| Type | Default | -|------|-----------------------------| -| enum | `MarkChannelReadOn.reenter` | - ### messageDeliveryStatus Status describing whether own message has been delivered or read by another. If the last message is not an own message, then the status is undefined. The value is calculated from `channel.read` data on mount and updated on every `message.new` resp. `message.read` WS event. diff --git a/docusaurus/docs/React/guides/channel-read-state.mdx b/docusaurus/docs/React/guides/channel-read-state.mdx index 161a8abb0..533c370e2 100644 --- a/docusaurus/docs/React/guides/channel-read-state.mdx +++ b/docusaurus/docs/React/guides/channel-read-state.mdx @@ -9,7 +9,7 @@ This guide intends to provide an overview how channel read state is handled by d ## The model -The React SDK maintains channel read state for UI components inside `Channel` componet in a separate variable `channelUnreadUiState`. Channel read state reflecting the back-end state, can be accessed via `channel.state.read` mapping. +The React SDK maintains channel read state for UI components inside `Channel` component in a separate variable `channelUnreadUiState`. Channel read state reflecting the back-end state, can be accessed via `channel.state.read` mapping. ### Channel UI unread state @@ -69,7 +69,7 @@ import { useChannelActionContext } from 'stream-chat-react'; const MarkReadButton = (props) => { const { markRead } = useChannelActionContext(); - return + return }; ``` @@ -91,7 +91,6 @@ The default components included in **marking a channel read**: | Component | Description | |-----------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | [`Channel`](../../components/core-components/channel) | Can be configured to mark active channel read when mounted. This can be done through its prop `markReadOnMount`. By default disabled. | -| [`ChannelPreviewMessenger`](../../components/utility-components/channel_preview_ui) | Can be configured to mark active channel read when re-entered or left or disabled. This can be done through the prop `markActiveChannelReadOn`. By default channel is marked read on re-enter. | | [`MessageList`](../../components/core-components/message_list), [`VirtualizedMessageList`](../../components/core-components/virtualized_list) | Can be configured to mark channel read when message list is scrolled to the bottom. This can be done through the list's prop `markReadOnScrolledToBottom`. By default disabled. | | [`UnreadMessagesNotification`](../../components/contexts/component_context#unreadmessagesnotification) | Floating notification rendered in the message list. Contains a button, which when clicked, marks the channel read. | @@ -118,7 +117,7 @@ Message threads do not participate in handling read state of a channel. Thread r The channel is marked read in the following scenarios: -1. User enters a channel with unread messages, leaves and when returns back the channel is marked read. +1. User enters a channel with unread messages if `Channel` prop `markReadOnMount` is enabled (default behavior). 2. User clicks the button on the default `UnreadMessagesNotification` component to mark channel read. The channel is marked unread in the following scenarios: @@ -136,32 +135,13 @@ There is a possibility to configure when a channel is marked read by tweaking th | Component | Prop | |-----------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------| | [`Channel`](../../components/core-components/channel) | `markReadOnMount` (by default disabled) | -| [`ChannelPreviewMessenger`](../../components/utility-components/channel_preview_ui) | `markActiveChannelReadOn` (`MarkActiveChannelOn.reenter`) | | [`MessageList`](../../components/core-components/message_list), [`VirtualizedMessageList`](../../components/core-components/virtualized_list) | `markReadOnScrolledToBottom` (by default disabled) | -And so instead of marking a channel read on re-enter or when leaving the given channel, the channel can be marked read when scrolled to the bottom or immediately when mounted. - -To disable marking a channel read when `ChannelPreview` is clicked, we need to provide a custom `Preview` component that renders the default: - -```tsx -import { - ChannelList, - ChannelPreviewMessenger, - ChannelPreviewUIComponentProps, - MarkActiveChannelReadOn, -} from 'stream-chat-react'; - -const Preview = (props: ChannelPreviewUIComponentProps) => - - -const Sidebar = () => ( - -); -``` +And so instead of marking a channel read on `Channel` component mount, the channel can be marked read when scrolled to the bottom. ### Customization through custom components -Aside from the custom `Preview` component, we can override the following components via `Channel`'s component context: +We can override the following components via `Channel`'s component context: #### Custom `UnreadMessagesSeparator` component diff --git a/src/components/ChannelPreview/ChannelPreview.tsx b/src/components/ChannelPreview/ChannelPreview.tsx index 29d728efb..7697935b7 100644 --- a/src/components/ChannelPreview/ChannelPreview.tsx +++ b/src/components/ChannelPreview/ChannelPreview.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useState } from 'react'; -import { ChannelPreviewMessenger, MarkChannelReadOn } from './ChannelPreviewMessenger'; +import { ChannelPreviewMessenger } from './ChannelPreviewMessenger'; import { useIsChannelMuted } from './hooks/useIsChannelMuted'; import { useChannelPreviewInfo } from './hooks/useChannelPreviewInfo'; import { getLatestMessagePreview } from './utils'; @@ -30,21 +30,6 @@ export type ChannelPreviewUIComponentProps< lastMessage?: StreamMessage; /** Latest message preview to display, will be a string or JSX element supporting markdown. */ latestMessage?: string | JSX.Element; - /** - * Configuration that determines when and whether a channel is marked read upon clicking ChannelPreview. - * 1. MarkChannelReadOn.never: - * Prevents a channel from being marked read when any ChannelPreview is clicked. - * 2. MarkChannelReadOn.leave: - * Marks active channel read before switching the active channel state to the clicked preview's channel. - * This means that active channel being left is marked read before navigating to another channel. - * 3. MarkChannelReadOn.reenter: - * Channel, which is re-entered by clicking the preview, is marked read. - * That means - * 1. an active channel can be marked unread, left and on return marked read. - * 2. a non-active channel receives a new message, is entered, left and re-entered and marked read. - * The default configuration is set to MarkChannelReadOn.reenter. - */ - markActiveChannelReadOn?: MarkChannelReadOn; /** Status describing whether own message has been delivered or read by another. If the last message is not an own message, then the status is undefined. */ messageDeliveryStatus?: MessageDeliveryStatus; /** Number of unread Messages */ diff --git a/src/components/ChannelPreview/ChannelPreviewMessenger.tsx b/src/components/ChannelPreview/ChannelPreviewMessenger.tsx index 62d0a0f95..8308dfda4 100644 --- a/src/components/ChannelPreview/ChannelPreviewMessenger.tsx +++ b/src/components/ChannelPreview/ChannelPreviewMessenger.tsx @@ -1,19 +1,11 @@ -import React, { useEffect, useRef } from 'react'; +import React, { useRef } from 'react'; import clsx from 'clsx'; import { Avatar as DefaultAvatar } from '../Avatar'; -import { useChatContext } from '../../context'; - -import type { Event } from 'stream-chat'; import type { ChannelPreviewUIComponentProps } from './ChannelPreview'; import type { DefaultStreamChatGenerics } from '../../types/types'; -export enum MarkChannelReadOn { - 'leave', - 'reenter', -} - const UnMemoizedChannelPreviewMessenger = < StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics >( @@ -21,62 +13,27 @@ const UnMemoizedChannelPreviewMessenger = < ) => { const { active, - activeChannel, Avatar = DefaultAvatar, channel, className: customClassName = '', displayImage, displayTitle, latestMessage, - markActiveChannelReadOn, onSelect: customOnSelectChannel, setActiveChannel, unread, watchers, } = props; - const { client } = useChatContext('ChannelPreviewMessenger'); const channelPreviewButton = useRef(null); + const avatarName = displayTitle || channel.state.messages[channel.state.messages.length - 1]?.user?.id; - const previouslyClicked = useRef(active); - - const handleMarkReadOnReenter = () => { - if (!client.user) return; - const ownReadState = channel.state.read[client.user.id]; - if (!previouslyClicked.current) { - previouslyClicked.current = true; - } else if ( - !active && - (ownReadState?.first_unread_message_id || ownReadState?.unread_messages > 0) && - previouslyClicked.current - ) { - channel.markRead(); - } - }; - - const handleMarkReadOnLeave = () => { - if (!(client.user && activeChannel)) return; - const ownReadState = activeChannel.state.read[client.user.id]; - if (ownReadState?.first_unread_message_id || ownReadState?.unread_messages > 0) { - activeChannel.markRead(); - } - }; - const onSelectChannel = (e: React.MouseEvent) => { if (customOnSelectChannel) { customOnSelectChannel(e); } else if (setActiveChannel) { - // eslint-disable-next-line default-case - switch (markActiveChannelReadOn) { - case MarkChannelReadOn.leave: - handleMarkReadOnLeave(); - break; - case MarkChannelReadOn.reenter: - handleMarkReadOnReenter(); - break; - } setActiveChannel(channel, watchers); } if (channelPreviewButton?.current) { @@ -84,22 +41,6 @@ const UnMemoizedChannelPreviewMessenger = < } }; - useEffect(() => { - if (markActiveChannelReadOn !== MarkChannelReadOn.reenter) return; - const handleEvent = (event: Event) => { - if (active) return; - if (channel.cid !== event.cid) return; - if (event.type === 'notification.mark_unread' && event.user?.id !== client.user?.id) return; - previouslyClicked.current = false; - }; - channel.on('notification.mark_unread', handleEvent); - channel.on('message.new', handleEvent); - return () => { - channel.off('notification.mark_unread', handleEvent); - channel.off('message.new', handleEvent); - }; - }, [active, channel, client, markActiveChannelReadOn, previouslyClicked]); - return (