wip
This commit is contained in:
parent
51afc9ace9
commit
0163f07e4e
61
packages/frontend-embed/src/custom-emojis.ts
Normal file
61
packages/frontend-embed/src/custom-emojis.ts
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { shallowRef, computed, markRaw, watch } from 'vue';
|
||||||
|
import * as Misskey from 'misskey-js';
|
||||||
|
import { misskeyApi, misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||||
|
import { get, set } from '@/scripts/idb-proxy.js';
|
||||||
|
|
||||||
|
const storageCache = await get('emojis');
|
||||||
|
export const customEmojis = shallowRef<Misskey.entities.EmojiSimple[]>(Array.isArray(storageCache) ? storageCache : []);
|
||||||
|
export const customEmojiCategories = computed<[ ...string[], null ]>(() => {
|
||||||
|
const categories = new Set<string>();
|
||||||
|
for (const emoji of customEmojis.value) {
|
||||||
|
if (emoji.category && emoji.category !== 'null') {
|
||||||
|
categories.add(emoji.category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return markRaw([...Array.from(categories), null]);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const customEmojisMap = new Map<string, Misskey.entities.EmojiSimple>();
|
||||||
|
watch(customEmojis, emojis => {
|
||||||
|
customEmojisMap.clear();
|
||||||
|
for (const emoji of emojis) {
|
||||||
|
customEmojisMap.set(emoji.name, emoji);
|
||||||
|
}
|
||||||
|
}, { immediate: true });
|
||||||
|
|
||||||
|
export async function fetchCustomEmojis(force = false) {
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
let res;
|
||||||
|
if (force) {
|
||||||
|
res = await misskeyApi('emojis', {});
|
||||||
|
} else {
|
||||||
|
const lastFetchedAt = await get('lastEmojisFetchedAt');
|
||||||
|
if (lastFetchedAt && (now - lastFetchedAt) < 1000 * 60 * 60) return;
|
||||||
|
res = await misskeyApiGet('emojis', {});
|
||||||
|
}
|
||||||
|
|
||||||
|
customEmojis.value = res.emojis;
|
||||||
|
set('emojis', res.emojis);
|
||||||
|
set('lastEmojisFetchedAt', now);
|
||||||
|
}
|
||||||
|
|
||||||
|
let cachedTags;
|
||||||
|
export function getCustomEmojiTags() {
|
||||||
|
if (cachedTags) return cachedTags;
|
||||||
|
|
||||||
|
const tags = new Set();
|
||||||
|
for (const emoji of customEmojis.value) {
|
||||||
|
for (const tag of emoji.aliases) {
|
||||||
|
tags.add(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const res = Array.from(tags);
|
||||||
|
cachedTags = res;
|
||||||
|
return res;
|
||||||
|
}
|
99
packages/frontend-embed/src/misskey-api.ts
Normal file
99
packages/frontend-embed/src/misskey-api.ts
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as Misskey from 'misskey-js';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { apiUrl } from '@/config.js';
|
||||||
|
|
||||||
|
export const pendingApiRequestsCount = ref(0);
|
||||||
|
|
||||||
|
// Implements Misskey.api.ApiClient.request
|
||||||
|
export function misskeyApi<
|
||||||
|
ResT = void,
|
||||||
|
E extends keyof Misskey.Endpoints = keyof Misskey.Endpoints,
|
||||||
|
P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req'],
|
||||||
|
_ResT = ResT extends void ? Misskey.api.SwitchCaseResponseType<E, P> : ResT,
|
||||||
|
>(
|
||||||
|
endpoint: E,
|
||||||
|
data: P = {} as any,
|
||||||
|
signal?: AbortSignal,
|
||||||
|
): Promise<_ResT> {
|
||||||
|
if (endpoint.includes('://')) throw new Error('invalid endpoint');
|
||||||
|
pendingApiRequestsCount.value++;
|
||||||
|
|
||||||
|
const onFinally = () => {
|
||||||
|
pendingApiRequestsCount.value--;
|
||||||
|
};
|
||||||
|
|
||||||
|
const promise = new Promise<_ResT>((resolve, reject) => {
|
||||||
|
// Send request
|
||||||
|
window.fetch(`${apiUrl}/${endpoint}`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
credentials: 'omit',
|
||||||
|
cache: 'no-cache',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
signal,
|
||||||
|
}).then(async (res) => {
|
||||||
|
const body = res.status === 204 ? null : await res.json();
|
||||||
|
|
||||||
|
if (res.status === 200) {
|
||||||
|
resolve(body);
|
||||||
|
} else if (res.status === 204) {
|
||||||
|
resolve(undefined as _ResT); // void -> undefined
|
||||||
|
} else {
|
||||||
|
reject(body.error);
|
||||||
|
}
|
||||||
|
}).catch(reject);
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.then(onFinally, onFinally);
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements Misskey.api.ApiClient.request
|
||||||
|
export function misskeyApiGet<
|
||||||
|
ResT = void,
|
||||||
|
E extends keyof Misskey.Endpoints = keyof Misskey.Endpoints,
|
||||||
|
P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req'],
|
||||||
|
_ResT = ResT extends void ? Misskey.api.SwitchCaseResponseType<E, P> : ResT,
|
||||||
|
>(
|
||||||
|
endpoint: E,
|
||||||
|
data: P = {} as any,
|
||||||
|
): Promise<_ResT> {
|
||||||
|
pendingApiRequestsCount.value++;
|
||||||
|
|
||||||
|
const onFinally = () => {
|
||||||
|
pendingApiRequestsCount.value--;
|
||||||
|
};
|
||||||
|
|
||||||
|
const query = new URLSearchParams(data as any);
|
||||||
|
|
||||||
|
const promise = new Promise<_ResT>((resolve, reject) => {
|
||||||
|
// Send request
|
||||||
|
window.fetch(`${apiUrl}/${endpoint}?${query}`, {
|
||||||
|
method: 'GET',
|
||||||
|
credentials: 'omit',
|
||||||
|
cache: 'default',
|
||||||
|
}).then(async (res) => {
|
||||||
|
const body = res.status === 204 ? null : await res.json();
|
||||||
|
|
||||||
|
if (res.status === 200) {
|
||||||
|
resolve(body);
|
||||||
|
} else if (res.status === 204) {
|
||||||
|
resolve(undefined as _ResT); // void -> undefined
|
||||||
|
} else {
|
||||||
|
reject(body.error);
|
||||||
|
}
|
||||||
|
}).catch(reject);
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.then(onFinally, onFinally);
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
Loading…
Reference in a new issue