History visibility for new members
When someone is added to a channel, the app decides how much of the earlier conversation they see: all of it, none of it, or what was sent after a date. This page covers the options that decide it. The Hide history for new members UI cookbook builds a modal that lets the user choose.
What users get
The user adds Bob to the "Design" channel. Depending on how they add him, Bob opens the channel and sees:
- every message, as with any member;
- only the messages sent after he joined;
- only the messages sent after a date the user picked, for example the last seven days.
The choice is made once, when Bob is added. Messages sent after he joins are visible to him either way.
How it works across the layers
State: the options on Channel.addMembers()
Channel.addMembers({ members, ...options }) adds members. Next to members, the request takes two history options:
hide_history: truehides every message sent before the member joined.hide_history_beforehides the messages sent before aDate. The date must be in the past. When both are given,hide_history_beforeapplies.
Without either option, the new member sees the whole history.
// Bob sees nothing sent before he joined.
await channel.addMembers({ members: ["bob"], hide_history: true });
// Carol sees the last seven days.
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
await channel.addMembers({
members: ["carol"],
hide_history_before: sevenDaysAgo,
});hide_history_before is typed as a Date. Pass the Date itself, not a string.
The request also takes message, an optional message that announces the change in the channel, such as { text: "Bob joined the design team" }. Leave it out to add members without one.
The server applies the options. From then on, the channel's messages that the server returns to the new member start at the cutoff, so the client has nothing to filter. The existing members' view doesn't change.
UI: no built-in control
The SDK has no control for these options. The Add form in channel details calls Channel.addMembers({ members }) without them, so members added there see the whole history. To let users choose, call Channel.addMembers() from your own UI, as the UI cookbook does, or replace the Add form's header, as Hiding history in the Add form does.
Turning it on or off
There's nothing to configure. Each Channel.addMembers() call decides for the members it adds.
Adding members needs the update-channel-members capability. Permissions reference explains how the server grants it.
Customizing
Letting the user choose
The Hide history for new members UI cookbook builds a modal with four choices: no history, from today, from the beginning, or from a custom date. It maps each choice to the options above.
Hiding history in the Add form
The Add form's header holds the button that adds the selected users. It's the ChannelAddMembersFormHeader key, and it reads the selection from useChannelAddMembersContext(). This header adds the selected users with hide_history: true:
import { useState } from "react";
import { Button, StyleSheet, Text, View } from "react-native";
import {
useChannelAddMembersContext,
useChannelDetailsContext,
useIsSelectionEmpty,
useNotificationApi,
} from "stream-chat-react-native";
import type {
ChannelAddMembersFormHeaderProps,
ComponentOverrides,
} from "stream-chat-react-native";
const AddMembersHeader = ({ onClose }: ChannelAddMembersFormHeaderProps) => {
const { channel } = useChannelDetailsContext();
const { selectionStore } = useChannelAddMembersContext();
const { addNotification } = useNotificationApi();
const isSelectionEmpty = useIsSelectionEmpty(selectionStore);
const [adding, setAdding] = useState(false);
const add = async () => {
const { selectedIds } = selectionStore.state.getLatestValue();
setAdding(true);
try {
// The new members see nothing sent before they joined.
await channel.addMembers({
hide_history: true,
members: Array.from(selectedIds),
});
onClose();
} catch {
addNotification({
message: "Couldn't add the members",
options: { severity: "error", type: "api:channel:add-members:failed" },
origin: { emitter: "AddMembersHeader" },
});
} finally {
setAdding(false);
}
};
return (
<View style={styles.header}>
<Button onPress={onClose} title="Cancel" />
<Text style={styles.title}>Add Members</Text>
<Button
disabled={isSelectionEmpty || adding}
onPress={() => void add()}
title="Add"
/>
</View>
);
};
// Pass these to WithComponents around ChannelDetails.
export const addMembersOverrides: ComponentOverrides = {
ChannelAddMembersFormHeader: AddMembersHeader,
};
const styles = StyleSheet.create({
header: {
alignItems: "center",
flexDirection: "row",
justifyContent: "space-between",
padding: 16,
},
title: { fontSize: 17, fontWeight: "600" },
});The default header adds the members through useChannelActions(channel).addMembers(), which publishes "N members added" when it succeeds. This one calls the channel directly, so it publishes only its own error notification.
Hiding history for every member your app adds
To apply one rule everywhere your own code adds members, add them through one function of your own:
import type { Channel } from "stream-chat";
// Every member this app adds sees the last 30 days of history.
export const addMembersWithRecentHistory = (
channel: Channel,
userIds: string[],
) => {
const cutoff = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
return channel.addMembers({
members: userIds,
hide_history_before: cutoff,
});
};Reference
- Channel and channel state:
addMembersand the other member methods. - Channel details contexts:
useChannelAddMembersContextand its selection store. - Hide history in the Chat API docs: the server's rules for both options.