Join a Conversation
When you click the "+ button" on your list of joined conversations, the app displays an overlay listing all the other available conversations. Click a conversation to join it and start receiving the messages from that conversation.
The joinedConversations/JoinConversationDialog/JoinConversationDialog.tsx
component displays the dialog with a list of conversations that are available to join.
The component calls the getAllConversations
selector to fetch all conversations from the local store.
It also calls getConversationsByUserId
selector to fetch the user’s current conversations from the local store so the list doesn't display them again.
// Fetch all conversations and remove the ones we're already a member of
const getJoinableConversations = createSelector(
[getAllConversations, getLoggedInUserId, getConversationsByUserId],
(
conversations: Conversation[],
userId: string,
joinedConversations: MembershipHash
): ConversationDescriptionFragment[] => {
return conversations.filter(conversation => {
return !joinedConversations[userId]
.map(conv => conv.id)
.includes(conversation.id);
});
}
);
/**
* Present list to the user of conversations that they could join, but have not.
* Allow the user to select the conversation to join or back out.
*/
const JoinConversationDialog = () => {
const conversations: ConversationDescriptionFragment[] = useSelector(
getJoinableConversations
);
const views = useSelector(getViewStates);
const currentUserId = useSelector(getLoggedInUserId);
const dispatch = useDispatch();
const themeContext = useContext(ThemeContext);
const isSmall = useMediaQuery(themeContext.breakpoint.mediaQuery.small);
return (
<Overlay displayed={views.JoinConversation}>
<Modal
animate={views.JoinConversation ? "open" : "closed"}
variants={getAnimatedModalVariants(isSmall)}
>
<Header>
<Title>Join a Conversation</Title>
<CloseButton
onClick={() => {
dispatch(joinConversationViewHidden());
}}
>
<CrossIcon title="close" />
</CloseButton>
</Header>
<ScrollView>
{conversations.map(conversation => (
<ConversationDescription
key={`conversationDescription-${conversation.id}`}
onClick={() => {
const conversationId = conversation.id;
dispatch(joinConversation(currentUserId, conversationId));
dispatch(joinConversationViewHidden());
}}
conversation={conversation}
/>
))}
</ScrollView>
</Modal>
</Overlay>
);
};
export { JoinConversationDialog }
joinSpaces Command
The joinConversation()
method (in the joinedConversations/joinConversationCommand.ts
file) uses the joinSpaces command from the Redux framework to add the conversation membership for the user.
It also calls pubnub.api.subscribe to subscribe to the conversation channel to start receiving messages on that channel.
export const joinConversation = (
userId: string,
conversationId: string
): ThunkAction<Promise<void>> => {
return (dispatch, getState, context) => {
return dispatch(
joinSpaces({
userId: userId,
spaces: [{ id: conversationId }]
})
).then(() => {
context.pubnub.api.subscribe({
channels: [conversationId],
withPresence: true
});
dispatch(focusOnConversation(conversationId));
});
};
};