Show badges in reaction viewer
This commit is contained in:
parent
2cbcd59609
commit
c63bf11a8f
14 changed files with 44 additions and 53 deletions
|
@ -97,7 +97,6 @@ const renderAudioAttachment: Props['renderAudioAttachment'] = props => (
|
|||
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||
attachments: overrideProps.attachments,
|
||||
author: overrideProps.author || getDefaultConversation(),
|
||||
authorBadge: overrideProps.authorBadge,
|
||||
reducedMotion: boolean('reducedMotion', false),
|
||||
bodyRanges: overrideProps.bodyRanges,
|
||||
canReply: true,
|
||||
|
@ -128,6 +127,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
|||
expirationTimestamp:
|
||||
number('expirationTimestamp', overrideProps.expirationTimestamp || 0) ||
|
||||
undefined,
|
||||
getPreferredBadge: overrideProps.getPreferredBadge || (() => undefined),
|
||||
i18n,
|
||||
id: text('id', overrideProps.id || ''),
|
||||
renderingContext: 'storybook',
|
||||
|
@ -544,8 +544,8 @@ story.add('Avatar in Group', () => {
|
|||
|
||||
story.add('Badge in Group', () => {
|
||||
const props = createProps({
|
||||
authorBadge: getFakeBadge(),
|
||||
conversationType: 'group',
|
||||
getPreferredBadge: () => getFakeBadge(),
|
||||
status: 'sent',
|
||||
text: 'Hello it is me, the saxophone.',
|
||||
});
|
||||
|
|
|
@ -62,7 +62,7 @@ import type {
|
|||
LocalizerType,
|
||||
ThemeType,
|
||||
} from '../../types/Util';
|
||||
import type { BadgeType } from '../../badges/types';
|
||||
import type { PreferredBadgeSelectorType } from '../../state/selectors/badges';
|
||||
import type {
|
||||
ContactNameColorType,
|
||||
ConversationColorType,
|
||||
|
@ -157,7 +157,6 @@ export type PropsData = {
|
|||
| 'title'
|
||||
| 'unblurredAvatarPath'
|
||||
>;
|
||||
authorBadge: undefined | BadgeType;
|
||||
reducedMotion?: boolean;
|
||||
conversationType: ConversationTypeType;
|
||||
attachments?: Array<AttachmentType>;
|
||||
|
@ -204,6 +203,7 @@ export type PropsData = {
|
|||
export type PropsHousekeeping = {
|
||||
containerElementRef: RefObject<HTMLElement>;
|
||||
containerWidthBreakpoint: WidthBreakpoint;
|
||||
getPreferredBadge: PreferredBadgeSelectorType;
|
||||
i18n: LocalizerType;
|
||||
interactionMode: InteractionModeType;
|
||||
theme: ThemeType;
|
||||
|
@ -1191,7 +1191,8 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
public renderAvatar(): JSX.Element | undefined {
|
||||
const { author, authorBadge, i18n, showContactModal, theme } = this.props;
|
||||
const { author, getPreferredBadge, i18n, showContactModal, theme } =
|
||||
this.props;
|
||||
|
||||
if (!this.hasAvatar()) {
|
||||
return undefined;
|
||||
|
@ -1207,7 +1208,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
<Avatar
|
||||
acceptedMessageRequest={author.acceptedMessageRequest}
|
||||
avatarPath={author.avatarPath}
|
||||
badge={authorBadge}
|
||||
badge={getPreferredBadge(author.badges)}
|
||||
color={author.color}
|
||||
conversationType="direct"
|
||||
i18n={i18n}
|
||||
|
@ -1946,7 +1947,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
};
|
||||
|
||||
public renderReactions(outgoing: boolean): JSX.Element | null {
|
||||
const { reactions = [], i18n } = this.props;
|
||||
const { getPreferredBadge, reactions = [], i18n, theme } = this.props;
|
||||
|
||||
if (!this.hasReactions()) {
|
||||
return null;
|
||||
|
@ -2095,9 +2096,11 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
...style,
|
||||
zIndex: 2,
|
||||
}}
|
||||
getPreferredBadge={getPreferredBadge}
|
||||
reactions={reactions}
|
||||
i18n={i18n}
|
||||
onClose={this.toggleReactionViewer}
|
||||
theme={theme}
|
||||
/>
|
||||
)}
|
||||
</Popper>
|
||||
|
|
|
@ -27,7 +27,6 @@ const defaultMessage: MessageDataPropsType = {
|
|||
id: 'some-id',
|
||||
title: 'Max',
|
||||
}),
|
||||
authorBadge: getFakeBadge(),
|
||||
canReply: true,
|
||||
canDeleteForEveryone: true,
|
||||
canDownload: true,
|
||||
|
|
|
@ -64,7 +64,7 @@ export type PropsData = {
|
|||
i18n: LocalizerType;
|
||||
theme: ThemeType;
|
||||
getPreferredBadge: PreferredBadgeSelectorType;
|
||||
} & Pick<MessagePropsType, 'interactionMode'>;
|
||||
} & Pick<MessagePropsType, 'getPreferredBadge' | 'interactionMode'>;
|
||||
|
||||
export type PropsBackboneActions = Pick<
|
||||
MessagePropsType,
|
||||
|
@ -276,6 +276,7 @@ export class MessageDetail extends React.Component<Props> {
|
|||
contactNameColor,
|
||||
displayTapToViewMessage,
|
||||
doubleCheckMissingQuoteReference,
|
||||
getPreferredBadge,
|
||||
i18n,
|
||||
interactionMode,
|
||||
kickOffAttachmentDownload,
|
||||
|
@ -327,6 +328,7 @@ export class MessageDetail extends React.Component<Props> {
|
|||
log.warn('MessageDetail: deleteMessageForEveryone called!')
|
||||
}
|
||||
doubleCheckMissingQuoteReference={doubleCheckMissingQuoteReference}
|
||||
getPreferredBadge={getPreferredBadge}
|
||||
i18n={i18n}
|
||||
interactionMode={interactionMode}
|
||||
kickOffAttachmentDownload={kickOffAttachmentDownload}
|
||||
|
|
|
@ -37,7 +37,6 @@ const defaultMessageProps: MessagesProps = {
|
|||
id: 'some-id',
|
||||
title: 'Person X',
|
||||
}),
|
||||
authorBadge: undefined,
|
||||
canReply: true,
|
||||
canDeleteForEveryone: true,
|
||||
canDownload: true,
|
||||
|
@ -56,6 +55,7 @@ const defaultMessageProps: MessagesProps = {
|
|||
doubleCheckMissingQuoteReference: action(
|
||||
'default--doubleCheckMissingQuoteReference'
|
||||
),
|
||||
getPreferredBadge: () => undefined,
|
||||
i18n,
|
||||
id: 'messageId',
|
||||
renderingContext: 'storybook',
|
||||
|
|
|
@ -11,17 +11,20 @@ import { ReactionViewer } from './ReactionViewer';
|
|||
import { setupI18n } from '../../util/setupI18n';
|
||||
import enMessages from '../../../_locales/en/messages.json';
|
||||
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
|
||||
import { ThemeType } from '../../types/Util';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
const story = storiesOf('Components/Conversation/ReactionViewer', module);
|
||||
|
||||
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||
getPreferredBadge: () => undefined,
|
||||
i18n,
|
||||
onClose: action('onClose'),
|
||||
pickedReaction: overrideProps.pickedReaction,
|
||||
reactions: overrideProps.reactions || [],
|
||||
style: overrideProps.style,
|
||||
theme: ThemeType.light,
|
||||
});
|
||||
|
||||
story.add('All Reactions', () => {
|
||||
|
|
|
@ -10,9 +10,11 @@ import { Avatar } from '../Avatar';
|
|||
import { Emoji } from '../emoji/Emoji';
|
||||
import { useRestoreFocus } from '../../hooks/useRestoreFocus';
|
||||
import type { ConversationType } from '../../state/ducks/conversations';
|
||||
import type { PreferredBadgeSelectorType } from '../../state/selectors/badges';
|
||||
import type { EmojiData } from '../emoji/lib';
|
||||
import { emojiToData } from '../emoji/lib';
|
||||
import { useEscapeHandling } from '../../hooks/useEscapeHandling';
|
||||
import type { ThemeType } from '../../types/Util';
|
||||
|
||||
export type Reaction = {
|
||||
emoji: string;
|
||||
|
@ -21,6 +23,7 @@ export type Reaction = {
|
|||
ConversationType,
|
||||
| 'acceptedMessageRequest'
|
||||
| 'avatarPath'
|
||||
| 'badges'
|
||||
| 'color'
|
||||
| 'id'
|
||||
| 'isMe'
|
||||
|
@ -33,9 +36,11 @@ export type Reaction = {
|
|||
};
|
||||
|
||||
export type OwnProps = {
|
||||
getPreferredBadge: PreferredBadgeSelectorType;
|
||||
reactions: Array<Reaction>;
|
||||
pickedReaction?: string;
|
||||
onClose?: () => unknown;
|
||||
theme: ThemeType;
|
||||
};
|
||||
|
||||
export type Props = OwnProps &
|
||||
|
@ -62,7 +67,18 @@ type ReactionCategory = {
|
|||
type ReactionWithEmojiData = Reaction & EmojiData;
|
||||
|
||||
export const ReactionViewer = React.forwardRef<HTMLDivElement, Props>(
|
||||
({ i18n, reactions, onClose, pickedReaction, ...rest }, ref) => {
|
||||
(
|
||||
{
|
||||
getPreferredBadge,
|
||||
i18n,
|
||||
onClose,
|
||||
pickedReaction,
|
||||
reactions,
|
||||
theme,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const reactionsWithEmojiData = React.useMemo(
|
||||
() =>
|
||||
reactions
|
||||
|
@ -205,6 +221,7 @@ export const ReactionViewer = React.forwardRef<HTMLDivElement, Props>(
|
|||
<Avatar
|
||||
acceptedMessageRequest={from.acceptedMessageRequest}
|
||||
avatarPath={from.avatarPath}
|
||||
badge={getPreferredBadge(from.badges)}
|
||||
conversationType="direct"
|
||||
sharedGroupNames={from.sharedGroupNames}
|
||||
size={32}
|
||||
|
@ -213,6 +230,7 @@ export const ReactionViewer = React.forwardRef<HTMLDivElement, Props>(
|
|||
name={from.name}
|
||||
profileName={from.profileName}
|
||||
phoneNumber={from.phoneNumber}
|
||||
theme={theme}
|
||||
title={from.title}
|
||||
i18n={i18n}
|
||||
/>
|
||||
|
|
|
@ -47,7 +47,6 @@ const items: Record<string, TimelineItemType> = {
|
|||
author: getDefaultConversation({
|
||||
phoneNumber: '(202) 555-2001',
|
||||
}),
|
||||
authorBadge: undefined,
|
||||
canDeleteForEveryone: false,
|
||||
canDownload: true,
|
||||
canReply: true,
|
||||
|
@ -68,7 +67,6 @@ const items: Record<string, TimelineItemType> = {
|
|||
type: 'message',
|
||||
data: {
|
||||
author: getDefaultConversation({}),
|
||||
authorBadge: undefined,
|
||||
canDeleteForEveryone: false,
|
||||
canDownload: true,
|
||||
canReply: true,
|
||||
|
@ -102,7 +100,6 @@ const items: Record<string, TimelineItemType> = {
|
|||
type: 'message',
|
||||
data: {
|
||||
author: getDefaultConversation({}),
|
||||
authorBadge: undefined,
|
||||
canDeleteForEveryone: false,
|
||||
canDownload: true,
|
||||
canReply: true,
|
||||
|
@ -192,7 +189,6 @@ const items: Record<string, TimelineItemType> = {
|
|||
type: 'message',
|
||||
data: {
|
||||
author: getDefaultConversation({}),
|
||||
authorBadge: undefined,
|
||||
canDeleteForEveryone: false,
|
||||
canDownload: true,
|
||||
canReply: true,
|
||||
|
@ -214,7 +210,6 @@ const items: Record<string, TimelineItemType> = {
|
|||
type: 'message',
|
||||
data: {
|
||||
author: getDefaultConversation({}),
|
||||
authorBadge: undefined,
|
||||
canDeleteForEveryone: false,
|
||||
canDownload: true,
|
||||
canReply: true,
|
||||
|
@ -236,7 +231,6 @@ const items: Record<string, TimelineItemType> = {
|
|||
type: 'message',
|
||||
data: {
|
||||
author: getDefaultConversation({}),
|
||||
authorBadge: undefined,
|
||||
canDeleteForEveryone: false,
|
||||
canDownload: true,
|
||||
canReply: true,
|
||||
|
@ -258,7 +252,6 @@ const items: Record<string, TimelineItemType> = {
|
|||
type: 'message',
|
||||
data: {
|
||||
author: getDefaultConversation({}),
|
||||
authorBadge: undefined,
|
||||
canDeleteForEveryone: false,
|
||||
canDownload: true,
|
||||
canReply: true,
|
||||
|
@ -280,7 +273,6 @@ const items: Record<string, TimelineItemType> = {
|
|||
type: 'message',
|
||||
data: {
|
||||
author: getDefaultConversation({}),
|
||||
authorBadge: undefined,
|
||||
canDeleteForEveryone: false,
|
||||
canDownload: true,
|
||||
canReply: true,
|
||||
|
@ -389,6 +381,7 @@ const renderItem = ({
|
|||
containerWidthBreakpoint: WidthBreakpoint;
|
||||
}) => (
|
||||
<TimelineItem
|
||||
getPreferredBadge={() => undefined}
|
||||
id=""
|
||||
isSelected={false}
|
||||
renderEmojiPicker={() => <div />}
|
||||
|
|
|
@ -51,6 +51,7 @@ const getDefaultProps = () => ({
|
|||
containerElementRef: React.createRef<HTMLElement>(),
|
||||
containerWidthBreakpoint: WidthBreakpoint.Wide,
|
||||
conversationId: 'conversation-id',
|
||||
getPreferredBadge: () => undefined,
|
||||
id: 'asdf',
|
||||
isSelected: false,
|
||||
interactionMode: 'keyboard' as const,
|
||||
|
|
|
@ -165,6 +165,7 @@ export type PropsType = PropsLocalType &
|
|||
Pick<
|
||||
AllMessageProps,
|
||||
| 'containerWidthBreakpoint'
|
||||
| 'getPreferredBadge'
|
||||
| 'renderEmojiPicker'
|
||||
| 'renderAudioAttachment'
|
||||
| 'renderReactionPicker'
|
||||
|
@ -175,6 +176,7 @@ export class TimelineItem extends React.PureComponent<PropsType> {
|
|||
const {
|
||||
containerElementRef,
|
||||
conversationId,
|
||||
getPreferredBadge,
|
||||
id,
|
||||
isSelected,
|
||||
item,
|
||||
|
@ -201,6 +203,7 @@ export class TimelineItem extends React.PureComponent<PropsType> {
|
|||
{...omit(this.props, ['item'])}
|
||||
{...item.data}
|
||||
containerElementRef={containerElementRef}
|
||||
getPreferredBadge={getPreferredBadge}
|
||||
i18n={i18n}
|
||||
theme={theme}
|
||||
renderingContext="conversation/TimelineItem"
|
||||
|
|
|
@ -134,8 +134,6 @@ import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
|||
import * as log from '../logging/log';
|
||||
import * as Bytes from '../Bytes';
|
||||
import { computeHash } from '../Crypto';
|
||||
import type { PreferredBadgeSelectorType } from '../state/selectors/badges';
|
||||
import { getPreferredBadgeSelector } from '../state/selectors/badges';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/* eslint-disable more/no-then */
|
||||
|
@ -394,13 +392,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
ourConversationId,
|
||||
ourNumber: window.textsecure.storage.user.getNumber(),
|
||||
ourUuid: window.textsecure.storage.user.getCheckedUuid().toString(),
|
||||
preferredBadgeSelector: (
|
||||
...args: Parameters<PreferredBadgeSelectorType>
|
||||
) => {
|
||||
const state = window.reduxStore.getState();
|
||||
const preferredBadgeSelector = getPreferredBadgeSelector(state);
|
||||
return preferredBadgeSelector(...args);
|
||||
},
|
||||
regionCode: window.storage.get('regionCode', 'ZZ'),
|
||||
accountSelector: (identifier?: string) => {
|
||||
const state = window.reduxStore.getState();
|
||||
|
|
|
@ -49,8 +49,6 @@ import { getPinnedConversationIds } from './items';
|
|||
import { getPropsForBubble } from './message';
|
||||
import type { CallSelectorType, CallStateType } from './calling';
|
||||
import { getActiveCall, getCallSelector } from './calling';
|
||||
import type { PreferredBadgeSelectorType } from './badges';
|
||||
import { getPreferredBadgeSelector } from './badges';
|
||||
import type { AccountSelectorType } from './accounts';
|
||||
import { getAccountSelector } from './accounts';
|
||||
import * as log from '../../logging/log';
|
||||
|
@ -795,7 +793,6 @@ export const getMessageSelector = createSelector(
|
|||
getMessages,
|
||||
getSelectedMessage,
|
||||
getConversationSelector,
|
||||
getPreferredBadgeSelector,
|
||||
getRegionCode,
|
||||
getUserNumber,
|
||||
getUserUuid,
|
||||
|
@ -809,7 +806,6 @@ export const getMessageSelector = createSelector(
|
|||
messageLookup: MessageLookupType,
|
||||
selectedMessage: SelectedMessageType | undefined,
|
||||
conversationSelector: GetConversationByIdType,
|
||||
preferredBadgeSelector: PreferredBadgeSelectorType,
|
||||
regionCode: string,
|
||||
ourNumber: string,
|
||||
ourUuid: UUIDStringType,
|
||||
|
@ -830,7 +826,6 @@ export const getMessageSelector = createSelector(
|
|||
ourConversationId,
|
||||
ourNumber,
|
||||
ourUuid,
|
||||
preferredBadgeSelector,
|
||||
regionCode,
|
||||
selectedMessageId: selectedMessage?.id,
|
||||
selectedMessageCounter: selectedMessage?.counter,
|
||||
|
|
|
@ -63,7 +63,6 @@ import type {
|
|||
} from '../ducks/conversations';
|
||||
|
||||
import type { AccountSelectorType } from './accounts';
|
||||
import type { PreferredBadgeSelectorType } from './badges';
|
||||
import type { CallSelectorType, CallStateType } from './calling';
|
||||
import type {
|
||||
GetConversationByIdType,
|
||||
|
@ -82,7 +81,6 @@ import {
|
|||
someSendStatus,
|
||||
} from '../../messages/MessageSendState';
|
||||
import * as log from '../../logging/log';
|
||||
import type { BadgeType } from '../../badges/types';
|
||||
|
||||
const THREE_HOURS = 3 * 60 * 60 * 1000;
|
||||
|
||||
|
@ -108,7 +106,6 @@ export type GetPropsForBubbleOptions = Readonly<{
|
|||
ourConversationId: string;
|
||||
ourNumber?: string;
|
||||
ourUuid: UUIDStringType;
|
||||
preferredBadgeSelector: PreferredBadgeSelectorType;
|
||||
selectedMessageId?: string;
|
||||
selectedMessageCounter?: number;
|
||||
regionCode: string;
|
||||
|
@ -350,19 +347,6 @@ const getCachedAuthorForMessage = createSelectorCreator(memoizeByRoot, isEqual)(
|
|||
(_, author): PropsData['author'] => author
|
||||
);
|
||||
|
||||
const getAuthorBadgeForMessage: (
|
||||
message: MessageWithUIFieldsType,
|
||||
options: {
|
||||
preferredBadgeSelector: PreferredBadgeSelectorType;
|
||||
}
|
||||
) => undefined | BadgeType = createSelectorCreator(memoizeByRoot, isEqual)(
|
||||
// `memoizeByRoot` requirement
|
||||
identity,
|
||||
(_, { preferredBadgeSelector }) => preferredBadgeSelector,
|
||||
getAuthorForMessage,
|
||||
(_, preferredBadgeSelector, author) => preferredBadgeSelector(author.badges)
|
||||
);
|
||||
|
||||
export const getPreviewsForMessage = createSelectorCreator(memoizeByRoot)(
|
||||
// `memoizeByRoot` requirement
|
||||
identity,
|
||||
|
@ -412,6 +396,7 @@ export const getReactionsForMessage = createSelectorCreator(
|
|||
const unsafe = pick(c, [
|
||||
'acceptedMessageRequest',
|
||||
'avatarPath',
|
||||
'badges',
|
||||
'color',
|
||||
'id',
|
||||
'isMe',
|
||||
|
@ -514,7 +499,6 @@ export type GetPropsForMessageOptions = Pick<
|
|||
| 'ourConversationId'
|
||||
| 'ourUuid'
|
||||
| 'ourNumber'
|
||||
| 'preferredBadgeSelector'
|
||||
| 'selectedMessageId'
|
||||
| 'selectedMessageCounter'
|
||||
| 'regionCode'
|
||||
|
@ -656,7 +640,6 @@ export const getPropsForMessage: (
|
|||
getAttachmentsForMessage,
|
||||
processBodyRanges,
|
||||
getCachedAuthorForMessage,
|
||||
getAuthorBadgeForMessage,
|
||||
getPreviewsForMessage,
|
||||
getReactionsForMessage,
|
||||
getPropsForQuote,
|
||||
|
@ -666,7 +649,6 @@ export const getPropsForMessage: (
|
|||
attachments: Array<AttachmentType>,
|
||||
bodyRanges: BodyRangesType | undefined,
|
||||
author: PropsData['author'],
|
||||
authorBadge: undefined | BadgeType,
|
||||
previews: Array<LinkPreviewType>,
|
||||
reactions: PropsData['reactions'],
|
||||
quote: PropsData['quote'],
|
||||
|
@ -675,7 +657,6 @@ export const getPropsForMessage: (
|
|||
return {
|
||||
attachments,
|
||||
author,
|
||||
authorBadge,
|
||||
bodyRanges,
|
||||
previews,
|
||||
quote,
|
||||
|
|
|
@ -9,6 +9,7 @@ import { mapDispatchToProps } from '../actions';
|
|||
import type { StateType } from '../reducer';
|
||||
|
||||
import { TimelineItem } from '../../components/conversation/TimelineItem';
|
||||
import { getPreferredBadgeSelector } from '../selectors/badges';
|
||||
import { getIntl, getInteractionMode, getTheme } from '../selectors/user';
|
||||
import {
|
||||
getConversationSelector,
|
||||
|
@ -68,6 +69,7 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
|
|||
conversationId,
|
||||
conversationColor: conversation?.conversationColor,
|
||||
customColor: conversation?.customColor,
|
||||
getPreferredBadge: getPreferredBadgeSelector(state),
|
||||
isSelected,
|
||||
renderContact,
|
||||
renderUniversalTimerNotification,
|
||||
|
|
Loading…
Add table
Reference in a new issue