move mentions and emojify to a functional component

pull/2164/head
Audric Ackermann 3 years ago
parent 19722b6bdc
commit 2478a78794
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -21,6 +21,10 @@
.module-quote__primary__author { .module-quote__primary__author {
color: var(--color-sent-message-text); color: var(--color-sent-message-text);
font-weight: bold; font-weight: bold;
.module-contact-name {
font-weight: bold;
}
} }
.module-quote__primary__text { .module-quote__primary__text {
color: var(--color-sent-message-text); color: var(--color-sent-message-text);
@ -35,6 +39,9 @@
.module-quote__primary__author { .module-quote__primary__author {
color: var(--color-received-message-text); color: var(--color-received-message-text);
font-weight: bold; font-weight: bold;
.module-contact-name {
font-weight: bold;
}
} }
.module-quote__primary__text { .module-quote__primary__text {
color: var(--color-received-message-text); color: var(--color-received-message-text);

@ -9,8 +9,8 @@ import {
renderTextDefault, renderTextDefault,
} from '../conversation/message/message-content/MessageBody'; } from '../conversation/message/message-content/MessageBody';
const renderNewLines: RenderTextCallbackType = ({ text, key }) => ( const renderNewLines: RenderTextCallbackType = ({ text, key, isGroup }) => (
<AddNewLines key={key} text={text} renderNonNewLine={renderTextDefault} /> <AddNewLines key={key} text={text} renderNonNewLine={renderTextDefault} isGroup={isGroup} />
); );
const SnippetHighlight = styled.span` const SnippetHighlight = styled.span`
@ -23,15 +23,25 @@ const renderEmoji = ({
key, key,
sizeClass, sizeClass,
renderNonEmoji, renderNonEmoji,
isGroup,
}: { }: {
text: string; text: string;
key: number; key: number;
isGroup: boolean;
sizeClass: SizeClassType; sizeClass: SizeClassType;
renderNonEmoji: RenderTextCallbackType; renderNonEmoji: RenderTextCallbackType;
}) => <Emojify key={key} text={text} sizeClass={sizeClass} renderNonEmoji={renderNonEmoji} />; }) => (
<Emojify
key={key}
text={text}
sizeClass={sizeClass}
renderNonEmoji={renderNonEmoji}
isGroup={isGroup}
/>
);
export const MessageBodyHighlight = (props: { text: string }) => { export const MessageBodyHighlight = (props: { text: string; isGroup: boolean }) => {
const { text } = props; const { text, isGroup } = props;
const results: Array<JSX.Element> = []; const results: Array<JSX.Element> = [];
// this is matching what sqlite fts5 is giving us back // this is matching what sqlite fts5 is giving us back
const FIND_BEGIN_END = /<<left>>(.+?)<<right>>/g; const FIND_BEGIN_END = /<<left>>(.+?)<<right>>/g;
@ -41,7 +51,9 @@ export const MessageBodyHighlight = (props: { text: string }) => {
let count = 1; let count = 1;
if (!match) { if (!match) {
return <MessageBody disableJumbomoji={true} disableLinks={true} text={text} />; return (
<MessageBody disableJumbomoji={true} disableLinks={true} text={text} isGroup={isGroup} />
);
} }
const sizeClass = 'default'; const sizeClass = 'default';
@ -55,6 +67,7 @@ export const MessageBodyHighlight = (props: { text: string }) => {
sizeClass, sizeClass,
key: count++, key: count++,
renderNonEmoji: renderNewLines, renderNonEmoji: renderNewLines,
isGroup,
}) })
); );
} }
@ -67,6 +80,7 @@ export const MessageBodyHighlight = (props: { text: string }) => {
sizeClass, sizeClass,
key: count++, key: count++,
renderNonEmoji: renderNewLines, renderNonEmoji: renderNewLines,
isGroup,
})} })}
</SnippetHighlight> </SnippetHighlight>
); );
@ -83,6 +97,7 @@ export const MessageBodyHighlight = (props: { text: string }) => {
sizeClass, sizeClass,
key: count++, key: count++,
renderNonEmoji: renderNewLines, renderNonEmoji: renderNewLines,
isGroup,
}) })
); );
} }

