mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-13 15:58:50 +00:00
85 lines
2.5 KiB
TypeScript
85 lines
2.5 KiB
TypeScript
import { flattenEmojiData } from 'emojibase';
|
|
import type { CompactEmoji, FlatCompactEmoji } from 'emojibase';
|
|
|
|
import type { ApiCustomEmojiJSON } from '@/flavours/glitch/api_types/custom_emoji';
|
|
|
|
import {
|
|
putEmojiData,
|
|
putCustomEmojiData,
|
|
loadLatestEtag,
|
|
putLatestEtag,
|
|
} from './database';
|
|
import { toSupportedLocale, toSupportedLocaleOrCustom } from './locale';
|
|
import type { LocaleOrCustom } from './types';
|
|
import { emojiLogger } from './utils';
|
|
|
|
const log = emojiLogger('loader');
|
|
|
|
export async function importEmojiData(localeString: string) {
|
|
const locale = toSupportedLocale(localeString);
|
|
const emojis = await fetchAndCheckEtag<CompactEmoji[]>(locale);
|
|
if (!emojis) {
|
|
return;
|
|
}
|
|
const flattenedEmojis: FlatCompactEmoji[] = flattenEmojiData(emojis);
|
|
log('loaded %d for %s locale', flattenedEmojis.length, locale);
|
|
await putEmojiData(flattenedEmojis, locale);
|
|
}
|
|
|
|
export async function importCustomEmojiData() {
|
|
const emojis = await fetchAndCheckEtag<ApiCustomEmojiJSON[]>('custom');
|
|
if (!emojis) {
|
|
return;
|
|
}
|
|
log('loaded %d custom emojis', emojis.length);
|
|
await putCustomEmojiData(emojis);
|
|
}
|
|
|
|
async function fetchAndCheckEtag<ResultType extends object[]>(
|
|
localeOrCustom: LocaleOrCustom,
|
|
): Promise<ResultType | null> {
|
|
const locale = toSupportedLocaleOrCustom(localeOrCustom);
|
|
|
|
// Use location.origin as this script may be loaded from a CDN domain.
|
|
const url = new URL(location.origin);
|
|
if (locale === 'custom') {
|
|
url.pathname = '/api/v1/custom_emojis';
|
|
} else {
|
|
// This doesn't use isDevelopment() as that module loads initial state
|
|
// which breaks workers, as they cannot access the DOM.
|
|
url.pathname = `/packs${import.meta.env.DEV ? '-dev' : ''}/emoji/${locale}.json`;
|
|
}
|
|
|
|
const oldEtag = await loadLatestEtag(locale);
|
|
const response = await fetch(url, {
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'If-None-Match': oldEtag ?? '', // Send the old ETag to check for modifications
|
|
},
|
|
});
|
|
// If not modified, return null
|
|
if (response.status === 304) {
|
|
return null;
|
|
}
|
|
if (!response.ok) {
|
|
throw new Error(
|
|
`Failed to fetch emoji data for ${localeOrCustom}: ${response.statusText}`,
|
|
);
|
|
}
|
|
|
|
const data = (await response.json()) as ResultType;
|
|
if (!Array.isArray(data)) {
|
|
throw new Error(
|
|
`Unexpected data format for ${localeOrCustom}: expected an array`,
|
|
);
|
|
}
|
|
|
|
// Store the ETag for future requests
|
|
const etag = response.headers.get('ETag');
|
|
if (etag) {
|
|
await putLatestEtag(etag, localeOrCustom);
|
|
}
|
|
|
|
return data;
|
|
}
|