Skip to content

Commit

Permalink
fix(chat): Add emoji shortcodes to message reaction labels (bigbluebu…
Browse files Browse the repository at this point in the history
  • Loading branch information
JoVictorNunes authored Dec 11, 2024
1 parent 12a2261 commit 7270094
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 99 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,8 @@
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import emojiData from '@emoji-mart/data';
import Styled from './styles';
import useCurrentUser from '/imports/ui/core/hooks/useCurrentUser';
import TooltipContainer from '/imports/ui/components/common/tooltip/container';

const intlMessages = defineMessages({
reactedBy: {
id: 'app.chat.toolbar.reactions.reactedByLabel',
},
you: {
id: 'app.chat.toolbar.reactions.youLabel',
},
and: {
id: 'app.chat.toolbar.reactions.andLabel',
},
findAReaction: {
id: 'app.chat.toolbar.reactions.findReactionButtonLabel',
},
});
import ReactionItem from './reaction-item/component';

interface ChatMessageReactionsProps {
reactions: {
Expand All @@ -42,6 +27,7 @@ type ReactionItem = {
reactionEmoji: string;
reactionEmojiId: string;
leastRecent: number;
shortcodes: string;
}

const sortByCount = (r1: ReactionItem, r2: ReactionItem) => r2.count - r1.count;
Expand All @@ -53,7 +39,6 @@ const ChatMessageReactions: React.FC<ChatMessageReactionsProps> = (props) => {
} = props;

const { data: currentUser } = useCurrentUser((u) => ({ userId: u.userId }));
const intl = useIntl();

if (reactions.length === 0) return null;

Expand All @@ -75,6 +60,8 @@ const ChatMessageReactions: React.FC<ChatMessageReactionsProps> = (props) => {
reactionEmoji,
reactionEmojiId,
leastRecent: new Date(createdAt).getTime(),
// @ts-ignore
shortcodes: emojiData.emojis[reactionEmojiId].skins[0].shortcodes,
};
return newValue;
}
Expand All @@ -91,53 +78,21 @@ const ChatMessageReactions: React.FC<ChatMessageReactionsProps> = (props) => {

return (
<Styled.ReactionsWrapper>
{Object.values(reactionItems).sort(sortByLeastRecent).sort(sortByCount).map((details) => {
const {
count,
reactedByMe,
reactionEmoji,
reactionEmojiId,
userNames,
} = details;
let label = intl.formatMessage(intlMessages.reactedBy);
if (userNames.length) {
const users = userNames.join(', ');
label += ` ${users}`;

if (reactedByMe) {
label += ` ${intl.formatMessage(intlMessages.and)} ${intl.formatMessage(intlMessages.you)}`;
}
} else if (reactedByMe) {
label += ` ${intl.formatMessage(intlMessages.you)}`;
}

return (
<TooltipContainer title={label} key={reactionEmojiId}>
<Styled.EmojiWrapper
highlighted={reactedByMe}
onClick={() => {
if (reactedByMe) {
deleteReaction(reactionEmoji, reactionEmojiId, chatId, messageId);
} else {
sendReaction(reactionEmoji, reactionEmojiId, chatId, messageId);
}
}}
>
<em-emoji
size={parseFloat(
window.getComputedStyle(document.documentElement).fontSize,
)}
emoji={{
id: reactionEmojiId,
native: reactionEmoji,
}}
native={reactionEmoji}
/>
<span>{count}</span>
</Styled.EmojiWrapper>
</TooltipContainer>
);
})}
{Object.values(reactionItems).sort(sortByLeastRecent).sort(sortByCount).map((details) => (
<ReactionItem
chatId={chatId}
count={details.count}
deleteReaction={deleteReaction}
messageId={messageId}
reactedByMe={details.reactedByMe}
reactionEmoji={details.reactionEmoji}
reactionEmojiId={details.reactionEmojiId}
sendReaction={sendReaction}
shortcodes={details.shortcodes}
userNames={details.userNames}
key={details.reactionEmojiId}
/>
))}
</Styled.ReactionsWrapper>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { useId } from 'react';
import { capitalize } from 'radash';
import TooltipContainer from '/imports/ui/components/common/tooltip/container';
import { defineMessages, useIntl } from 'react-intl';
import Styled from './styles';

const intlMessages = defineMessages({
reactionLabel: {
id: 'app.chat.toolbar.reactions.reactionLabel',
},
you: {
id: 'app.chat.toolbar.reactions.youLabel',
},
and: {
id: 'app.chat.toolbar.reactions.andLabel',
},
});

interface ReactionItemProps {
count: number;
userNames: string[];
reactedByMe: boolean;
reactionEmoji: string;
reactionEmojiId: string;
shortcodes: string;
sendReaction(reactionEmoji: string, reactionEmojiId: string, chatId: string, messageId: string): void;
deleteReaction(reactionEmoji: string, reactionEmojiId: string, chatId: string, messageId: string): void;
chatId: string;
messageId: string;
}

const ReactionItem: React.FC<ReactionItemProps> = (props) => {
const {
count,
reactedByMe,
reactionEmoji,
reactionEmojiId,
userNames,
shortcodes,
chatId,
messageId,
deleteReaction,
sendReaction,
} = props;

const intl = useIntl();
const id = useId();

let usersLabel = '';
if (userNames.length) {
const users = userNames.join(', ');
usersLabel += users;

if (reactedByMe) {
usersLabel += ` ${intl.formatMessage(intlMessages.and)} ${intl.formatMessage(intlMessages.you)}`;
}
} else if (reactedByMe) {
usersLabel += capitalize(intl.formatMessage(intlMessages.you));
}

const label = intl.formatMessage(intlMessages.reactionLabel, {
0: usersLabel,
1: shortcodes,
});

return (
<TooltipContainer title={label} key={reactionEmojiId}>
<Styled.EmojiWrapper
aria-describedby={id}
highlighted={reactedByMe}
onClick={() => {
if (reactedByMe) {
deleteReaction(reactionEmoji, reactionEmojiId, chatId, messageId);
} else {
sendReaction(reactionEmoji, reactionEmojiId, chatId, messageId);
}
}}
>
<em-emoji
size={parseFloat(
window.getComputedStyle(document.documentElement).fontSize,
)}
emoji={{
id: reactionEmojiId,
native: reactionEmoji,
}}
native={reactionEmoji}
/>
<span>{count}</span>
<span className="sr-only" id={id}>{label}</span>
</Styled.EmojiWrapper>
</TooltipContainer>
);
};

export default ReactionItem;
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import styled from 'styled-components';
import { colorGrayLightest, colorOffWhite, colorGrayLighter } from '/imports/ui/stylesheets/styled-components/palette';

const EmojiWrapper = styled.button<{ highlighted: boolean }>`
background: none;
border-radius: 1rem;
padding: 0.375rem 1rem;
line-height: 1;
display: flex;
flex-wrap: nowrap;
border: 1px solid ${colorGrayLightest};
cursor: pointer;
${({ highlighted }) => highlighted && `
background-color: ${colorOffWhite};
`}
em-emoji {
[dir='ltr'] & {
margin-right: 0.25rem;
}
[dir='rtl'] & {
margin-left: 0.25rem;
}
}
&:hover {
border: 1px solid ${colorGrayLighter};
}
`;

export default {
EmojiWrapper,
};
Original file line number Diff line number Diff line change
@@ -1,36 +1,4 @@
import styled from 'styled-components';
import {
colorGrayLighter, colorGrayLightest, colorOffWhite,
} from '/imports/ui/stylesheets/styled-components/palette';

const EmojiWrapper = styled.button<{ highlighted: boolean }>`
background: none;
border-radius: 1rem;
padding: 0.375rem 1rem;
line-height: 1;
display: flex;
flex-wrap: nowrap;
border: 1px solid ${colorGrayLightest};
cursor: pointer;
${({ highlighted }) => highlighted && `
background-color: ${colorOffWhite};
`}
em-emoji {
[dir='ltr'] & {
margin-right: 0.25rem;
}
[dir='rtl'] & {
margin-left: 0.25rem;
}
}
&:hover {
border: 1px solid ${colorGrayLighter};
}
`;

const ReactionsWrapper = styled.div`
display: flex;
Expand All @@ -40,6 +8,5 @@ const ReactionsWrapper = styled.div`
`;

export default {
EmojiWrapper,
ReactionsWrapper,
};
2 changes: 1 addition & 1 deletion bigbluebutton-html5/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"app.chat.toolbar.reply": "Reply to message {0}",
"app.chat.toolbar.edit": "Edit",
"app.chat.toolbar.delete": "Delete",
"app.chat.toolbar.reactions.reactedByLabel": "Reacted by",
"app.chat.toolbar.reactions.reactionLabel": "{0} reacted with {1}",
"app.chat.toolbar.reactions.youLabel": "you",
"app.chat.toolbar.reactions.andLabel": "and",
"app.chat.toolbar.reactions.findReactionButtonLabel": "Find a reaction",
Expand Down

0 comments on commit 7270094

Please sign in to comment.