feat(chat): preload and cache the custom emoji. Closes #3117

This commit is contained in:
Gabe Kangas 2023-06-27 15:48:16 -07:00
parent 8a4039217f
commit 02811ef37e
No known key found for this signature in database
GPG key ID: 4345B2060657F330
2 changed files with 36 additions and 21 deletions

View file

@ -72,6 +72,7 @@ export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText, enabled, fo
const websocketService = useRecoilValue<WebsocketService>(websocketServiceAtom);
const text = useRef(defaultText || '');
const [savedCursorLocation, setSavedCursorLocation] = useState(0);
const [customEmoji, setCustomEmoji] = useState([]);
// This is a bit of a hack to force the component to re-render when the text changes.
// By default when updating a ref the component doesn't re-render.
@ -211,6 +212,28 @@ export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText, enabled, fo
document.getElementById('chat-input-content-editable').focus();
}, []);
const getCustomEmoji = async () => {
try {
const response = await fetch(`/api/emoji`);
const emoji = await response.json();
setCustomEmoji(emoji);
emoji.forEach(e => {
const preImg = document.createElement('link');
preImg.href = e.url;
preImg.rel = 'preload';
preImg.as = 'image';
document.head.appendChild(preImg);
});
} catch (e) {
console.error('cannot fetch custom emoji', e);
}
};
useEffect(() => {
getCustomEmoji();
}, []);
return (
<div id="chat-input" className={styles.root}>
<div
@ -221,7 +244,11 @@ export const ChatTextField: FC<ChatTextFieldProps> = ({ defaultText, enabled, fo
>
<Popover
content={
<EmojiPicker onEmojiSelect={onEmojiSelect} onCustomEmojiSelect={onCustomEmojiSelect} />
<EmojiPicker
customEmoji={customEmoji}
onEmojiSelect={onEmojiSelect}
onCustomEmojiSelect={onCustomEmojiSelect}
/>
}
trigger="click"
placement="topRight"

View file

@ -1,31 +1,19 @@
import React, { FC, useEffect, useRef, useState } from 'react';
import React, { FC, useEffect, useRef } from 'react';
import { createPicker } from 'picmo';
const CUSTOM_EMOJI_URL = '/api/emoji';
export type EmojiPickerProps = {
onEmojiSelect: (emoji: string) => void;
onCustomEmojiSelect: (name: string, url: string) => void;
customEmoji: any[];
};
export const EmojiPicker: FC<EmojiPickerProps> = ({ onEmojiSelect, onCustomEmojiSelect }) => {
const [customEmoji, setCustomEmoji] = useState([]);
export const EmojiPicker: FC<EmojiPickerProps> = ({
onEmojiSelect,
onCustomEmojiSelect,
customEmoji,
}) => {
const ref = useRef();
const getCustomEmoji = async () => {
try {
const response = await fetch(CUSTOM_EMOJI_URL);
const emoji = await response.json();
setCustomEmoji(emoji);
} catch (e) {
console.error('cannot fetch custom emoji', e);
}
};
// Fetch the custom emoji on component mount.
useEffect(() => {
getCustomEmoji();
}, []);
// Recreate the emoji picker when the custom emoji changes.
useEffect(() => {
const e = customEmoji.map(emoji => ({
@ -48,7 +36,7 @@ export const EmojiPicker: FC<EmojiPickerProps> = ({ onEmojiSelect, onCustomEmoji
onEmojiSelect(event.emoji);
}
});
}, [customEmoji]);
}, []);
return <div ref={ref} />;
};