Add back an emojifyText function, do it during render
This commit is contained in:
parent
3cd479b601
commit
c27e4c6556
|
@ -15,6 +15,7 @@ import VerificationBadge from 'soapbox/components/verification-badge.tsx';
|
||||||
import ActionButton from 'soapbox/features/ui/components/action-button.tsx';
|
import ActionButton from 'soapbox/features/ui/components/action-button.tsx';
|
||||||
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
||||||
import { getAcct } from 'soapbox/utils/accounts.ts';
|
import { getAcct } from 'soapbox/utils/accounts.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
import { displayFqn } from 'soapbox/utils/state.ts';
|
import { displayFqn } from 'soapbox/utils/state.ts';
|
||||||
|
|
||||||
import Badge from './badge.tsx';
|
import Badge from './badge.tsx';
|
||||||
|
@ -233,7 +234,7 @@ const Account = ({
|
||||||
<LinkEl {...linkProps}>
|
<LinkEl {...linkProps}>
|
||||||
<HStack space={1} alignItems='center' grow>
|
<HStack space={1} alignItems='center' grow>
|
||||||
<Text size='sm' weight='semibold' truncate>
|
<Text size='sm' weight='semibold' truncate>
|
||||||
{account.display_name}
|
{emojifyText(account.display_name, account.emojis)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{account.verified && <VerificationBadge />}
|
{account.verified && <VerificationBadge />}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import HStack from 'soapbox/components/ui/hstack.tsx';
|
import HStack from 'soapbox/components/ui/hstack.tsx';
|
||||||
import Text from 'soapbox/components/ui/text.tsx';
|
import Text from 'soapbox/components/ui/text.tsx';
|
||||||
import { useSoapboxConfig } from 'soapbox/hooks/useSoapboxConfig.ts';
|
import { useSoapboxConfig } from 'soapbox/hooks/useSoapboxConfig.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
|
|
||||||
import { getAcct } from '../utils/accounts.ts';
|
import { getAcct } from '../utils/accounts.ts';
|
||||||
|
|
||||||
|
@ -10,7 +11,7 @@ import VerificationBadge from './verification-badge.tsx';
|
||||||
import type { Account } from 'soapbox/schemas/index.ts';
|
import type { Account } from 'soapbox/schemas/index.ts';
|
||||||
|
|
||||||
interface IDisplayName {
|
interface IDisplayName {
|
||||||
account: Pick<Account, 'id' | 'acct' | 'fqn' | 'verified' | 'display_name'>;
|
account: Pick<Account, 'id' | 'acct' | 'emojis' | 'fqn' | 'verified' | 'display_name'>;
|
||||||
withSuffix?: boolean;
|
withSuffix?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ const DisplayNameInline: React.FC<IDisplayName> = ({ account, withSuffix = true
|
||||||
weight='normal'
|
weight='normal'
|
||||||
truncate
|
truncate
|
||||||
>
|
>
|
||||||
{account.display_name}
|
{emojifyText(account.display_name, account.emojis)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{verified && <VerificationBadge />}
|
{verified && <VerificationBadge />}
|
||||||
|
|
|
@ -2,16 +2,15 @@ import HoverRefWrapper from 'soapbox/components/hover-ref-wrapper.tsx';
|
||||||
import HStack from 'soapbox/components/ui/hstack.tsx';
|
import HStack from 'soapbox/components/ui/hstack.tsx';
|
||||||
import Text from 'soapbox/components/ui/text.tsx';
|
import Text from 'soapbox/components/ui/text.tsx';
|
||||||
import { useSoapboxConfig } from 'soapbox/hooks/useSoapboxConfig.ts';
|
import { useSoapboxConfig } from 'soapbox/hooks/useSoapboxConfig.ts';
|
||||||
|
import { getAcct } from 'soapbox/utils/accounts.ts';
|
||||||
import { getAcct } from '../utils/accounts.ts';
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
|
|
||||||
|
|
||||||
import VerificationBadge from './verification-badge.tsx';
|
import VerificationBadge from './verification-badge.tsx';
|
||||||
|
|
||||||
import type { Account } from 'soapbox/schemas/index.ts';
|
import type { Account } from 'soapbox/schemas/index.ts';
|
||||||
|
|
||||||
interface IDisplayName {
|
interface IDisplayName {
|
||||||
account: Pick<Account, 'id' | 'acct' | 'fqn' | 'verified' | 'display_name'>;
|
account: Pick<Account, 'id' | 'acct' | 'emojis' | 'fqn' | 'verified' | 'display_name'>;
|
||||||
withSuffix?: boolean;
|
withSuffix?: boolean;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +26,7 @@ const DisplayName: React.FC<IDisplayName> = ({ account, children, withSuffix = t
|
||||||
weight='semibold'
|
weight='semibold'
|
||||||
truncate
|
truncate
|
||||||
>
|
>
|
||||||
{account.display_name}
|
{emojifyText(account.display_name, account.emojis)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{verified && <VerificationBadge />}
|
{verified && <VerificationBadge />}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import { useState, useRef, useLayoutEffect, useMemo, memo } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import Icon from 'soapbox/components/icon.tsx';
|
import Icon from 'soapbox/components/icon.tsx';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
import { getTextDirection } from '../utils/rtl.ts';
|
import { getTextDirection } from 'soapbox/utils/rtl.ts';
|
||||||
|
|
||||||
import HashtagLink from './hashtag-link.tsx';
|
import HashtagLink from './hashtag-link.tsx';
|
||||||
import Markup from './markup.tsx';
|
import Markup from './markup.tsx';
|
||||||
|
@ -90,27 +90,7 @@ const StatusContent: React.FC<IStatusContent> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (domNode instanceof DOMText) {
|
if (domNode instanceof DOMText) {
|
||||||
const parts: Array<string | JSX.Element> = [];
|
return emojifyText(domNode.data, status.emojis.toJS());
|
||||||
|
|
||||||
const textNodes = domNode.data.split(/:\w+:/);
|
|
||||||
const shortcodes = [...domNode.data.matchAll(/:(\w+):/g)];
|
|
||||||
|
|
||||||
for (let i = 0; i < textNodes.length; i++) {
|
|
||||||
parts.push(textNodes[i]);
|
|
||||||
|
|
||||||
if (shortcodes[i]) {
|
|
||||||
const [text, shortcode] = shortcodes[i];
|
|
||||||
const customEmoji = status.emojis.find((e) => e.shortcode === shortcode);
|
|
||||||
|
|
||||||
if (customEmoji) {
|
|
||||||
parts.push(<img key={i} src={customEmoji.url} alt={shortcode} className='inline-block h-[1em]' />);
|
|
||||||
} else {
|
|
||||||
parts.push(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return <>{parts}</>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (domNode instanceof Element && domNode.name === 'a') {
|
if (domNode instanceof Element && domNode.name === 'a') {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import QuotedStatus from 'soapbox/features/status/containers/quoted-status-conta
|
||||||
import { HotKeys } from 'soapbox/features/ui/components/hotkeys.tsx';
|
import { HotKeys } from 'soapbox/features/ui/components/hotkeys.tsx';
|
||||||
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
||||||
import { useSettings } from 'soapbox/hooks/useSettings.ts';
|
import { useSettings } from 'soapbox/hooks/useSettings.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
import { defaultMediaVisibility, textForScreenReader, getActualStatus } from 'soapbox/utils/status.ts';
|
import { defaultMediaVisibility, textForScreenReader, getActualStatus } from 'soapbox/utils/status.ts';
|
||||||
|
|
||||||
import EventPreview from './event-preview.tsx';
|
import EventPreview from './event-preview.tsx';
|
||||||
|
@ -232,7 +233,7 @@ const Status: React.FC<IStatus> = (props) => {
|
||||||
>
|
>
|
||||||
<bdi className='truncate'>
|
<bdi className='truncate'>
|
||||||
<strong className='text-gray-800 dark:text-gray-200'>
|
<strong className='text-gray-800 dark:text-gray-200'>
|
||||||
{status.account.display_name}
|
{emojifyText(status.account.display_name, status.account.emojis)}
|
||||||
</strong>
|
</strong>
|
||||||
</bdi>
|
</bdi>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -263,7 +264,7 @@ const Status: React.FC<IStatus> = (props) => {
|
||||||
<Link to={`/@${status.account.acct}`} className='hover:underline'>
|
<Link to={`/@${status.account.acct}`} className='hover:underline'>
|
||||||
<bdi className='truncate'>
|
<bdi className='truncate'>
|
||||||
<strong className='text-gray-800 dark:text-gray-200'>
|
<strong className='text-gray-800 dark:text-gray-200'>
|
||||||
{status.account.display_name}
|
{emojifyText(status.account.display_name, status.account.emojis)}
|
||||||
</strong>
|
</strong>
|
||||||
</bdi>
|
</bdi>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
interface ICustomEmoji {
|
|
||||||
/** Custom emoji URL. */
|
|
||||||
url: string;
|
|
||||||
/** Image alt text, usually the shortcode. */
|
|
||||||
alt?: string;
|
|
||||||
/** `img` tag className. Default: `h-[1em]` */
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A single custom emoji image. */
|
|
||||||
const CustomEmoji: React.FC<ICustomEmoji> = (props): JSX.Element | null => {
|
|
||||||
const { url, alt, className = 'h-[1em]' } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<img src={url} alt={alt} className={className} />
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CustomEmoji;
|
|
|
@ -8,6 +8,7 @@ import Stack from 'soapbox/components/ui/stack.tsx';
|
||||||
import Text from 'soapbox/components/ui/text.tsx';
|
import Text from 'soapbox/components/ui/text.tsx';
|
||||||
import VerificationBadge from 'soapbox/components/verification-badge.tsx';
|
import VerificationBadge from 'soapbox/components/verification-badge.tsx';
|
||||||
import useAccountSearch from 'soapbox/queries/search.ts';
|
import useAccountSearch from 'soapbox/queries/search.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
|
|
||||||
import type { Account } from 'soapbox/types/entities.ts';
|
import type { Account } from 'soapbox/types/entities.ts';
|
||||||
|
|
||||||
|
@ -41,7 +42,10 @@ const Results = ({ accountSearchResult, onSelect }: IResults) => {
|
||||||
|
|
||||||
<Stack alignItems='start'>
|
<Stack alignItems='start'>
|
||||||
<div className='flex grow items-center space-x-1'>
|
<div className='flex grow items-center space-x-1'>
|
||||||
<Text weight='bold' size='sm' truncate>{account.display_name}</Text>
|
<Text weight='bold' size='sm' truncate>
|
||||||
|
{emojifyText(account.display_name, account.emojis)}
|
||||||
|
</Text>
|
||||||
|
|
||||||
{account.verified && <VerificationBadge />}
|
{account.verified && <VerificationBadge />}
|
||||||
</div>
|
</div>
|
||||||
<Text size='sm' weight='medium' theme='muted' direction='ltr' truncate>@{account.acct}</Text> {/* eslint-disable-line formatjs/no-literal-string-in-jsx */}
|
<Text size='sm' weight='medium' theme='muted' direction='ltr' truncate>@{account.acct}</Text> {/* eslint-disable-line formatjs/no-literal-string-in-jsx */}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import Stack from 'soapbox/components/ui/stack.tsx';
|
||||||
import Text from 'soapbox/components/ui/text.tsx';
|
import Text from 'soapbox/components/ui/text.tsx';
|
||||||
import VerificationBadge from 'soapbox/components/verification-badge.tsx';
|
import VerificationBadge from 'soapbox/components/verification-badge.tsx';
|
||||||
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
|
|
||||||
import ActionButton from '../ui/components/action-button.tsx';
|
import ActionButton from '../ui/components/action-button.tsx';
|
||||||
import { HotKeys } from '../ui/components/hotkeys.tsx';
|
import { HotKeys } from '../ui/components/hotkeys.tsx';
|
||||||
|
@ -47,7 +48,7 @@ const SuggestionItem: React.FC<ISuggestionItem> = ({ accountId }) => {
|
||||||
size='sm'
|
size='sm'
|
||||||
className='max-w-[95%]'
|
className='max-w-[95%]'
|
||||||
>
|
>
|
||||||
{account.display_name}
|
{emojifyText(account.display_name, account.emojis)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{account.verified && <VerificationBadge />}
|
{account.verified && <VerificationBadge />}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
||||||
import { useInstance } from 'soapbox/hooks/useInstance.ts';
|
import { useInstance } from 'soapbox/hooks/useInstance.ts';
|
||||||
import { makeGetNotification } from 'soapbox/selectors/index.ts';
|
import { makeGetNotification } from 'soapbox/selectors/index.ts';
|
||||||
import toast from 'soapbox/toast.tsx';
|
import toast from 'soapbox/toast.tsx';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
import { NotificationType, validType } from 'soapbox/utils/notification.ts';
|
import { NotificationType, validType } from 'soapbox/utils/notification.ts';
|
||||||
|
|
||||||
import type { ScrollPosition } from 'soapbox/components/status.tsx';
|
import type { ScrollPosition } from 'soapbox/components/status.tsx';
|
||||||
|
@ -57,7 +58,7 @@ const buildLink = (account: AccountEntity): JSX.Element => (
|
||||||
title={account.acct}
|
title={account.acct}
|
||||||
to={`/@${account.acct}`}
|
to={`/@${account.acct}`}
|
||||||
>
|
>
|
||||||
{account.display_name}
|
{emojifyText(account.display_name, account.emojis)}
|
||||||
</Link>
|
</Link>
|
||||||
</bdi>
|
</bdi>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Spinner from 'soapbox/components/ui/spinner.tsx';
|
||||||
import AccountContainer from 'soapbox/containers/account-container.tsx';
|
import AccountContainer from 'soapbox/containers/account-container.tsx';
|
||||||
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
||||||
import { makeGetAccount } from 'soapbox/selectors/index.ts';
|
import { makeGetAccount } from 'soapbox/selectors/index.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
|
|
||||||
const getAccount = makeGetAccount();
|
const getAccount = makeGetAccount();
|
||||||
|
|
||||||
|
@ -32,7 +33,7 @@ const FamiliarFollowersModal = ({ accountId, onClose }: IFamiliarFollowersModal)
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='account.familiar_followers.empty'
|
id='account.familiar_followers.empty'
|
||||||
defaultMessage='No one you know follows {name}.'
|
defaultMessage='No one you know follows {name}.'
|
||||||
values={{ name: account.display_name }}
|
values={{ name: emojifyText(account.display_name, account.emojis) }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ const FamiliarFollowersModal = ({ accountId, onClose }: IFamiliarFollowersModal)
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='column.familiar_followers'
|
id='column.familiar_followers'
|
||||||
defaultMessage='People you know following {name}'
|
defaultMessage='People you know following {name}'
|
||||||
values={{ name: account?.display_name ?? '' }}
|
values={{ name: account ? emojifyText(account.display_name, account.emojis) : '' }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
onClose={onClickClose}
|
onClose={onClickClose}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import Modal from 'soapbox/components/ui/modal.tsx';
|
||||||
import Stack from 'soapbox/components/ui/stack.tsx';
|
import Stack from 'soapbox/components/ui/stack.tsx';
|
||||||
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
||||||
import { ZapSplitData } from 'soapbox/schemas/zap-split.ts';
|
import { ZapSplitData } from 'soapbox/schemas/zap-split.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
|
|
||||||
import type { Account as AccountEntity } from 'soapbox/types/entities.ts';
|
import type { Account as AccountEntity } from 'soapbox/types/entities.ts';
|
||||||
|
|
||||||
|
@ -48,7 +49,13 @@ const ZapInvoiceModal: React.FC<IZapInvoice> = ({ account, invoice, splitData, o
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderTitle = () => {
|
const renderTitle = () => {
|
||||||
return <FormattedMessage id='zap.send_to' defaultMessage='Send zaps to {target}' values={{ target: account.display_name }} />;
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id='zap.send_to'
|
||||||
|
defaultMessage='Send zaps to {target}'
|
||||||
|
values={{ target: emojifyText(account.display_name, account.emojis) }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNext = () => {
|
const handleNext = () => {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import Button from 'soapbox/components/ui/button.tsx';
|
||||||
import HStack from 'soapbox/components/ui/hstack.tsx';
|
import HStack from 'soapbox/components/ui/hstack.tsx';
|
||||||
import Stack from 'soapbox/components/ui/stack.tsx';
|
import Stack from 'soapbox/components/ui/stack.tsx';
|
||||||
import { ZapSplitData } from 'soapbox/schemas/zap-split.ts';
|
import { ZapSplitData } from 'soapbox/schemas/zap-split.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
zap_open_wallet: { id: 'zap.open_wallet', defaultMessage: 'Open Wallet' },
|
zap_open_wallet: { id: 'zap.open_wallet', defaultMessage: 'Open Wallet' },
|
||||||
|
@ -31,7 +32,11 @@ const ZapSplit = ({ zapData, zapAmount, invoice, onNext, isLastStep, onFinish }:
|
||||||
const renderTitleQr = () => {
|
const renderTitleQr = () => {
|
||||||
return (
|
return (
|
||||||
<div className='max-w-[280px] truncate'>
|
<div className='max-w-[280px] truncate'>
|
||||||
<FormattedMessage id='zap.send_to' defaultMessage='Send zaps to {target}' values={{ target: account.display_name }} />
|
<FormattedMessage
|
||||||
|
id='zap.send_to'
|
||||||
|
defaultMessage='Send zaps to {target}'
|
||||||
|
values={{ target: emojifyText(account.display_name, account.emojis) }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
||||||
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
||||||
import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
|
import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
|
||||||
import { makeGetAccount } from 'soapbox/selectors/index.ts';
|
import { makeGetAccount } from 'soapbox/selectors/index.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
|
|
||||||
import type { Account } from 'soapbox/schemas/index.ts';
|
import type { Account } from 'soapbox/schemas/index.ts';
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ const ProfileFamiliarFollowers: React.FC<IProfileFamiliarFollowers> = ({ account
|
||||||
<Link className='inline-block text-primary-600 hover:underline dark:text-accent-blue' to={`/@${account.acct}`}>
|
<Link className='inline-block text-primary-600 hover:underline dark:text-accent-blue' to={`/@${account.acct}`}>
|
||||||
<HStack space={1} alignItems='center' grow>
|
<HStack space={1} alignItems='center' grow>
|
||||||
<Text size='sm' theme='primary' truncate>
|
<Text size='sm' theme='primary' truncate>
|
||||||
{account.display_name}
|
{emojifyText(account.display_name, account.emojis)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{account.verified && <VerificationBadge />}
|
{account.verified && <VerificationBadge />}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import Stack from 'soapbox/components/ui/stack.tsx';
|
||||||
import Text from 'soapbox/components/ui/text.tsx';
|
import Text from 'soapbox/components/ui/text.tsx';
|
||||||
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
||||||
import { useSoapboxConfig } from 'soapbox/hooks/useSoapboxConfig.ts';
|
import { useSoapboxConfig } from 'soapbox/hooks/useSoapboxConfig.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
import { capitalize } from 'soapbox/utils/strings.ts';
|
import { capitalize } from 'soapbox/utils/strings.ts';
|
||||||
|
|
||||||
import ProfileFamiliarFollowers from './profile-familiar-followers.tsx';
|
import ProfileFamiliarFollowers from './profile-familiar-followers.tsx';
|
||||||
|
@ -151,7 +152,7 @@ const ProfileInfoPanel: React.FC<IProfileInfoPanel> = ({ account, username }) =>
|
||||||
<Stack>
|
<Stack>
|
||||||
<HStack space={1} alignItems='center'>
|
<HStack space={1} alignItems='center'>
|
||||||
<Text size='lg' weight='bold' truncate>
|
<Text size='lg' weight='bold' truncate>
|
||||||
{deactivated ? intl.formatMessage(messages.deactivated) : account.display_name}
|
{deactivated ? intl.formatMessage(messages.deactivated) : emojifyText(account.display_name, account.emojis)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{account.bot && <Badge slug='bot' title={intl.formatMessage(messages.bot)} />}
|
{account.bot && <Badge slug='bot' title={intl.formatMessage(messages.bot)} />}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import Text from 'soapbox/components/ui/text.tsx';
|
||||||
import VerificationBadge from 'soapbox/components/verification-badge.tsx';
|
import VerificationBadge from 'soapbox/components/verification-badge.tsx';
|
||||||
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
||||||
import { getAcct } from 'soapbox/utils/accounts.ts';
|
import { getAcct } from 'soapbox/utils/accounts.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
import { shortNumberFormat } from 'soapbox/utils/numbers.tsx';
|
import { shortNumberFormat } from 'soapbox/utils/numbers.tsx';
|
||||||
import { displayFqn } from 'soapbox/utils/state.ts';
|
import { displayFqn } from 'soapbox/utils/state.ts';
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ const UserPanel: React.FC<IUserPanel> = ({ accountId, action, badges, domain })
|
||||||
<Link to={`/@${account.acct}`}>
|
<Link to={`/@${account.acct}`}>
|
||||||
<HStack space={1} alignItems='center'>
|
<HStack space={1} alignItems='center'>
|
||||||
<Text size='lg' weight='bold' truncate>
|
<Text size='lg' weight='bold' truncate>
|
||||||
{account.display_name}
|
{emojifyText(account.display_name, account.emojis)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{verified && <VerificationBadge />}
|
{verified && <VerificationBadge />}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import Stack from 'soapbox/components/ui/stack.tsx';
|
||||||
import SvgIcon from 'soapbox/components/ui/svg-icon.tsx';
|
import SvgIcon from 'soapbox/components/ui/svg-icon.tsx';
|
||||||
import Text from 'soapbox/components/ui/text.tsx';
|
import Text from 'soapbox/components/ui/text.tsx';
|
||||||
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
||||||
|
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||||
|
|
||||||
import ZapButton from './zap-button/zap-button.tsx';
|
import ZapButton from './zap-button/zap-button.tsx';
|
||||||
|
|
||||||
|
@ -113,7 +114,11 @@ const ZapPayRequestForm = ({ account, status, onClose }: IZapPayRequestForm) =>
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Text weight='semibold'>
|
<Text weight='semibold'>
|
||||||
<FormattedMessage id='zap.send_to' defaultMessage='Send zaps to {target}' values={{ target: account.display_name }} />
|
<FormattedMessage
|
||||||
|
id='zap.send_to'
|
||||||
|
defaultMessage='Send zaps to {target}'
|
||||||
|
values={{ target: emojifyText(account.display_name, account.emojis) }}
|
||||||
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
<Avatar src={account.avatar} size={50} />
|
<Avatar src={account.avatar} size={50} />
|
||||||
<DisplayNameInline account={account} />
|
<DisplayNameInline account={account} />
|
||||||
|
@ -141,12 +146,15 @@ const ZapPayRequestForm = ({ account, status, onClose }: IZapPayRequestForm) =>
|
||||||
{hasZapSplit && <p className='absolute right-0 font-bold sm:-right-6 sm:text-xl'>sats</p>}
|
{hasZapSplit && <p className='absolute right-0 font-bold sm:-right-6 sm:text-xl'>sats</p>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{hasZapSplit && <span className='flex justify-center text-xs'>
|
{hasZapSplit && (
|
||||||
|
<span className='flex justify-center text-xs'>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='zap.split_message.receiver'
|
id='zap.split_message.receiver'
|
||||||
defaultMessage='{receiver} will receive {amountReceiver} sats*' values={{ receiver: account.display_name, amountReceiver: zapSplitData.receiveAmount }}
|
defaultMessage='{receiver} will receive {amountReceiver} sats*'
|
||||||
|
values={{ receiver: emojifyText(account.display_name, account.emojis), amountReceiver: zapSplitData.receiveAmount }}
|
||||||
/>
|
/>
|
||||||
</span>}
|
</span>
|
||||||
|
)}
|
||||||
|
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
|
@ -162,7 +170,8 @@ const ZapPayRequestForm = ({ account, status, onClose }: IZapPayRequestForm) =>
|
||||||
<span className='text-[10px] sm:text-xs'>
|
<span className='text-[10px] sm:text-xs'>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='zap.split_message.deducted'
|
id='zap.split_message.deducted'
|
||||||
defaultMessage='{amountDeducted} sats will deducted*' values={{ instance: account.display_name, amountDeducted: zapSplitData.splitAmount }}
|
defaultMessage='{amountDeducted} sats will deducted*'
|
||||||
|
values={{ instance: emojifyText(account.display_name, account.emojis), amountDeducted: zapSplitData.splitAmount }}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { CustomEmoji } from 'soapbox/schemas/custom-emoji.ts';
|
||||||
|
|
||||||
|
/** Given text and a list of custom emojis, return JSX with the emojis rendered as `<img>` elements. */
|
||||||
|
export function emojifyText(text: string, emojis: CustomEmoji[]): JSX.Element {
|
||||||
|
const parts: Array<string | JSX.Element> = [];
|
||||||
|
|
||||||
|
const textNodes = text.split(/:\w+:/);
|
||||||
|
const shortcodes = [...text.matchAll(/:(\w+):/g)];
|
||||||
|
|
||||||
|
for (let i = 0; i < textNodes.length; i++) {
|
||||||
|
parts.push(textNodes[i]);
|
||||||
|
|
||||||
|
if (shortcodes[i]) {
|
||||||
|
const [match, shortcode] = shortcodes[i];
|
||||||
|
const customEmoji = emojis.find((e) => e.shortcode === shortcode);
|
||||||
|
|
||||||
|
if (customEmoji) {
|
||||||
|
parts.push(<img key={i} src={customEmoji.url} alt={shortcode} className='inline h-[1em] align-text-bottom' />);
|
||||||
|
} else {
|
||||||
|
parts.push(match);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>{parts}</>;
|
||||||
|
}
|
Loading…
Reference in New Issue