@ -8,7 +8,6 @@ import React from 'react';
interface MentionProps { interface MentionProps {
key: string; key: string;
text: string; text: string;
convoId: string;
} }
const Mention = (props: MentionProps) => { const Mention = (props: MentionProps) => {
@ -29,55 +28,48 @@ const Mention = (props: MentionProps) => {
} }
}; };
interface Props { type Props = {
text: string; text: string;
renderOther?: RenderTextCallbackType; renderOther?: RenderTextCallbackType;
convoId: string; isGroup: boolean;
} };
export class AddMentions extends React.Component<Props> {
public static defaultProps: Partial<Props> = {
renderOther: ({ text }) => text,
};
public render() { const defaultRenderOther = ({ text }: { text: string }) => <>{text}</>;
const { text, renderOther, convoId } = this.props;
const results: Array<any> = [];
const FIND_MENTIONS = new RegExp(`@${PubKey.regexForPubkeys}`, 'g');
// We have to do this, because renderOther is not required in our Props object, export const AddMentions = (props: Props): JSX.Element => {
// but it is always provided via defaultProps. const { text, renderOther, isGroup } = props;
if (!renderOther) {
return;
}
let match = FIND_MENTIONS.exec(text); const results: Array<JSX.Element> = [];
let last = 0; const FIND_MENTIONS = new RegExp(`@${PubKey.regexForPubkeys}`, 'g');
let count = 1000;
if (!match) { const renderWith = renderOther || defaultRenderOther;
return renderOther({ text, key: 0 });
}
while (match) { let match = FIND_MENTIONS.exec(text);
count++; let last = 0;
const key = count; let count = 1000;
if (last < match.index) {
const otherText = text.slice(last, match.index);
results.push(renderOther({ text: otherText, key }));
}
const pubkey = text.slice(match.index, FIND_MENTIONS.lastIndex); if (!match) {
results.push(<Mention text={pubkey} key={`${key}`} convoId={convoId} />); return renderWith({ text, key: 0, isGroup });
}
last = FIND_MENTIONS.lastIndex; while (match) {
match = FIND_MENTIONS.exec(text); count++;
const key = count;
if (last < match.index) {
const otherText = text.slice(last, match.index);
results.push(renderWith({ text: otherText, key, isGroup }));
} }
if (last < text.length) { const pubkey = text.slice(match.index, FIND_MENTIONS.lastIndex);
results.push(renderOther({ text: text.slice(last), key: count++ })); results.push(<Mention text={pubkey} key={`${key}`} />);
}
return results; last = FIND_MENTIONS.lastIndex;
match = FIND_MENTIONS.exec(text);
} }
}
if (last < text.length) {
results.push(renderWith({ text: text.slice(last), key: count++, isGroup }));
}
return <>{results}</>;
};

