From c63bf11a8f54c0ae0e4aade26b74c0b622c086fa Mon Sep 17 00:00:00 2001 From: Evan Hahn <69474926+EvanHahn-Signal@users.noreply.github.com> Date: Wed, 17 Nov 2021 15:11:46 -0600 Subject: [PATCH] Show badges in reaction viewer --- .../conversation/Message.stories.tsx | 4 ++-- ts/components/conversation/Message.tsx | 13 +++++++----- .../conversation/MessageDetail.stories.tsx | 1 - ts/components/conversation/MessageDetail.tsx | 4 +++- ts/components/conversation/Quote.stories.tsx | 2 +- .../conversation/ReactionViewer.stories.tsx | 3 +++ ts/components/conversation/ReactionViewer.tsx | 20 +++++++++++++++++- .../conversation/Timeline.stories.tsx | 9 +------- .../conversation/TimelineItem.stories.tsx | 1 + ts/components/conversation/TimelineItem.tsx | 3 +++ ts/models/messages.ts | 9 -------- ts/state/selectors/conversations.ts | 5 ----- ts/state/selectors/message.ts | 21 +------------------ ts/state/smart/TimelineItem.tsx | 2 ++ 14 files changed, 44 insertions(+), 53 deletions(-) diff --git a/ts/components/conversation/Message.stories.tsx b/ts/components/conversation/Message.stories.tsx index 5ae43e53d3..4c92124cd1 100644 --- a/ts/components/conversation/Message.stories.tsx +++ b/ts/components/conversation/Message.stories.tsx @@ -97,7 +97,6 @@ const renderAudioAttachment: Props['renderAudioAttachment'] = props => ( const createProps = (overrideProps: Partial = {}): 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 => ({ 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.', }); diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index a5fce5634a..d168e86bb7 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -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; @@ -204,6 +203,7 @@ export type PropsData = { export type PropsHousekeeping = { containerElementRef: RefObject; containerWidthBreakpoint: WidthBreakpoint; + getPreferredBadge: PreferredBadgeSelectorType; i18n: LocalizerType; interactionMode: InteractionModeType; theme: ThemeType; @@ -1191,7 +1191,8 @@ export class Message extends React.PureComponent { } 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 { { }; 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 { ...style, zIndex: 2, }} + getPreferredBadge={getPreferredBadge} reactions={reactions} i18n={i18n} onClose={this.toggleReactionViewer} + theme={theme} /> )} diff --git a/ts/components/conversation/MessageDetail.stories.tsx b/ts/components/conversation/MessageDetail.stories.tsx index c16faa2ed3..0da0629e99 100644 --- a/ts/components/conversation/MessageDetail.stories.tsx +++ b/ts/components/conversation/MessageDetail.stories.tsx @@ -27,7 +27,6 @@ const defaultMessage: MessageDataPropsType = { id: 'some-id', title: 'Max', }), - authorBadge: getFakeBadge(), canReply: true, canDeleteForEveryone: true, canDownload: true, diff --git a/ts/components/conversation/MessageDetail.tsx b/ts/components/conversation/MessageDetail.tsx index a924e814c6..718f14aed8 100644 --- a/ts/components/conversation/MessageDetail.tsx +++ b/ts/components/conversation/MessageDetail.tsx @@ -64,7 +64,7 @@ export type PropsData = { i18n: LocalizerType; theme: ThemeType; getPreferredBadge: PreferredBadgeSelectorType; -} & Pick; +} & Pick; export type PropsBackboneActions = Pick< MessagePropsType, @@ -276,6 +276,7 @@ export class MessageDetail extends React.Component { contactNameColor, displayTapToViewMessage, doubleCheckMissingQuoteReference, + getPreferredBadge, i18n, interactionMode, kickOffAttachmentDownload, @@ -327,6 +328,7 @@ export class MessageDetail extends React.Component { log.warn('MessageDetail: deleteMessageForEveryone called!') } doubleCheckMissingQuoteReference={doubleCheckMissingQuoteReference} + getPreferredBadge={getPreferredBadge} i18n={i18n} interactionMode={interactionMode} kickOffAttachmentDownload={kickOffAttachmentDownload} diff --git a/ts/components/conversation/Quote.stories.tsx b/ts/components/conversation/Quote.stories.tsx index 5711202797..26801ed8af 100644 --- a/ts/components/conversation/Quote.stories.tsx +++ b/ts/components/conversation/Quote.stories.tsx @@ -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', diff --git a/ts/components/conversation/ReactionViewer.stories.tsx b/ts/components/conversation/ReactionViewer.stories.tsx index a29019c355..16df87ad2b 100644 --- a/ts/components/conversation/ReactionViewer.stories.tsx +++ b/ts/components/conversation/ReactionViewer.stories.tsx @@ -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 => ({ + getPreferredBadge: () => undefined, i18n, onClose: action('onClose'), pickedReaction: overrideProps.pickedReaction, reactions: overrideProps.reactions || [], style: overrideProps.style, + theme: ThemeType.light, }); story.add('All Reactions', () => { diff --git a/ts/components/conversation/ReactionViewer.tsx b/ts/components/conversation/ReactionViewer.tsx index 761ded3f3c..59644b8815 100644 --- a/ts/components/conversation/ReactionViewer.tsx +++ b/ts/components/conversation/ReactionViewer.tsx @@ -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; 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( - ({ 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( ( name={from.name} profileName={from.profileName} phoneNumber={from.phoneNumber} + theme={theme} title={from.title} i18n={i18n} /> diff --git a/ts/components/conversation/Timeline.stories.tsx b/ts/components/conversation/Timeline.stories.tsx index 929b42ba03..969be7b505 100644 --- a/ts/components/conversation/Timeline.stories.tsx +++ b/ts/components/conversation/Timeline.stories.tsx @@ -47,7 +47,6 @@ const items: Record = { author: getDefaultConversation({ phoneNumber: '(202) 555-2001', }), - authorBadge: undefined, canDeleteForEveryone: false, canDownload: true, canReply: true, @@ -68,7 +67,6 @@ const items: Record = { type: 'message', data: { author: getDefaultConversation({}), - authorBadge: undefined, canDeleteForEveryone: false, canDownload: true, canReply: true, @@ -102,7 +100,6 @@ const items: Record = { type: 'message', data: { author: getDefaultConversation({}), - authorBadge: undefined, canDeleteForEveryone: false, canDownload: true, canReply: true, @@ -192,7 +189,6 @@ const items: Record = { type: 'message', data: { author: getDefaultConversation({}), - authorBadge: undefined, canDeleteForEveryone: false, canDownload: true, canReply: true, @@ -214,7 +210,6 @@ const items: Record = { type: 'message', data: { author: getDefaultConversation({}), - authorBadge: undefined, canDeleteForEveryone: false, canDownload: true, canReply: true, @@ -236,7 +231,6 @@ const items: Record = { type: 'message', data: { author: getDefaultConversation({}), - authorBadge: undefined, canDeleteForEveryone: false, canDownload: true, canReply: true, @@ -258,7 +252,6 @@ const items: Record = { type: 'message', data: { author: getDefaultConversation({}), - authorBadge: undefined, canDeleteForEveryone: false, canDownload: true, canReply: true, @@ -280,7 +273,6 @@ const items: Record = { type: 'message', data: { author: getDefaultConversation({}), - authorBadge: undefined, canDeleteForEveryone: false, canDownload: true, canReply: true, @@ -389,6 +381,7 @@ const renderItem = ({ containerWidthBreakpoint: WidthBreakpoint; }) => ( undefined} id="" isSelected={false} renderEmojiPicker={() =>
} diff --git a/ts/components/conversation/TimelineItem.stories.tsx b/ts/components/conversation/TimelineItem.stories.tsx index 5a4117f702..8494077105 100644 --- a/ts/components/conversation/TimelineItem.stories.tsx +++ b/ts/components/conversation/TimelineItem.stories.tsx @@ -51,6 +51,7 @@ const getDefaultProps = () => ({ containerElementRef: React.createRef(), containerWidthBreakpoint: WidthBreakpoint.Wide, conversationId: 'conversation-id', + getPreferredBadge: () => undefined, id: 'asdf', isSelected: false, interactionMode: 'keyboard' as const, diff --git a/ts/components/conversation/TimelineItem.tsx b/ts/components/conversation/TimelineItem.tsx index 29635ff949..8432e5f581 100644 --- a/ts/components/conversation/TimelineItem.tsx +++ b/ts/components/conversation/TimelineItem.tsx @@ -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 { const { containerElementRef, conversationId, + getPreferredBadge, id, isSelected, item, @@ -201,6 +203,7 @@ export class TimelineItem extends React.PureComponent { {...omit(this.props, ['item'])} {...item.data} containerElementRef={containerElementRef} + getPreferredBadge={getPreferredBadge} i18n={i18n} theme={theme} renderingContext="conversation/TimelineItem" diff --git a/ts/models/messages.ts b/ts/models/messages.ts index ede8823760..96977e4bff 100644 --- a/ts/models/messages.ts +++ b/ts/models/messages.ts @@ -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 { ourConversationId, ourNumber: window.textsecure.storage.user.getNumber(), ourUuid: window.textsecure.storage.user.getCheckedUuid().toString(), - preferredBadgeSelector: ( - ...args: Parameters - ) => { - 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(); diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index 2bbba6a1d4..28f54ddc0c 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -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, diff --git a/ts/state/selectors/message.ts b/ts/state/selectors/message.ts index d8edd39aa6..db8febfe04 100644 --- a/ts/state/selectors/message.ts +++ b/ts/state/selectors/message.ts @@ -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, bodyRanges: BodyRangesType | undefined, author: PropsData['author'], - authorBadge: undefined | BadgeType, previews: Array, reactions: PropsData['reactions'], quote: PropsData['quote'], @@ -675,7 +657,6 @@ export const getPropsForMessage: ( return { attachments, author, - authorBadge, bodyRanges, previews, quote, diff --git a/ts/state/smart/TimelineItem.tsx b/ts/state/smart/TimelineItem.tsx index 555778eec7..e1ed6211b4 100644 --- a/ts/state/smart/TimelineItem.tsx +++ b/ts/state/smart/TimelineItem.tsx @@ -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,