mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-14 00:08:46 +00:00
78 lines
2.2 KiB
TypeScript
78 lines
2.2 KiB
TypeScript
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
|
|
|
import { isList } from 'immutable';
|
|
|
|
import type { ApiCustomEmojiJSON } from '@/flavours/glitch/api_types/custom_emoji';
|
|
import { useAppSelector } from '@/flavours/glitch/store';
|
|
import { isModernEmojiEnabled } from '@/flavours/glitch/utils/environment';
|
|
|
|
import { toSupportedLocale } from './locale';
|
|
import { determineEmojiMode } from './mode';
|
|
import { emojifyElement } from './render';
|
|
import type {
|
|
CustomEmojiMapArg,
|
|
EmojiAppState,
|
|
ExtraCustomEmojiMap,
|
|
} from './types';
|
|
import { stringHasAnyEmoji } from './utils';
|
|
|
|
export function useEmojify(text: string, extraEmojis?: CustomEmojiMapArg) {
|
|
const [emojifiedText, setEmojifiedText] = useState<string | null>(null);
|
|
|
|
const appState = useEmojiAppState();
|
|
const extra: ExtraCustomEmojiMap = useMemo(() => {
|
|
if (!extraEmojis) {
|
|
return {};
|
|
}
|
|
if (isList(extraEmojis)) {
|
|
return (
|
|
extraEmojis.toJS() as ApiCustomEmojiJSON[]
|
|
).reduce<ExtraCustomEmojiMap>(
|
|
(acc, emoji) => ({ ...acc, [emoji.shortcode]: emoji }),
|
|
{},
|
|
);
|
|
}
|
|
return extraEmojis;
|
|
}, [extraEmojis]);
|
|
|
|
const emojify = useCallback(
|
|
async (input: string) => {
|
|
const wrapper = document.createElement('div');
|
|
wrapper.innerHTML = input;
|
|
const result = await emojifyElement(wrapper, appState, extra);
|
|
if (result) {
|
|
setEmojifiedText(result.innerHTML);
|
|
} else {
|
|
setEmojifiedText(input);
|
|
}
|
|
},
|
|
[appState, extra],
|
|
);
|
|
useLayoutEffect(() => {
|
|
if (isModernEmojiEnabled() && !!text.trim() && stringHasAnyEmoji(text)) {
|
|
void emojify(text);
|
|
} else {
|
|
// If no emoji or we don't want to render, fall back.
|
|
setEmojifiedText(text);
|
|
}
|
|
}, [emojify, text]);
|
|
|
|
return emojifiedText;
|
|
}
|
|
|
|
export function useEmojiAppState(): EmojiAppState {
|
|
const locale = useAppSelector((state) =>
|
|
toSupportedLocale(state.meta.get('locale') as string),
|
|
);
|
|
const mode = useAppSelector((state) =>
|
|
determineEmojiMode(state.meta.get('emoji_style') as string),
|
|
);
|
|
|
|
return {
|
|
currentLocale: locale,
|
|
locales: [locale],
|
|
mode,
|
|
darkTheme: document.body.classList.contains('theme-default'),
|
|
};
|
|
}
|