Skip to content

Commit

Permalink
fix: anonymous convo (#195)
Browse files Browse the repository at this point in the history
Co-authored-by: Borys Juskiw <[email protected]>
  • Loading branch information
EvilProfesseur and Borys Juskiw authored May 27, 2024
1 parent a2e6dd1 commit 39ae17a
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 47 deletions.
16 changes: 11 additions & 5 deletions frontend/src/apps/chat/convo-snippet/convo-snippet.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { FC, useMemo } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import classNames from 'classnames';
import dayjs from 'dayjs';
import { useIntl } from 'react-intl';
import { Link, useParams } from 'react-router-dom';
import { IConversation } from '../../../models/message';
import { Conversation } from '../../../shared/components/messaging/conversation/conversation';
Expand All @@ -12,12 +14,12 @@ import { useMessagesService } from '../../../shared/services/messages.service';
import MemoizedFormattedMessage from 'react-intl/src/components/message';

import './convo-snippet.scss';
import dayjs from 'dayjs';

export const ConvoSnippet: FC<{
convo: IConversation;
delayMultiplier: number;
}> = ({ convo, delayMultiplier }) => {
const intl = useIntl();
const { chatId } = useParams();
const { generateAnimation } = useStandardizedAnimation();
const { convoHasUnreadMessages } = useMessagesService();
Expand All @@ -44,9 +46,13 @@ export const ConvoSnippet: FC<{
}, [currentUser, convo.participantsAllowedToSendMsgs]);

const otherParty = () => {
const others = convo.participants.filter(
(participant) => participant !== currentUser?.handle
);
const others = convo.participants
.filter((participant) => participant !== currentUser?.handle)
.map((participant) =>
convo.anonymizedUsers.includes(participant)
? intl.formatMessage({ id: 'ANONYMOUS' })
: participant
);

if (others.length === 1) {
return others[0];
Expand All @@ -62,7 +68,7 @@ export const ConvoSnippet: FC<{

if (diff === 0) {
return date.format('HH:mm:ss');
}
}
if (diff < 3) {
return `${now.diff(date, 'hours')} hours ago`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Message } from '../message/message';
import { setMessagesAsRead } from '../../../../store/messages.slice';
import { IWebsocketContext } from '../../../providers/websocket.model';
import { useWebSocketContext } from '../../../providers/websocket.provider';
import { useUserService } from '../../../services/user.service';

import './conversation.scss';

Expand All @@ -15,6 +16,7 @@ export const Conversation: FC<{ convo: IConversation; className?: string }> = ({
className
}) => {
const dispatch = useDispatch();
const { currentUser } = useUserService();
const convoWrapper = useRef<HTMLDivElement>(null);
const { lastMessage } = useWebSocketContext() as IWebsocketContext;
const { chatId, gigId } = useParams();
Expand Down Expand Up @@ -47,6 +49,10 @@ export const Conversation: FC<{ convo: IConversation; className?: string }> = ({
[chatId, convo, dispatch, gigId, lastMessage]
);

const senderAnonymized = (sender: string) =>
convo.anonymizedUsers.includes(sender) &&
currentUser?.handle !== sender;

return (
<motion.div
ref={convoWrapper}
Expand All @@ -59,7 +65,12 @@ export const Conversation: FC<{ convo: IConversation; className?: string }> = ({
}}
>
{convo.messages.map((msg) => (
<Message key={msg.id} message={msg} convoId={convo.id} />
<Message
key={msg.id}
message={msg}
convoId={convo.id}
senderAnonymized={senderAnonymized(msg.sender)}
/>
))}
</motion.div>
);
Expand Down
21 changes: 13 additions & 8 deletions frontend/src/shared/components/messaging/message/message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,38 @@ import classNames from 'classnames';
import { IMessage } from '../../../../models/message';
import { useUserService } from '../../../services/user.service';
import { useMessagesService } from '../../../services/messages.service';
import { useIntl } from 'react-intl';

import './message.scss';

export const Message: FC<{ message: IMessage; convoId: string }> = ({
message,
convoId
}) => {
export const Message: FC<{
message: IMessage;
convoId: string;
senderAnonymized?: boolean;
}> = ({ message, convoId, senderAnonymized = false }) => {
const intl = useIntl();
const { currentUser, isInfluencer } = useUserService();
const { isMessageUnread } = useMessagesService();
const messageClassnames = classNames({
message: true,
'message--own': currentUser?.handle === message.sender,
'message--unread': isMessageUnread(convoId, message.id),
'message--unread': isMessageUnread(convoId, message.id)
});
const senderClasses = classNames({
'message__sender': true,
message__sender: true,
'message__sender--influencer': isInfluencer(message.sender)
});
const textClasses = classNames({
'message__text': true,
message__text: true,
'message__text--influencer': isInfluencer(message.sender)
});

return (
<p className={messageClassnames}>
{`${new Date(message.date).toLocaleTimeString()}`}
<span className={senderClasses}>{`<@${message.sender}>`}</span>
<span
className={senderClasses}
>{`<@${senderAnonymized ? intl.formatMessage({ id: 'ANONYMOUS' }) : message.sender}>`}</span>
<span className={textClasses}>{`${message.text.trim()}`}</span>
</p>
);
Expand Down
74 changes: 41 additions & 33 deletions frontend/src/shared/services/messages.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ export function useMessagesService() {
const dispatch = useDispatch();
const intl = useIntl();
const { api } = useApiService();
const { sendMessage } =
useWebSocketContext() as IWebsocketContext;
const { sendMessage } = useWebSocketContext() as IWebsocketContext;
const { displayToast } = useToastService();
const { currentUser } = useUserService();
const [fetchingConvo, setFetchingConvo] = useState(false);
const gigConversations = useSelector(selectGigConversations);
const unreadMessages = useSelector(selectUnreadMessages);
const unreadGigMessages = useSelector(selectUnreadGigMessages)
const unreadGigMessages = useSelector(selectUnreadGigMessages);

const createMessage: (text: string, senderHandle?: string) => IMessage = (
text,
senderHandle
) => {
const createMessage: (
text: string,
senderHandle?: string,
anonymize?: boolean
) => IMessage = (text, senderHandle) => {
return {
id: uuidv4(),
date: dayjs().add(100, 'year').toISOString(),
Expand All @@ -55,41 +55,49 @@ export function useMessagesService() {
id?: string,
anonymize?: boolean
) => Promise<string> = (participants, id, anonymize) =>
new Promise((resolve, reject) => {
const convoId = id ?? uuidv4();
const convo: IConversation = {
id: convoId,
anonymizedUsers: anonymize ? [currentUser!.handle] : [],
gigConversation: false,
participants,
messages: [...createInitialMessages(participants)]
};

api.url('Conversation')
.post(convo)
.json<IConversation>()
.catch(() => reject())
.then((conversation) => {
if (!conversation) {
reject();
return;
}
dispatch(addConversation(conversation));
resolve(conversation.id);
});
});
new Promise((resolve, reject) => {
const convoId = id ?? uuidv4();
const anonymizedUsers = anonymize ? [currentUser!.handle] : [];
const convo: IConversation = {
id: convoId,
anonymizedUsers,
gigConversation: false,
participants,
messages: [...createInitialMessages(participants, anonymize)]
};

api.url('Conversation')
.post(convo)
.json<IConversation>()
.catch(() => reject())
.then((conversation) => {
if (!conversation) {
reject();
return;
}
dispatch(addConversation(conversation));
resolve(conversation.id);
});
});

const getGigConvo = async (gigId: string): Promise<IConversation> => {
return await api
.get(`Gig/get/${gigId}/conversation`)
.json<IConversation>();
};

const createInitialMessages = (participants: string[]): IMessage[] => {
const createInitialMessages = (
participants: string[],
anonymize?: boolean
): IMessage[] => {
const initialMessages: IMessage[] = [];
participants.forEach((participant) => {
const handle =
anonymize && participant === currentUser?.handle
? intl.formatMessage({ id: 'ANONYMOUS' })
: participant;
const message = createMessage(
`<@${participant} ${intl.formatMessage({
`<@${handle} ${intl.formatMessage({
id: 'ENTERED_THE_CHAT'
})}>`,
participant
Expand Down Expand Up @@ -161,7 +169,7 @@ export function useMessagesService() {

const gigConvoHasUnreadMessages = (convoId: string): boolean => {
return unreadGigMessages[convoId]?.length > 0;
}
};

const updateConversationHashes = (
hashes: Record<string, number>,
Expand Down

0 comments on commit 39ae17a

Please sign in to comment.