@ -5,11 +5,12 @@ type Props = {
text: string; text: string;
/** Allows you to customize now non-newlines are rendered. Simplest is just a <span>. */ /** Allows you to customize now non-newlines are rendered. Simplest is just a <span>. */
renderNonNewLine: RenderTextCallbackType; renderNonNewLine: RenderTextCallbackType;
isGroup: boolean;
}; };
export const AddNewLines = (props: Props) => { export const AddNewLines = (props: Props) => {
const { text, renderNonNewLine } = props; const { text, renderNonNewLine, isGroup } = props;
const rendered = renderNonNewLine({ text, key: 0 }); const rendered = renderNonNewLine({ text, key: 0, isGroup });
if (typeof rendered === 'string') { if (typeof rendered === 'string') {
return <>{rendered}</>; return <>{rendered}</>;
} }

@ -2,7 +2,7 @@ import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { Emojify } from './Emojify'; import { Emojify } from './Emojify';
import { useConversationUsernameOrShorten } from '../../hooks/useParamSelector'; import { useConversationUsernameOrShorten, useIsPrivate } from '../../hooks/useParamSelector';
type Props = { type Props = {
pubkey: string; pubkey: string;
@ -19,7 +19,7 @@ export const ContactName = (props: Props) => {
const prefix = module ? module : 'module-contact-name'; const prefix = module ? module : 'module-contact-name';
const convoName = useConversationUsernameOrShorten(pubkey); const convoName = useConversationUsernameOrShorten(pubkey);
const isPrivate = useIsPrivate(pubkey);
const shouldShowProfile = Boolean(convoName || profileName || name); const shouldShowProfile = Boolean(convoName || profileName || name);
const styles = (boldProfileName const styles = (boldProfileName
? { ? {
@ -32,7 +32,7 @@ export const ContactName = (props: Props) => {
<span className={classNames(prefix, compact && 'compact')} dir="auto"> <span className={classNames(prefix, compact && 'compact')} dir="auto">
{shouldShowProfile ? ( {shouldShowProfile ? (
<span style={styles as any} className={`${prefix}__profile-name`}> <span style={styles as any} className={`${prefix}__profile-name`}>
<Emojify text={textProfile} sizeClass="small" /> <Emojify text={textProfile} sizeClass="small" isGroup={!isPrivate} />
</span> </span>
) : null} ) : null}
{shouldShowProfile ? ' ' : null} {shouldShowProfile ? ' ' : null}

@ -10,16 +10,17 @@ type Props = {
sizeClass: SizeClassType; sizeClass: SizeClassType;
/** Allows you to customize now non-newlines are rendered. Simplest is just a <span>. */ /** Allows you to customize now non-newlines are rendered. Simplest is just a <span>. */
renderNonEmoji?: RenderTextCallbackType; renderNonEmoji?: RenderTextCallbackType;
isGroup: boolean;
}; };
const defaultRenderNonEmoji = (text: string | undefined) => text || ''; const defaultRenderNonEmoji = (text: string | undefined) => <>{text || ''}</>;
export const Emojify = (props: Props): JSX.Element => { export const Emojify = (props: Props): JSX.Element => {
const { text, renderNonEmoji, sizeClass } = props; const { text, renderNonEmoji, sizeClass, isGroup } = props;
if (!renderNonEmoji) { if (!renderNonEmoji) {
return <>{defaultRenderNonEmoji(text)}</>; return <>{defaultRenderNonEmoji(text)}</>;
} }
const rendered = renderNonEmoji?.({ text: text || '', key: 1 }); const rendered = renderNonEmoji?.({ text: text || '', key: 1, isGroup });
let size = 1.0; let size = 1.0;
switch (sizeClass) { switch (sizeClass) {
case 'jumbo': case 'jumbo':

@ -7,71 +7,31 @@ import { isLinkSneaky } from '../../../js/modules/link_previews';
import { updateConfirmModal } from '../../state/ducks/modalDialog'; import { updateConfirmModal } from '../../state/ducks/modalDialog';
import { shell } from 'electron'; import { shell } from 'electron';
import { MessageInteraction } from '../../interactions'; import { MessageInteraction } from '../../interactions';
import { useDispatch } from 'react-redux';
const linkify = LinkifyIt(); const linkify = LinkifyIt();
interface Props { type Props = {
text: string; text: string;
/** Allows you to customize now non-links are rendered. Simplest is just a <span>. */ /** Allows you to customize now non-links are rendered. Simplest is just a <span>. */
renderNonLink?: RenderTextCallbackType; renderNonLink?: RenderTextCallbackType;
} isGroup: boolean;
};
const SUPPORTED_PROTOCOLS = /^(http|https):/i; const SUPPORTED_PROTOCOLS = /^(http|https):/i;
export class Linkify extends React.Component<Props> { const defaultRenderNonLink = ({ text }: { text: string }) => <>{text}</>;
public static defaultProps: Partial<Props> = {
renderNonLink: ({ text }) => text,
};
public render() {
const { text, renderNonLink } = this.props;
const results: Array<any> = [];
let count = 1;
const matchData = linkify.match(text) || [];
let last = 0;
// We have to do this, because renderNonLink is not required in our Props object,
// but it is always provided via defaultProps.
if (!renderNonLink) {
return;
}
if (matchData.length === 0) {
return renderNonLink({ text, key: 0 });
}
matchData.forEach((match: { index: number; url: string; lastIndex: number; text: string }) => {
if (last < match.index) {
const textWithNoLink = text.slice(last, match.index);
results.push(renderNonLink({ text: textWithNoLink, key: count++ }));
}
const { url, text: originalText } = match;
const isLink = SUPPORTED_PROTOCOLS.test(url) && !isLinkSneaky(url);
if (isLink) {
results.push(
<a key={count++} href={url} onClick={this.handleClick}>
{originalText}
</a>
);
} else {
results.push(renderNonLink({ text: originalText, key: count++ }));
}
last = match.lastIndex;
});
if (last < text.length) {
results.push(renderNonLink({ text: text.slice(last), key: count++ }));
}
return results;
}
export const Linkify = (props: Props): JSX.Element => {
const { text, isGroup, renderNonLink } = props;
const results: Array<any> = [];
let count = 1;
const dispatch = useDispatch();
const matchData = linkify.match(text) || [];
let last = 0;
// disable click on <a> elements so clicking a message containing a link doesn't // disable click on <a> elements so clicking a message containing a link doesn't
// select the message.The link will still be opened in the browser. // select the message.The link will still be opened in the browser.
public handleClick = (e: any) => { const handleClick = (e: any) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -81,7 +41,7 @@ export class Linkify extends React.Component<Props> {
void shell.openExternal(url); void shell.openExternal(url);
}; };
window.inboxStore?.dispatch( dispatch(
updateConfirmModal({ updateConfirmModal({
title: window.i18n('linkVisitWarningTitle'), title: window.i18n('linkVisitWarningTitle'),
message: window.i18n('linkVisitWarningMessage', url), message: window.i18n('linkVisitWarningMessage', url),
@ -90,7 +50,7 @@ export class Linkify extends React.Component<Props> {
showExitIcon: true, showExitIcon: true,
onClickOk: openLink, onClickOk: openLink,
onClickClose: () => { onClickClose: () => {
window.inboxStore?.dispatch(updateConfirmModal(null)); dispatch(updateConfirmModal(null));
}, },
onClickCancel: () => { onClickCancel: () => {
@ -99,4 +59,37 @@ export class Linkify extends React.Component<Props> {
}) })
); );
}; };
}
const renderWith = renderNonLink || defaultRenderNonLink;
if (matchData.length === 0) {
return renderWith({ text, key: 0, isGroup });
}
matchData.forEach((match: { index: number; url: string; lastIndex: number; text: string }) => {
if (last < match.index) {
const textWithNoLink = text.slice(last, match.index);
results.push(renderWith({ text: textWithNoLink, isGroup, key: count++ }));
}
const { url, text: originalText } = match;
const isLink = SUPPORTED_PROTOCOLS.test(url) && !isLinkSneaky(url);
if (isLink) {
results.push(
<a key={count++} href={url} onClick={handleClick}>
{originalText}
</a>
);
} else {
results.push(renderWith({ text: originalText, isGroup, key: count++ }));
}
last = match.lastIndex;
});
if (last < text.length) {
results.push(renderWith({ text: text.slice(last), isGroup, key: count++ }));
}
return <>{results}</>;
};

@ -12,18 +12,26 @@ type Props = {
disableJumbomoji: boolean; disableJumbomoji: boolean;
/** If set, links will be left alone instead of turned into clickable `<a>` tags. */ /** If set, links will be left alone instead of turned into clickable `<a>` tags. */
disableLinks: boolean; disableLinks: boolean;
isGroup: boolean;
}; };
const renderMentions: RenderTextCallbackType = ({ text, key }) => ( const renderMentions: RenderTextCallbackType = ({ text, key, isGroup }) => (
<AddMentions key={key} text={text} /> <AddMentions key={key} text={text} isGroup={isGroup} />
); );
export const renderTextDefault: RenderTextCallbackType = ({ text }) => text; export const renderTextDefault: RenderTextCallbackType = ({ text }) => <>{text}</>;
const renderNewLines: RenderTextCallbackType = ({ text: textWithNewLines, key, isGroup }) => { const renderNewLines: RenderTextCallbackType = ({ text: textWithNewLines, key, isGroup }) => {
const renderOther = isGroup ? renderMentions : renderTextDefault; const renderOther = isGroup ? renderMentions : renderTextDefault;
return <AddNewLines key={key} text={textWithNewLines} renderNonNewLine={renderOther} />; return (
<AddNewLines
key={key}
text={textWithNewLines}
renderNonNewLine={renderOther}
isGroup={isGroup}
/>
);
}; };
const renderEmoji = ({ const renderEmoji = ({
@ -31,12 +39,22 @@ const renderEmoji = ({
key, key,
sizeClass, sizeClass,
renderNonEmoji, renderNonEmoji,
isGroup,
}: { }: {
text: string; text: string;
key: number; key: number;
sizeClass: SizeClassType; sizeClass: SizeClassType;
renderNonEmoji: RenderTextCallbackType; renderNonEmoji: RenderTextCallbackType;
}) => <Emojify key={key} text={text} sizeClass={sizeClass} renderNonEmoji={renderNonEmoji} />; isGroup: boolean;
}) => (
<Emojify
key={key}
text={text}
sizeClass={sizeClass}
renderNonEmoji={renderNonEmoji}
isGroup={isGroup}
/>
);
/** /**
* This component makes it very easy to use all three of our message formatting * This component makes it very easy to use all three of our message formatting
@ -60,7 +78,7 @@ const JsxSelectable = (jsx: JSX.Element): JSX.Element => {
); );
}; };
export const MessageBody = (props: Props) => { export const MessageBody = (props: Props) => {
const { text, disableJumbomoji, disableLinks } = props; const { text, disableJumbomoji, disableLinks, isGroup } = props;
const sizeClass: SizeClassType = disableJumbomoji ? 'default' : getEmojiSizeClass(text); const sizeClass: SizeClassType = disableJumbomoji ? 'default' : getEmojiSizeClass(text);
if (disableLinks) { if (disableLinks) {
@ -70,24 +88,26 @@ export const MessageBody = (props: Props) => {
sizeClass, sizeClass,
key: 0, key: 0,
renderNonEmoji: renderNewLines, renderNonEmoji: renderNewLines,
isGroup,
}) })
); );
} }
if (text && text.startsWith('```') && text.endsWith('```')) { if (text && text.startsWith('```') && text.endsWith('```')) {
const length = text.length; return <pre className="text-selectable">{text.substring(4, text.length - 3)}</pre>;
return <pre className="text-selectable">{text.substring(4, length - 3)}</pre>;
} }
return JsxSelectable( return JsxSelectable(
<Linkify <Linkify
text={text} text={text}
isGroup={isGroup}
renderNonLink={({ key, text: nonLinkText }) => { renderNonLink={({ key, text: nonLinkText }) => {
return renderEmoji({ return renderEmoji({
text: nonLinkText, text: nonLinkText,
sizeClass, sizeClass,
key, key,
renderNonEmoji: renderNewLines, renderNonEmoji: renderNewLines,
isGroup,
}); });
}} }}
/> />

@ -15,7 +15,7 @@ type Props = {
export type MessageTextSelectorProps = Pick< export type MessageTextSelectorProps = Pick<
MessageRenderingProps, MessageRenderingProps,
'text' | 'direction' | 'status' | 'isDeleted' 'text' | 'direction' | 'status' | 'isDeleted' | 'conversationType'
>; >;
export const MessageText = (props: Props) => { export const MessageText = (props: Props) => {
@ -25,7 +25,7 @@ export const MessageText = (props: Props) => {
if (!selected) { if (!selected) {
return null; return null;
} }
const { text, direction, status, isDeleted } = selected; const { text, direction, status, isDeleted, conversationType } = selected;
const contents = isDeleted const contents = isDeleted
? window.i18n('messageDeletedPlaceholder') ? window.i18n('messageDeletedPlaceholder')
@ -47,7 +47,12 @@ export const MessageText = (props: Props) => {
)} )}
> >
{isDeleted && <SessionIcon iconType="delete" iconSize="small" />} {isDeleted && <SessionIcon iconType="delete" iconSize="small" />}
<MessageBody text={contents || ''} disableLinks={multiSelectMode} disableJumbomoji={false} /> <MessageBody
text={contents || ''}
disableLinks={multiSelectMode}
disableJumbomoji={false}
isGroup={conversationType === 'group'}
/>
</div> </div>
); );
}; };

@ -10,9 +10,13 @@ import { noop } from 'lodash';
import { useDisableDrag } from '../../../../hooks/useDisableDrag'; import { useDisableDrag } from '../../../../hooks/useDisableDrag';
import { useEncryptedFileFetch } from '../../../../hooks/useEncryptedFileFetch'; import { useEncryptedFileFetch } from '../../../../hooks/useEncryptedFileFetch';
import { PubKey } from '../../../../session/types'; import { PubKey } from '../../../../session/types';
import { isPublicGroupConversation } from '../../../../state/selectors/conversations'; import {
getSelectedConversationKey,
isPublicGroupConversation,
} from '../../../../state/selectors/conversations';
import { ContactName } from '../../ContactName'; import { ContactName } from '../../ContactName';
import { MessageBody } from './MessageBody'; import { MessageBody } from './MessageBody';
import { useIsPrivate } from '../../../../hooks/useParamSelector';
export type QuotePropsWithoutListener = { export type QuotePropsWithoutListener = {
attachment?: QuotedAttachmentType; attachment?: QuotedAttachmentType;
@ -225,6 +229,9 @@ export const QuoteText = (
) => { ) => {
const { text, attachment, isIncoming } = props; const { text, attachment, isIncoming } = props;
const convoId = useSelector(getSelectedConversationKey);
const isGroup = useIsPrivate(convoId);
if (text) { if (text) {
return ( return (
<div <div
@ -234,7 +241,7 @@ export const QuoteText = (
isIncoming ? 'module-quote__primary__text--incoming' : null isIncoming ? 'module-quote__primary__text--incoming' : null
)} )}
> >
<MessageBody text={text} disableLinks={true} disableJumbomoji={true} /> <MessageBody text={text} disableLinks={true} disableJumbomoji={true} isGroup={isGroup} />
</div> </div>
); );
} }

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { useConversationUsername, useIsMe } from '../../hooks/useParamSelector'; import { useConversationUsername, useIsMe, useIsPrivate } from '../../hooks/useParamSelector';
import { Avatar, AvatarSize } from '../avatar/Avatar'; import { Avatar, AvatarSize } from '../avatar/Avatar';
import { Emojify } from '../conversation/Emojify'; import { Emojify } from '../conversation/Emojify';
@ -20,6 +20,7 @@ export const ContactListItem = (props: Props) => {
const name = useConversationUsername(pubkey); const name = useConversationUsername(pubkey);
const isMe = useIsMe(pubkey); const isMe = useIsMe(pubkey);
const isGroup = !useIsPrivate(pubkey);
const title = name ? name : pubkey; const title = name ? name : pubkey;
const displayName = isMe ? window.i18n('me') : title; const displayName = isMe ? window.i18n('me') : title;
@ -36,7 +37,7 @@ export const ContactListItem = (props: Props) => {
<AvatarItem pubkey={pubkey} /> <AvatarItem pubkey={pubkey} />
<div className="module-contact-list-item__text"> <div className="module-contact-list-item__text">
<div className="module-contact-list-item__text__name"> <div className="module-contact-list-item__text__name">
<Emojify text={displayName} sizeClass="small" renderNonEmoji={({ text }) => text || ''} /> <Emojify text={displayName} sizeClass="small" isGroup={isGroup} />
</div> </div>
</div> </div>
</div> </div>

@ -1,7 +1,7 @@
import classNames from 'classnames'; import classNames from 'classnames';
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { useConversationPropsById } from '../../../hooks/useParamSelector'; import { useConversationPropsById, useIsPrivate } from '../../../hooks/useParamSelector';
import { MessageBody } from '../../conversation/message/message-content/MessageBody'; import { MessageBody } from '../../conversation/message/message-content/MessageBody';
import { OutgoingMessageStatus } from '../../conversation/message/message-content/OutgoingMessageStatus'; import { OutgoingMessageStatus } from '../../conversation/message/message-content/OutgoingMessageStatus';
import { TypingAnimation } from '../../conversation/TypingAnimation'; import { TypingAnimation } from '../../conversation/TypingAnimation';
@ -26,6 +26,8 @@ export const MessageItem = (props: { isMessageRequest: boolean }) => {
const conversationId = useContext(ContextConversationId); const conversationId = useContext(ContextConversationId);
const convoProps = useMessageItemProps(conversationId); const convoProps = useMessageItemProps(conversationId);
const isGroup = !!useIsPrivate(conversationId);
const isSearchingMode = useSelector(isSearching); const isSearchingMode = useSelector(isSearching);
if (!convoProps) { if (!convoProps) {
return null; return null;
@ -52,7 +54,7 @@ export const MessageItem = (props: { isMessageRequest: boolean }) => {
{isTyping ? ( {isTyping ? (
<TypingAnimation /> <TypingAnimation />
) : ( ) : (
<MessageBody text={text} disableJumbomoji={true} disableLinks={true} /> <MessageBody text={text} disableJumbomoji={true} disableLinks={true} isGroup={isGroup} />
)} )}
</div> </div>
<MessageRequestButtons isMessageRequest={props.isMessageRequest} /> <MessageRequestButtons isMessageRequest={props.isMessageRequest} />

@ -230,7 +230,7 @@ export const MessageSearchResult = (props: MessageResultProps) => {
</ResultsHeader> </ResultsHeader>
<ResultBody> <ResultBody>
<FromUserInGroup authorPubkey={source} conversationId={conversationId} /> <FromUserInGroup authorPubkey={source} conversationId={conversationId} />
<MessageBodyHighlight text={snippet || ''} /> <MessageBodyHighlight text={snippet || ''} isGroup={!convoIsPrivate} />
</ResultBody> </ResultBody>
</StyledResultText> </StyledResultText>
</StyledSearchResulsts> </StyledSearchResulsts>

@ -577,7 +577,7 @@ export const isRightPanelShowing = createSelector(
export const isMessageSelectionMode = createSelector( export const isMessageSelectionMode = createSelector(
getConversations, getConversations,
(state: ConversationsStateType): boolean => state.selectedMessageIds.length > 0 (state: ConversationsStateType): boolean => Boolean(state.selectedMessageIds.length > 0)
); );
export const getSelectedMessageIds = createSelector( export const getSelectedMessageIds = createSelector(
@ -907,13 +907,14 @@ export const getMessageTextProps = createSelector(getMessagePropsByMessageId, (p
return undefined; return undefined;
} }
const { direction, status, text, isDeleted } = props.propsForMessage; const { direction, status, text, isDeleted, conversationType } = props.propsForMessage;
const msgProps: MessageTextSelectorProps = { const msgProps: MessageTextSelectorProps = {
direction, direction,
status, status,
text, text,
isDeleted, isDeleted,
conversationType,
}; };
return msgProps; return msgProps;

@ -3,7 +3,7 @@ import { LocalizerKeys } from './LocalizerKeys';
export type RenderTextCallbackType = (options: { export type RenderTextCallbackType = (options: {
text: string; text: string;
key: number; key: number;
isGroup?: boolean; isGroup: boolean;
}) => JSX.Element | string; }) => JSX.Element;
export type LocalizerType = (key: LocalizerKeys, values?: Array<string>) => string; export type LocalizerType = (key: LocalizerKeys, values?: Array<string>) => string;

Loading…
Cancel
Save