Skip to content

Commit

Permalink
Merge pull request #2862 from GetStream/develop
Browse files Browse the repository at this point in the history
Next Release
  • Loading branch information
khushal87 authored Dec 24, 2024
2 parents 01b1e4f + d0ada39 commit ca0668c
Show file tree
Hide file tree
Showing 44 changed files with 2,140 additions and 1,202 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
[![NPM](https://img.shields.io/npm/v/stream-chat-react-native.svg)](https://www.npmjs.com/package/stream-chat-react-native)
[![Build Status](https://github.com/GetStream/stream-chat-react-native/actions/workflows/release.yml/badge.svg)](https://github.com/GetStream/stream-chat-react-native/actions)
[![Component Reference](https://img.shields.io/badge/docs-component%20reference-blue.svg)](https://getstream.io/chat/docs/sdk/reactnative)
![JS Bundle Size](https://img.shields.io/badge/js_bundle_size-456%20KB-blue)
![JS Bundle Size](https://img.shields.io/badge/js_bundle_size-460%20KB-blue)

<img align="right" src="https://getstream.imgix.net/images/ios-chat-tutorial/[email protected]?auto=format,enhance" width="50%" />

Expand Down
10 changes: 5 additions & 5 deletions examples/SampleApp/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2164,7 +2164,7 @@ PODS:
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.10)
- SocketRocket (0.7.1)
- stream-chat-react-native (6.0.0):
- stream-chat-react-native (6.0.1):
- DoubleConversion
- glog
- hermes-engine
Expand Down Expand Up @@ -2474,7 +2474,7 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
boost: 1dca942403ed9342f98334bf4c3621f011aa7946
DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385
DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5
FBLazyVector: 1bf99bb46c6af9a2712592e707347315f23947aa
Firebase: 7a56fe4f56b5ab81b86a6822f5b8f909ae6fc7e2
FirebaseAnalytics: 2f4a11eeb7a0e9c6fcf642d4e6aaca7fa4d38c28
Expand All @@ -2488,7 +2488,7 @@ SPEC CHECKSUMS:
FirebaseRemoteConfigInterop: e75e348953352a000331eb77caf01e424248e176
FirebaseSessions: b252b3f91a51186188882ea8e7e1730fc1eee391
fmt: 10c6e61f4be25dc963c36bd73fc7b1705fe975be
glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a
glog: 69ef571f3de08433d766d614c73a9838a06bf7eb
GoogleAppMeasurement: ee5c2d2242816773fbf79e5b0563f5355ef1c315
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
Expand Down Expand Up @@ -2576,9 +2576,9 @@ SPEC CHECKSUMS:
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
stream-chat-react-native: 557a9b07b068fea9a1670302ca43f8589d884e33
stream-chat-react-native: 4b3bb162446ad9b25c745fc8083a2516d363d5eb
Yoga: 7548e4449365bf0ef60db4aefe58abff37fcabec

PODFILE CHECKSUM: 4f662370295f8f9cee909f1a4c59a614999a209d

COCOAPODS: 1.14.3
COCOAPODS: 1.16.2
8 changes: 4 additions & 4 deletions examples/SampleApp/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7952,10 +7952,10 @@ statuses@~1.5.0:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==

[email protected].0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-6.0.0.tgz#77798c7082877572ef70223e1f799d22f0c78fe7"
integrity sha512-3cFao8iL2MjP7nhVRAl1vi526FbPlqUj4BHnYQ7sUNe+xb4z/HCEL6fKFh8kIfK5MEAacOQO4juPPQktoIf7zg==
[email protected].1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-6.0.1.tgz#a67f14685519cafa58466d28eee8f1edc9dbafcf"
integrity sha512-kyHgGn2PF+JTt7eEKdHMot9Nxzx+yecnlut9oyhi/IJbxOwpjIgB87+rdQXEI5o8SeNwQuAeV3VatxGaxl5Jbw==
dependencies:
"@gorhom/bottom-sheet" "^5.0.6"
dayjs "1.10.5"
Expand Down
126 changes: 102 additions & 24 deletions package/src/components/Channel/Channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
Channel as ChannelType,
EventHandler,
FormatMessageResponse,
logChatPromiseExecution,
MessageResponse,
Reaction,
SendMessageAPIResponse,
Expand Down Expand Up @@ -92,7 +91,7 @@ import {
isImagePickerAvailable,
} from '../../native';
import * as dbApi from '../../store/apis';
import { DefaultStreamChatGenerics, FileTypes } from '../../types/types';
import { ChannelUnreadState, DefaultStreamChatGenerics, FileTypes } from '../../types/types';
import { addReactionToLocalState } from '../../utils/addReactionToLocalState';
import { compressedImageURI } from '../../utils/compressImage';
import { DBSyncManager } from '../../utils/DBSyncManager';
Expand Down Expand Up @@ -179,6 +178,7 @@ import { ScrollToBottomButton as ScrollToBottomButtonDefault } from '../MessageL
import { StickyHeader as StickyHeaderDefault } from '../MessageList/StickyHeader';
import { TypingIndicator as TypingIndicatorDefault } from '../MessageList/TypingIndicator';
import { TypingIndicatorContainer as TypingIndicatorContainerDefault } from '../MessageList/TypingIndicatorContainer';
import { UnreadMessagesNotification as UnreadMessagesNotificationDefault } from '../MessageList/UnreadMessagesNotification';
import { MessageActionList as MessageActionListDefault } from '../MessageMenu/MessageActionList';
import { MessageActionListItem as MessageActionListItemDefault } from '../MessageMenu/MessageActionListItem';
import { MessageMenu as MessageMenuDefault } from '../MessageMenu/MessageMenu';
Expand All @@ -188,6 +188,15 @@ import { MessageUserReactionsAvatar as MessageUserReactionsAvatarDefault } from
import { MessageUserReactionsItem as MessageUserReactionsItemDefault } from '../MessageMenu/MessageUserReactionsItem';
import { Reply as ReplyDefault } from '../Reply/Reply';

export type MarkReadFunctionOptions = {
/**
* Signal, whether the `channelUnreadUiState` should be updated.
* By default, the local state update is prevented when the Channel component is mounted.
* This is in order to keep the UI indicating the original unread state, when the user opens a channel.
*/
updateChannelUnreadState?: boolean;
};

const styles = StyleSheet.create({
selectChannel: { fontWeight: 'bold', padding: 16 },
});
Expand Down Expand Up @@ -301,6 +310,7 @@ export type ChannelPropsWithContext<
| 'handleDelete'
| 'handleEdit'
| 'handleFlag'
| 'handleMarkUnread'
| 'handleMute'
| 'handlePinMessage'
| 'handleReaction'
Expand Down Expand Up @@ -360,6 +370,7 @@ export type ChannelPropsWithContext<
| 'VideoThumbnail'
| 'PollContent'
| 'hasCreatePoll'
| 'UnreadMessagesNotification'
| 'StreamingMessageView'
>
> &
Expand All @@ -384,7 +395,10 @@ export type ChannelPropsWithContext<
* Overrides the Stream default mark channel read request (Advanced usage only)
* @param channel Channel object
*/
doMarkReadRequest?: (channel: ChannelType<StreamChatGenerics>) => void;
doMarkReadRequest?: (
channel: ChannelType<StreamChatGenerics>,
setChannelUnreadUiState?: (state: ChannelUnreadState) => void,
) => void;
/**
* Overrides the Stream default send message request (Advanced usage only)
* @param channelId
Expand Down Expand Up @@ -433,6 +447,10 @@ export type ChannelPropsWithContext<
* Custom loading error indicator to override the Stream default
*/
LoadingErrorIndicator?: React.ComponentType<LoadingErrorProps>;
/**
* Boolean flag to enable/disable marking the channel as read on mount
*/
markReadOnMount?: boolean;
maxMessageLength?: number;
/**
* Load the channel at a specified message instead of the most recent message.
Expand Down Expand Up @@ -529,6 +547,7 @@ const ChannelWithContext = <
handleDelete,
handleEdit,
handleFlag,
handleMarkUnread,
handleMute,
handlePinMessage,
handleQuotedReply,
Expand Down Expand Up @@ -566,6 +585,7 @@ const ChannelWithContext = <
loadingMore: loadingMoreProp,
loadingMoreRecent: loadingMoreRecentProp,
markdownRules,
markReadOnMount = true,
maxMessageLength: maxMessageLengthProp,
maxNumberOfFiles = 10,
maxTimeBetweenGroupedMessages,
Expand Down Expand Up @@ -647,6 +667,7 @@ const ChannelWithContext = <
threadMessages,
TypingIndicator = TypingIndicatorDefault,
TypingIndicatorContainer = TypingIndicatorContainerDefault,
UnreadMessagesNotification = UnreadMessagesNotificationDefault,
UploadProgressIndicator = UploadProgressIndicatorDefault,
UrlPreview = CardDefault,
VideoThumbnail = VideoThumbnailDefault,
Expand Down Expand Up @@ -674,10 +695,13 @@ const ChannelWithContext = <
const [thread, setThread] = useState<MessageType<StreamChatGenerics> | null>(threadProps || null);
const [threadHasMore, setThreadHasMore] = useState(true);
const [threadLoadingMore, setThreadLoadingMore] = useState(false);
const [channelUnreadState, setChannelUnreadState] = useState<ChannelUnreadState | undefined>(
undefined,
);

const syncingChannelRef = useRef(false);

const { setTargetedMessage, targetedMessage } = useTargetedMessage();
const { highlightedMessageId, setTargetedMessage, targetedMessage } = useTargetedMessage();

/**
* This ref will hold the abort controllers for
Expand All @@ -692,6 +716,7 @@ const ChannelWithContext = <
const {
copyStateFromChannel,
initStateFromChannel,
setRead,
setTyping,
state: channelState,
} = useChannelDataState<StreamChatGenerics>(channel);
Expand Down Expand Up @@ -754,6 +779,22 @@ const ChannelWithContext = <
}
}

if (event.type === 'notification.mark_unread') {
setChannelUnreadState((prev) => {
if (!(event.last_read_at && event.user)) return prev;
return {
first_unread_message_id: event.first_unread_message_id,
last_read: new Date(event.last_read_at),
last_read_message_id: event.last_read_message_id,
unread_messages: event.unread_messages ?? 0,
};
});
}

if (event.type === 'channel.truncated' && event.cid === channel.cid) {
setChannelUnreadState(undefined);
}

// only update channel state if the events are not the previously subscribed useEffect's subscription events
if (channel && channel.initialized) {
copyChannelState();
Expand All @@ -764,6 +805,8 @@ const ChannelWithContext = <
useEffect(() => {
let listener: ReturnType<typeof channel.on>;
const initChannel = async () => {
setLastRead(new Date());
const unreadCount = channel.countUnread();
if (!channel || !shouldSyncChannel || channel.offlineMode) return;
let errored = false;

Expand All @@ -782,14 +825,33 @@ const ChannelWithContext = <
loadInitialMessagesStateFromChannel(channel, channel.state.messagePagination.hasPrev);
}

if (client.user?.id && channel.state.read[client.user.id]) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { user, ...ownReadState } = channel.state.read[client.user.id];
setChannelUnreadState(ownReadState);
}

if (messageId) {
await loadChannelAroundMessage({ messageId, setTargetedMessage });
} else if (
initialScrollToFirstUnreadMessage &&
channel.countUnread() > scrollToFirstUnreadThreshold
client.user &&
unreadCount > scrollToFirstUnreadThreshold
) {
await loadChannelAtFirstUnreadMessage({ setTargetedMessage });
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { user, ...ownReadState } = channel.state.read[client.user.id];

await loadChannelAtFirstUnreadMessage({
channelUnreadState: ownReadState,
setChannelUnreadState,
setTargetedMessage,
});
}

if (unreadCount > 0 && markReadOnMount) {
await markRead({ updateChannelUnreadState: false });
}

listener = channel.on(handleEvent);
};

Expand Down Expand Up @@ -819,12 +881,12 @@ const ChannelWithContext = <
*/
useEffect(() => {
const handleEvent: EventHandler<StreamChatGenerics> = (event) => {
if (channel.cid === event.cid) copyChannelState();
if (channel.cid === event.cid) setRead(channel);
};

const { unsubscribe } = client.on('notification.mark_read', handleEvent);
return unsubscribe;
}, [channel.cid, client, copyChannelState]);
}, [channel, client, setRead]);

const threadPropsExists = !!threadProps;

Expand Down Expand Up @@ -858,23 +920,33 @@ const ChannelWithContext = <
/**
* CHANNEL METHODS
*/
const markRead: ChannelContextValue<StreamChatGenerics>['markRead'] = useRef(
throttle(
() => {
if (!channel || channel?.disconnected || !clientChannelConfig?.read_events) {
return;
}
const markRead: ChannelContextValue<StreamChatGenerics>['markRead'] = throttle(
async (options?: MarkReadFunctionOptions) => {
const { updateChannelUnreadState = true } = options ?? {};
if (!channel || channel?.disconnected || !clientChannelConfig?.read_events) {
return;
}

if (doMarkReadRequest) {
doMarkReadRequest(channel);
} else {
logChatPromiseExecution(channel.markRead(), 'mark read');
if (doMarkReadRequest) {
doMarkReadRequest(channel, updateChannelUnreadState ? setChannelUnreadState : undefined);
} else {
try {
const response = await channel.markRead();
if (updateChannelUnreadState && response && lastRead) {
setChannelUnreadState({
last_read: lastRead,
last_read_message_id: response?.event.last_read_message_id,
unread_messages: 0,
});
}
} catch (err) {
console.log('Error marking channel as read:', err);
}
},
defaultThrottleInterval,
throttleOptions,
),
).current;
}
},
defaultThrottleInterval,
throttleOptions,
);

const reloadThread = async () => {
if (!channel || !thread?.id) return;
Expand Down Expand Up @@ -1596,8 +1668,9 @@ const ChannelWithContext = <
overrideCapabilities: overrideOwnCapabilities,
});

const channelContext = useCreateChannelContext({
const channelContext = useCreateChannelContext<StreamChatGenerics>({
channel,
channelUnreadState,
disabled: !!channel?.data?.frozen,
EmptyStateIndicator,
enableMessageGroupingByUser,
Expand All @@ -1608,9 +1681,11 @@ const ChannelWithContext = <
!!(clientChannelConfig?.commands || [])?.some((command) => command.name === 'giphy'),
hideDateSeparators,
hideStickyDateHeader,
highlightedMessageId,
isChannelActive: shouldSyncChannel,
lastRead,
loadChannelAroundMessage,
loadChannelAtFirstUnreadMessage,
loading: channelMessagesState.loading,
LoadingIndicator,
markRead,
Expand All @@ -1620,6 +1695,7 @@ const ChannelWithContext = <
read: channelState.read ?? {},
reloadChannel,
scrollToFirstUnreadThreshold,
setChannelUnreadState,
setLastRead,
setTargetedMessage,
StickyHeader,
Expand Down Expand Up @@ -1748,6 +1824,7 @@ const ChannelWithContext = <
handleDelete,
handleEdit,
handleFlag,
handleMarkUnread,
handleMute,
handlePinMessage,
handleQuotedReply,
Expand Down Expand Up @@ -1815,6 +1892,7 @@ const ChannelWithContext = <
targetedMessage,
TypingIndicator,
TypingIndicatorContainer,
UnreadMessagesNotification,
updateMessage,
UrlPreview,
VideoThumbnail,
Expand Down
Loading

0 comments on commit ca0668c

Please sign in to comment.