mirror of
https://github.com/mastodon/mastodon.git
synced 2026-05-12 08:34:17 +00:00
Emoji loading performance (#38784)
This commit is contained in:
parent
fdb2563abf
commit
5bc69ea668
|
|
@ -17,6 +17,7 @@ import { ToggleField } from '@/mastodon/components/form_fields';
|
|||
import { useElementHandledLink } from '@/mastodon/components/status/handled_link';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useCurrentAccountId } from '@/mastodon/hooks/useAccountId';
|
||||
import { useCustomEmojis } from '@/mastodon/hooks/useCustomEmojis';
|
||||
import { autoPlayGif } from '@/mastodon/initial_state';
|
||||
import {
|
||||
fetchProfile,
|
||||
|
|
@ -175,7 +176,7 @@ export const AccountEdit: FC = () => {
|
|||
}, [dispatch, profile?.bot]);
|
||||
|
||||
// Normally we would use the account emoji, but we want all custom emojis to be available to render after editing.
|
||||
const emojis = useAppSelector((state) => state.custom_emojis);
|
||||
const emojis = useCustomEmojis();
|
||||
const htmlHandlers = useElementHandledLink({
|
||||
hashtagAccountId: profile?.id,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,10 @@
|
|||
import { forwardRef, useCallback, useImperativeHandle, useState } from 'react';
|
||||
import {
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useImperativeHandle,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import type { FC, FocusEventHandler } from 'react';
|
||||
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
|
@ -9,6 +15,7 @@ import { closeModal } from '@/mastodon/actions/modal';
|
|||
import { Button } from '@/mastodon/components/button';
|
||||
import type { FieldStatus } from '@/mastodon/components/form_fields';
|
||||
import { EmojiTextInputField } from '@/mastodon/components/form_fields';
|
||||
import { useCustomEmojis } from '@/mastodon/hooks/useCustomEmojis';
|
||||
import {
|
||||
removeField,
|
||||
selectFieldById,
|
||||
|
|
@ -104,11 +111,6 @@ const selectFieldLimits = createAppSelector(
|
|||
|
||||
const RECOMMENDED_LIMIT = 40;
|
||||
|
||||
const selectEmojiCodes = createAppSelector(
|
||||
[(state) => state.custom_emojis],
|
||||
(emojis) => emojis.map((emoji) => emoji.get('shortcode')).toArray(),
|
||||
);
|
||||
|
||||
interface ConfirmationMessage {
|
||||
message: string;
|
||||
confirm: string;
|
||||
|
|
@ -143,7 +145,11 @@ export const EditFieldModal = forwardRef<
|
|||
value?: FieldStatus;
|
||||
}>({});
|
||||
|
||||
const customEmojiCodes = useAppSelector(selectEmojiCodes);
|
||||
const customEmojis = useCustomEmojis();
|
||||
const customEmojiCodes = useMemo(
|
||||
() => Object.keys(customEmojis ?? {}),
|
||||
[customEmojis],
|
||||
);
|
||||
const checkField = useCallback(
|
||||
(value: string): FieldStatus | null => {
|
||||
if (!value.trim()) {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import { CSS } from '@dnd-kit/utilities';
|
|||
import { CustomEmojiProvider } from '@/mastodon/components/emoji/context';
|
||||
import { normalizeKey } from '@/mastodon/components/hotkeys/utils';
|
||||
import { Icon } from '@/mastodon/components/icon';
|
||||
import { useCustomEmojis } from '@/mastodon/hooks/useCustomEmojis';
|
||||
import type { FieldData } from '@/mastodon/reducers/slices/profile_edit';
|
||||
import {
|
||||
patchProfile,
|
||||
|
|
@ -217,7 +218,7 @@ export const ReorderFieldsModal: FC<DialogModalProps> = ({ onClose }) => {
|
|||
void dispatch(patchProfile({ fields_attributes: newFields })).then(onClose);
|
||||
}, [dispatch, fieldKeys, fields, onClose]);
|
||||
|
||||
const emojis = useAppSelector((state) => state.custom_emojis);
|
||||
const emojis = useCustomEmojis();
|
||||
|
||||
return (
|
||||
// Add a wrapper here in the capture phase, so that it can be intercepted before the window listener in ModalRoot.
|
||||
|
|
|
|||
|
|
@ -267,6 +267,11 @@ export async function searchCustomEmojisByShortcodes(shortcodes: string[]) {
|
|||
return results.filter((emoji) => shortcodes.includes(emoji.shortcode));
|
||||
}
|
||||
|
||||
export async function loadAllCustomEmoji() {
|
||||
const db = await loadDB();
|
||||
return db.getAll('custom');
|
||||
}
|
||||
|
||||
export async function loadLegacyShortcodesByShortcode(shortcode: string) {
|
||||
const db = await loadDB();
|
||||
return db.getFromIndex(
|
||||
|
|
|
|||
|
|
@ -185,21 +185,16 @@ export function cleanExtraEmojis(extraEmojis?: CustomEmojiMapArg | null) {
|
|||
if (!extraEmojis) {
|
||||
return null;
|
||||
}
|
||||
if (Array.isArray(extraEmojis)) {
|
||||
return extraEmojis.reduce<ExtraCustomEmojiMap>(
|
||||
(acc, emoji) => ({ ...acc, [emoji.shortcode]: emoji }),
|
||||
{},
|
||||
);
|
||||
if (!Array.isArray(extraEmojis) && !isList(extraEmojis)) {
|
||||
return extraEmojis;
|
||||
}
|
||||
if (isList(extraEmojis)) {
|
||||
return extraEmojis
|
||||
.toJS()
|
||||
.reduce<ExtraCustomEmojiMap>(
|
||||
(acc, emoji) => ({ ...acc, [emoji.shortcode]: emoji }),
|
||||
{},
|
||||
);
|
||||
const emojis: ExtraCustomEmojiMap = {};
|
||||
const emojiArray = isList(extraEmojis) ? extraEmojis.toJS() : extraEmojis;
|
||||
for (const emoji of emojiArray) {
|
||||
emojis[emoji.shortcode] = emoji;
|
||||
}
|
||||
return extraEmojis;
|
||||
|
||||
return emojis;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import elephantUIPlane from '@/images/elephant_ui_plane.svg';
|
|||
import type { RenderSlideFn } from '@/mastodon/components/carousel';
|
||||
import { Carousel } from '@/mastodon/components/carousel';
|
||||
import { CustomEmojiProvider } from '@/mastodon/components/emoji/context';
|
||||
import { useCustomEmojis } from '@/mastodon/hooks/useCustomEmojis';
|
||||
import { mascot } from '@/mastodon/initial_state';
|
||||
import { createAppSelector, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
|
|
@ -23,7 +24,7 @@ const announcementSelector = createAppSelector(
|
|||
|
||||
export const Announcements: FC = () => {
|
||||
const announcements = useAppSelector(announcementSelector);
|
||||
const emojis = useAppSelector((state) => state.custom_emojis);
|
||||
const emojis = useCustomEmojis();
|
||||
|
||||
const renderSlide: RenderSlideFn<{
|
||||
id: string;
|
||||
|
|
|
|||
35
app/javascript/mastodon/hooks/useCustomEmojis.ts
Normal file
35
app/javascript/mastodon/hooks/useCustomEmojis.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
|
||||
import type { ExtraCustomEmojiMap } from '../features/emoji/types';
|
||||
|
||||
let emojis: ExtraCustomEmojiMap | null = null;
|
||||
|
||||
export function useCustomEmojis() {
|
||||
const [, setLoaded] = useState(emojis !== null);
|
||||
useEffect(() => {
|
||||
if (!emojis) {
|
||||
void loadEmojisIntoCache().then(() => {
|
||||
setLoaded(true);
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
return emojis;
|
||||
}
|
||||
|
||||
async function loadEmojisIntoCache() {
|
||||
const { loadAllCustomEmoji } = await import('../features/emoji/database');
|
||||
const emojisRaw = await loadAllCustomEmoji();
|
||||
if (emojisRaw.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
emojis = {};
|
||||
for (const emoji of emojisRaw) {
|
||||
emojis[emoji.shortcode] = {
|
||||
url: emoji.url,
|
||||
shortcode: emoji.shortcode,
|
||||
static_url: emoji.static_url,
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user