Skip to content

Commit

Permalink
feat(Reactions): switch options type to array to guarantee order
Browse files Browse the repository at this point in the history
  • Loading branch information
arnautov-anton committed Feb 20, 2023
1 parent 25188dc commit 2899d72
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 71 deletions.
98 changes: 48 additions & 50 deletions src/components/Reactions/ReactionSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,57 +150,55 @@ const UnMemoizedReactionSelector = React.forwardRef(
</div>
)}
<ul className='str-chat__message-reactions-list str-chat__message-reactions-options'>
{Object.entries(reactionOptions).map(
([reactionType, { Component, name: reactionName }]) => {
const latestUser = getLatestUserForReactionType(reactionType);
const count = reactionCounts && reactionCounts[reactionType];
return (
<li key={`item-${reactionType}`}>
<button
aria-label={`Select Reaction: ${reactionName || reactionType}`}
className={clsx(
'str-chat__message-reactions-list-item str-chat__message-reactions-option',
{
'str-chat__message-reactions-option-selected': iHaveReactedWithReaction(
reactionType,
),
},
)}
data-text={reactionType}
onClick={(event) => handleReaction(reactionType, event)}
>
{!!count && detailedView && (
<div
className='latest-user str-chat__message-reactions-last-user'
onClick={hideTooltip}
onMouseEnter={(e) => showTooltip(e, reactionType)}
onMouseLeave={hideTooltip}
>
{latestUser ? (
<Avatar
image={latestUser.image}
name={latestUser.name}
size={20}
user={latestUser}
/>
) : (
<div className='latest-user-not-found' />
)}
</div>
)}
<span className='str-chat__message-reaction-emoji'>
<Component />
{reactionOptions.map(({ Component, name: reactionName, type: reactionType }) => {
const latestUser = getLatestUserForReactionType(reactionType);
const count = reactionCounts && reactionCounts[reactionType];
return (
<li key={reactionType}>
<button
aria-label={`Select Reaction: ${reactionName || reactionType}`}
className={clsx(
'str-chat__message-reactions-list-item str-chat__message-reactions-option',
{
'str-chat__message-reactions-option-selected': iHaveReactedWithReaction(
reactionType,
),
},
)}
data-text={reactionType}
onClick={(event) => handleReaction(reactionType, event)}
>
{!!count && detailedView && (
<div
className='latest-user str-chat__message-reactions-last-user'
onClick={hideTooltip}
onMouseEnter={(e) => showTooltip(e, reactionType)}
onMouseLeave={hideTooltip}
>
{latestUser ? (
<Avatar
image={latestUser.image}
name={latestUser.name}
size={20}
user={latestUser}
/>
) : (
<div className='latest-user-not-found' />
)}
</div>
)}
<span className='str-chat__message-reaction-emoji'>
<Component />
</span>
{Boolean(count) && detailedView && (
<span className='str-chat__message-reactions-list-item__count'>
{count || ''}
</span>
{Boolean(count) && detailedView && (
<span className='str-chat__message-reactions-list-item__count'>
{count || ''}
</span>
)}
</button>
</li>
);
},
)}
)}
</button>
</li>
);
})}
</ul>
</div>
);
Expand Down
6 changes: 3 additions & 3 deletions src/components/Reactions/ReactionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@ const UnMemoizedReactionsList = <
>
<ul className='str-chat__message-reactions'>
{latestReactionTypes.map((reactionType) => {
const [, Reaction] = getEmojiByReactionType(reactionType) ?? [];
const ReactionOption = getEmojiByReactionType(reactionType);
const isOwnReaction = iHaveReactedWithReaction(reactionType);
return (
Reaction && (
ReactionOption && (
<li
className={clsx('str-chat__message-reaction', {
'str-chat__message-reaction-own': isOwnReaction,
Expand All @@ -118,7 +118,7 @@ const UnMemoizedReactionsList = <
>
{
<span className='str-chat__message-reaction-emoji'>
<Reaction.Component />
<ReactionOption.Component />
</span>
}
&nbsp;
Expand Down
6 changes: 3 additions & 3 deletions src/components/Reactions/SimpleReactionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,13 @@ const UnMemoizedSimpleReactionsList = <
onMouseLeave={() => setTooltipReactionType(undefined)}
>
{latestReactionTypes.map((reactionType, i) => {
const [, Reaction] = getEmojiByReactionType(reactionType) ?? [];
const ReactionOption = getEmojiByReactionType(reactionType);
const isOwnReaction = iHaveReactedWithReaction(reactionType);
const tooltipVisible = tooltipReactionType === reactionType;
const tooltipContent = getUsersPerReactionType(tooltipReactionType)?.join(', ');

return (
Reaction && (
ReactionOption && (
<li
className={clsx('str-chat__simple-reactions-list-item', {
'str-chat__message-reaction-own': isOwnReaction,
Expand All @@ -130,7 +130,7 @@ const UnMemoizedSimpleReactionsList = <
onMouseLeave={() => setTooltipReactionType(undefined)}
title={tooltipContent}
>
<Reaction.Component />
<ReactionOption.Component />
&nbsp;
{tooltipVisible && themeVersion === '1' && (
<div className='str-chat__simple-reactions-list-tooltip'>
Expand Down
6 changes: 3 additions & 3 deletions src/components/Reactions/hooks/useProcessReactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const useProcessReactions = <
);

const getEmojiByReactionType = useCallback(
(reactionType: string) => Object.entries(reactionOptions).find(([rt]) => rt === reactionType),
(reactionType: string) => reactionOptions.find(({ type }) => type === reactionType),
[reactionOptions],
);

Expand All @@ -54,15 +54,15 @@ export const useProcessReactions = <

const supportedReactionMap = useMemo(
() =>
Object.keys(reactionOptions).reduce<Record<string, boolean>>((map, reactionType) => {
reactionOptions.reduce<Record<string, boolean>>((map, { type: reactionType }) => {
map[reactionType] = true;
return map;
}, {}),
[reactionOptions],
);

const supportedReactionsArePresent = useMemo(
() => latestReactionTypes.some((type) => supportedReactionMap[type]),
() => latestReactionTypes.some((reactionType) => supportedReactionMap[reactionType]),
[latestReactionTypes, supportedReactionMap],
);

Expand Down
26 changes: 14 additions & 12 deletions src/components/Reactions/reactionOptions.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
/* eslint-disable sort-keys */
/* eslint-disable react/display-name */
import React from 'react';

import { StreamEmoji } from './StreamEmoji';

export type ReactionOptions = Record<
string,
{ Component: React.ComponentType; aliases?: string[]; name?: string }
>;
export type ReactionOptions = Array<{
Component: React.ComponentType;
type: string;
name?: string;
}>;

export const defaultReactionOptions: ReactionOptions = {
angry: { Component: () => <StreamEmoji fallback='😠' type='angry' />, name: 'Angry' },
haha: { Component: () => <StreamEmoji fallback='πŸ˜‚' type='haha' />, name: 'Joy' },
like: { Component: () => <StreamEmoji fallback='πŸ‘' type='like' />, name: 'Thumbs up' },
love: { Component: () => <StreamEmoji fallback='❀️' type='love' />, name: 'Heart' },
sad: { Component: () => <StreamEmoji fallback='πŸ˜”' type='sad' />, name: 'Sad' },
wow: { Component: () => <StreamEmoji fallback='😲' type='wow' />, name: 'Astonished' },
};
export const defaultReactionOptions: ReactionOptions = [
{ type: 'angry', Component: () => <StreamEmoji fallback='😠' type='angry' />, name: 'Angry' },
{ type: 'haha', Component: () => <StreamEmoji fallback='πŸ˜‚' type='haha' />, name: 'Joy' },
{ type: 'like', Component: () => <StreamEmoji fallback='πŸ‘' type='like' />, name: 'Thumbs up' },
{ type: 'love', Component: () => <StreamEmoji fallback='❀️' type='love' />, name: 'Heart' },
{ type: 'sad', Component: () => <StreamEmoji fallback='πŸ˜”' type='sad' />, name: 'Sad' },
{ type: 'wow', Component: () => <StreamEmoji fallback='😲' type='wow' />, name: 'Astonished' },
];

0 comments on commit 2899d72

Please sign in to comment.