mirror of
https://github.com/mastodon/mastodon.git
synced 2025-10-05 16:42:47 +00:00
move HTML and Text components into the Emoji directory
Some checks are pending
Chromatic / Run Chromatic (push) Waiting to run
Some checks are pending
Chromatic / Run Chromatic (push) Waiting to run
This commit is contained in:
parent
2e7629d03b
commit
3188a0e11e
|
@ -2,10 +2,11 @@ import { useCallback } from 'react';
|
|||
|
||||
import { useLinks } from 'mastodon/hooks/useLinks';
|
||||
|
||||
import { EmojiHTML } from '../features/emoji/emoji_html';
|
||||
import { useAppSelector } from '../store';
|
||||
import { isModernEmojiEnabled } from '../utils/environment';
|
||||
|
||||
import { EmojiHTML } from './emoji/html';
|
||||
|
||||
interface AccountBioProps {
|
||||
className: string;
|
||||
accountId: string;
|
||||
|
|
|
@ -2,7 +2,7 @@ import type { ComponentPropsWithoutRef, FC } from 'react';
|
|||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { EmojiText } from '@/mastodon/features/emoji/emoji_text';
|
||||
import { EmojiText } from '@/mastodon/components/emoji/text';
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
|
||||
import { AnimateEmojiProvider } from '../emoji/context';
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import type { ComponentPropsWithoutRef, FC } from 'react';
|
||||
|
||||
import { ModernEmojiText } from '@/mastodon/features/emoji/emoji_text';
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
|
||||
import { AnimateEmojiProvider } from '../emoji/context';
|
||||
import { ModernEmojiText } from '../emoji/text';
|
||||
|
||||
import type { DisplayNameProps } from './index';
|
||||
|
||||
|
|
|
@ -3,10 +3,14 @@ import type {
|
|||
ElementType,
|
||||
PropsWithChildren,
|
||||
} from 'react';
|
||||
import { createContext, useCallback, useState } from 'react';
|
||||
import { createContext, useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import { cleanExtraEmojis } from '@/mastodon/features/emoji/normalize';
|
||||
import { autoPlayGif } from '@/mastodon/initial_state';
|
||||
import type { ExtraCustomEmojiMap } from 'mastodon/features/emoji/types';
|
||||
import type {
|
||||
CustomEmojiMapArg,
|
||||
ExtraCustomEmojiMap,
|
||||
} from 'mastodon/features/emoji/types';
|
||||
|
||||
// Animation context
|
||||
export const AnimateEmojiContext = createContext(autoPlayGif ?? false);
|
||||
|
@ -47,10 +51,11 @@ export const CustomEmojiContext = createContext<ExtraCustomEmojiMap>({});
|
|||
|
||||
export const CustomEmojiProvider = ({
|
||||
children,
|
||||
emoji = {},
|
||||
}: PropsWithChildren<{ emoji?: ExtraCustomEmojiMap | null }>) => {
|
||||
emojis: rawEmojis,
|
||||
}: PropsWithChildren<{ emojis?: CustomEmojiMapArg }>) => {
|
||||
const emojis = useMemo(() => cleanExtraEmojis(rawEmojis) ?? {}, [rawEmojis]);
|
||||
return (
|
||||
<CustomEmojiContext.Provider value={emoji ?? {}}>
|
||||
<CustomEmojiContext.Provider value={emojis}>
|
||||
{children}
|
||||
</CustomEmojiContext.Provider>
|
||||
);
|
||||
|
|
|
@ -3,14 +3,12 @@ import type { ComponentPropsWithoutRef, ElementType } from 'react';
|
|||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { Emoji } from '@/mastodon/components/emoji';
|
||||
import { CustomEmojiProvider } from '@/mastodon/components/emoji/context';
|
||||
import type { CustomEmojiMapArg } from '@/mastodon/features/emoji/types';
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
import { htmlStringToComponents } from '@/mastodon/utils/html';
|
||||
|
||||
import { cleanExtraEmojis } from './normalize';
|
||||
import { tokenizeText } from './render';
|
||||
import type { CustomEmojiMapArg } from './types';
|
||||
import { CustomEmojiProvider } from './context';
|
||||
import { textToEmojis } from './index';
|
||||
|
||||
type EmojiHTMLProps<Element extends ElementType = 'div'> = Omit<
|
||||
ComponentPropsWithoutRef<Element>,
|
||||
|
@ -19,21 +17,11 @@ type EmojiHTMLProps<Element extends ElementType = 'div'> = Omit<
|
|||
htmlString: string;
|
||||
extraEmojis?: CustomEmojiMapArg;
|
||||
as?: Element;
|
||||
shallow?: boolean;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export function onText(text: string) {
|
||||
return tokenizeText(text).map((token, index) => {
|
||||
if (typeof token === 'string') {
|
||||
return token;
|
||||
}
|
||||
return <Emoji code={token.code} key={`emoji-${token.code}-${index}`} />;
|
||||
});
|
||||
}
|
||||
|
||||
export const ModernEmojiHTML = ({
|
||||
extraEmojis: rawExtraEmojis,
|
||||
extraEmojis,
|
||||
htmlString,
|
||||
as: Wrapper = 'div', // Rename for syntax highlighting
|
||||
shallow,
|
||||
|
@ -41,20 +29,16 @@ export const ModernEmojiHTML = ({
|
|||
...props
|
||||
}: EmojiHTMLProps<ElementType>) => {
|
||||
const contents = useMemo(
|
||||
() => htmlStringToComponents(htmlString, { onText }),
|
||||
() => htmlStringToComponents(htmlString, { onText: textToEmojis }),
|
||||
[htmlString],
|
||||
);
|
||||
const extraEmojis = useMemo(
|
||||
() => cleanExtraEmojis(rawExtraEmojis),
|
||||
[rawExtraEmojis],
|
||||
);
|
||||
const components = (
|
||||
<Wrapper {...props} className={className}>
|
||||
{contents}
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
return (
|
||||
<CustomEmojiProvider emoji={extraEmojis}>{components}</CustomEmojiProvider>
|
||||
<CustomEmojiProvider emojis={extraEmojis}>
|
||||
<Wrapper {...props} className={className}>
|
||||
{contents}
|
||||
</Wrapper>
|
||||
</CustomEmojiProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -64,14 +48,7 @@ export const EmojiHTML = <Element extends ElementType>(
|
|||
if (isModernEmojiEnabled()) {
|
||||
return <ModernEmojiHTML {...props} />;
|
||||
}
|
||||
const {
|
||||
as: asElement,
|
||||
htmlString,
|
||||
extraEmojis,
|
||||
className,
|
||||
shallow,
|
||||
...rest
|
||||
} = props;
|
||||
const { as: asElement, htmlString, extraEmojis, className, ...rest } = props;
|
||||
const Wrapper = asElement ?? 'div';
|
||||
return (
|
||||
<Wrapper
|
|
@ -9,6 +9,7 @@ import {
|
|||
loadEmojiDataToState,
|
||||
shouldRenderImage,
|
||||
stringToEmojiState,
|
||||
tokenizeText,
|
||||
} from '@/mastodon/features/emoji/render';
|
||||
|
||||
import { AnimateEmojiContext, CustomEmojiContext } from './context';
|
||||
|
@ -83,3 +84,16 @@ export const Emoji: FC<EmojiProps> = ({
|
|||
/>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes a text string and converts it to an array of React nodes.
|
||||
* @param text The text to be tokenized and converted.
|
||||
*/
|
||||
export function textToEmojis(text: string) {
|
||||
return tokenizeText(text).map((token, index) => {
|
||||
if (typeof token === 'string') {
|
||||
return token;
|
||||
}
|
||||
return <Emoji code={token.code} key={`emoji-${token.code}-${index}`} />;
|
||||
});
|
||||
}
|
||||
|
|
24
app/javascript/mastodon/components/emoji/text.tsx
Normal file
24
app/javascript/mastodon/components/emoji/text.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { useMemo } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import type { CustomEmojiMapArg } from '@/mastodon/features/emoji/types';
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
|
||||
import { CustomEmojiProvider } from './context';
|
||||
import { textToEmojis } from './index';
|
||||
|
||||
interface EmojiTextProps {
|
||||
text: string;
|
||||
extraEmojis?: CustomEmojiMapArg;
|
||||
}
|
||||
|
||||
export const ModernEmojiText: FC<EmojiTextProps> = ({ text, extraEmojis }) => {
|
||||
const contents = useMemo(() => textToEmojis(text), [text]);
|
||||
|
||||
return (
|
||||
<CustomEmojiProvider emojis={extraEmojis}>{contents}</CustomEmojiProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export const EmojiText: FC<EmojiTextProps> = ({ text }) =>
|
||||
isModernEmojiEnabled() ? <ModernEmojiText text={text} /> : text;
|
|
@ -13,10 +13,12 @@ import ChevronRightIcon from '@/material-icons/400-24px/chevron_right.svg?react'
|
|||
import { Icon } from 'mastodon/components/icon';
|
||||
import { Poll } from 'mastodon/components/poll';
|
||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { autoPlayGif, languages as preloadedLanguages } from 'mastodon/initial_state';
|
||||
import { EmojiHTML } from '../features/emoji/emoji_html';
|
||||
import { languages as preloadedLanguages } from 'mastodon/initial_state';
|
||||
|
||||
import { isModernEmojiEnabled } from '../utils/environment';
|
||||
|
||||
import { EmojiHTML } from './emoji/html';
|
||||
|
||||
const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
import { useMemo } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { CustomEmojiProvider } from '@/mastodon/components/emoji/context';
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
|
||||
import { onText } from './emoji_html';
|
||||
import { cleanExtraEmojis } from './normalize';
|
||||
import type { CustomEmojiMapArg } from './types';
|
||||
|
||||
interface EmojiTextProps {
|
||||
text: string;
|
||||
extraEmojis?: CustomEmojiMapArg;
|
||||
}
|
||||
|
||||
export const ModernEmojiText: FC<EmojiTextProps> = ({
|
||||
text,
|
||||
extraEmojis: rawExtraEmojis,
|
||||
}) => {
|
||||
const contents = useMemo(() => onText(text), [text]);
|
||||
const extraEmojis = useMemo(
|
||||
() => cleanExtraEmojis(rawExtraEmojis),
|
||||
[rawExtraEmojis],
|
||||
);
|
||||
|
||||
return (
|
||||
<CustomEmojiProvider emoji={extraEmojis}>{contents}</CustomEmojiProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export const EmojiText: FC<EmojiTextProps> = ({ text }) =>
|
||||
isModernEmojiEnabled() ? <ModernEmojiText text={text} /> : text;
|
Loading…
Reference in New Issue
Block a user