summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-01-09 15:50:25 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-01-09 15:50:25 +0900
commit462acc9eee3f89a926fd4b46ffed0b066519759b (patch)
tree3e8df5e6f490966c078fce12fd2d89f1385f58c0
parentfix(server): アンテナタイムライン(ストリーミング)が、... (diff)
downloadmisskey-462acc9eee3f89a926fd4b46ffed0b066519759b.tar.gz
misskey-462acc9eee3f89a926fd4b46ffed0b066519759b.tar.bz2
misskey-462acc9eee3f89a926fd4b46ffed0b066519759b.zip
カスタム絵文字一覧情報をmetaから分離
-rw-r--r--CHANGELOG.md2
-rw-r--r--packages/backend/src/core/entities/EmojiEntityService.ts8
-rw-r--r--packages/backend/src/models/schema/emoji.ts8
-rw-r--r--packages/backend/src/server/api/EndpointsModule.ts4
-rw-r--r--packages/backend/src/server/api/endpoints.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/emojis.ts91
-rw-r--r--packages/backend/src/server/api/endpoints/meta.ts57
-rw-r--r--packages/frontend/src/components/MkAutocomplete.vue5
-rw-r--r--packages/frontend/src/components/MkEmojiPicker.vue9
-rw-r--r--packages/frontend/src/custom-emojis.ts48
-rw-r--r--packages/frontend/src/instance.ts24
-rw-r--r--packages/frontend/src/local-storage.ts2
-rw-r--r--packages/frontend/src/pages/about.emojis.vue87
-rw-r--r--packages/frontend/src/pages/admin/emoji-edit-dialog.vue4
-rw-r--r--packages/frontend/src/pages/admin/overview.stats.vue5
-rw-r--r--packages/frontend/src/pages/mfm-cheat-sheet.vue5
-rw-r--r--packages/frontend/src/pages/settings/index.vue2
17 files changed, 212 insertions, 151 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 269f8b1000..43cf0ef6e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -40,6 +40,8 @@ You should also include the user name that made the change.
- Firefox109以下はサポートされなくなりました
#### For app developers
+- API: metaのレスポンスに`emojis`プロパティが含まれなくなりました
+ - カスタム絵文字一覧情報を取得するには、`emojis`エンドポイントにリクエストします
- API: カスタム絵文字エンティティに`url`プロパティが含まれなくなりました
- 絵文字画像を表示するには、`<instance host>/emoji/<emoji name>.webp`にリクエストすると画像が返ります。
- e.g. `https://p1.a9z.dev/emoji/misskey.webp`
diff --git a/packages/backend/src/core/entities/EmojiEntityService.ts b/packages/backend/src/core/entities/EmojiEntityService.ts
index 8a2dc70eda..2a4e09519f 100644
--- a/packages/backend/src/core/entities/EmojiEntityService.ts
+++ b/packages/backend/src/core/entities/EmojiEntityService.ts
@@ -22,23 +22,25 @@ export class EmojiEntityService {
@bindThis
public async pack(
src: Emoji['id'] | Emoji,
+ opts: { omitHost?: boolean; omitId?: boolean; } = {},
): Promise<Packed<'Emoji'>> {
const emoji = typeof src === 'object' ? src : await this.emojisRepository.findOneByOrFail({ id: src });
return {
- id: emoji.id,
+ id: opts.omitId ? undefined : emoji.id,
aliases: emoji.aliases,
name: emoji.name,
category: emoji.category,
- host: emoji.host,
+ host: opts.omitHost ? undefined : emoji.host,
};
}
@bindThis
public packMany(
emojis: any[],
+ opts: { omitHost?: boolean; omitId?: boolean; } = {},
) {
- return Promise.all(emojis.map(x => this.pack(x)));
+ return Promise.all(emojis.map(x => this.pack(x, opts)));
}
}
diff --git a/packages/backend/src/models/schema/emoji.ts b/packages/backend/src/models/schema/emoji.ts
index 9a52609b68..d897a0fc05 100644
--- a/packages/backend/src/models/schema/emoji.ts
+++ b/packages/backend/src/models/schema/emoji.ts
@@ -3,7 +3,7 @@ export const packedEmojiSchema = {
properties: {
id: {
type: 'string',
- optional: false, nullable: false,
+ optional: true, nullable: false,
format: 'id',
example: 'xxxxxxxxxx',
},
@@ -26,12 +26,8 @@ export const packedEmojiSchema = {
},
host: {
type: 'string',
- optional: false, nullable: true,
+ optional: true, nullable: true,
description: 'The local host is represented with `null`.',
},
- url: {
- type: 'string',
- optional: true, nullable: false,
- },
},
} as const;
diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts
index 60beca4f47..ab9349966d 100644
--- a/packages/backend/src/server/api/EndpointsModule.ts
+++ b/packages/backend/src/server/api/EndpointsModule.ts
@@ -220,6 +220,7 @@ import * as ep___messaging_messages_create from './endpoints/messaging/messages/
import * as ep___messaging_messages_delete from './endpoints/messaging/messages/delete.js';
import * as ep___messaging_messages_read from './endpoints/messaging/messages/read.js';
import * as ep___meta from './endpoints/meta.js';
+import * as ep___emojis from './endpoints/emojis.js';
import * as ep___miauth_genToken from './endpoints/miauth/gen-token.js';
import * as ep___mute_create from './endpoints/mute/create.js';
import * as ep___mute_delete from './endpoints/mute/delete.js';
@@ -550,6 +551,7 @@ const $messaging_messages_create: Provider = { provide: 'ep:messaging/messages/c
const $messaging_messages_delete: Provider = { provide: 'ep:messaging/messages/delete', useClass: ep___messaging_messages_delete.default };
const $messaging_messages_read: Provider = { provide: 'ep:messaging/messages/read', useClass: ep___messaging_messages_read.default };
const $meta: Provider = { provide: 'ep:meta', useClass: ep___meta.default };
+const $emojis: Provider = { provide: 'ep:emojis', useClass: ep___emojis.default };
const $miauth_genToken: Provider = { provide: 'ep:miauth/gen-token', useClass: ep___miauth_genToken.default };
const $mute_create: Provider = { provide: 'ep:mute/create', useClass: ep___mute_create.default };
const $mute_delete: Provider = { provide: 'ep:mute/delete', useClass: ep___mute_delete.default };
@@ -884,6 +886,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$messaging_messages_delete,
$messaging_messages_read,
$meta,
+ $emojis,
$miauth_genToken,
$mute_create,
$mute_delete,
@@ -1212,6 +1215,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$messaging_messages_delete,
$messaging_messages_read,
$meta,
+ $emojis,
$miauth_genToken,
$mute_create,
$mute_delete,
diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts
index d4f8be5b85..f9749ad660 100644
--- a/packages/backend/src/server/api/endpoints.ts
+++ b/packages/backend/src/server/api/endpoints.ts
@@ -219,6 +219,7 @@ import * as ep___messaging_messages_create from './endpoints/messaging/messages/
import * as ep___messaging_messages_delete from './endpoints/messaging/messages/delete.js';
import * as ep___messaging_messages_read from './endpoints/messaging/messages/read.js';
import * as ep___meta from './endpoints/meta.js';
+import * as ep___emojis from './endpoints/emojis.js';
import * as ep___miauth_genToken from './endpoints/miauth/gen-token.js';
import * as ep___mute_create from './endpoints/mute/create.js';
import * as ep___mute_delete from './endpoints/mute/delete.js';
@@ -547,6 +548,7 @@ const eps = [
['messaging/messages/delete', ep___messaging_messages_delete],
['messaging/messages/read', ep___messaging_messages_read],
['meta', ep___meta],
+ ['emojis', ep___emojis],
['miauth/gen-token', ep___miauth_genToken],
['mute/create', ep___mute_create],
['mute/delete', ep___mute_delete],
diff --git a/packages/backend/src/server/api/endpoints/emojis.ts b/packages/backend/src/server/api/endpoints/emojis.ts
new file mode 100644
index 0000000000..0a16268229
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/emojis.ts
@@ -0,0 +1,91 @@
+import { IsNull, MoreThan } from 'typeorm';
+import { Inject, Injectable } from '@nestjs/common';
+import type { EmojisRepository } from '@/models/index.js';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
+import type { Config } from '@/config.js';
+import { DI } from '@/di-symbols.js';
+
+export const meta = {
+ tags: ['meta'],
+
+ requireCredential: false,
+
+ res: {
+ type: 'object',
+ optional: false, nullable: false,
+ properties: {
+ emojis: {
+ type: 'array',
+ optional: false, nullable: false,
+ items: {
+ type: 'object',
+ optional: false, nullable: false,
+ properties: {
+ id: {
+ type: 'string',
+ optional: false, nullable: false,
+ format: 'id',
+ },
+ aliases: {
+ type: 'array',
+ optional: false, nullable: false,
+ items: {
+ type: 'string',
+ optional: false, nullable: false,
+ },
+ },
+ category: {
+ type: 'string',
+ optional: false, nullable: true,
+ },
+ },
+ },
+ },
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ },
+ required: [],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.config)
+ private config: Config,
+
+ @Inject(DI.emojisRepository)
+ private emojisRepository: EmojisRepository,
+
+ private emojiEntityService: EmojiEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const emojis = await this.emojisRepository.find({
+ where: {
+ host: IsNull(),
+ },
+ order: {
+ category: 'ASC',
+ name: 'ASC',
+ },
+ cache: {
+ id: 'meta_emojis',
+ milliseconds: 3600000, // 1 hour
+ },
+ });
+
+ return {
+ emojis: await this.emojiEntityService.packMany(emojis, {
+ omitId: true,
+ omitHost: true,
+ }),
+ };
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts
index 05da011979..c44d63d64b 100644
--- a/packages/backend/src/server/api/endpoints/meta.ts
+++ b/packages/backend/src/server/api/endpoints/meta.ts
@@ -4,7 +4,6 @@ import type { AdsRepository, EmojisRepository, UsersRepository } from '@/models/
import { MAX_NOTE_TEXT_LENGTH, DB_MAX_NOTE_TEXT_LENGTH } from '@/const.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
-import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { MetaService } from '@/core/MetaService.js';
import type { Config } from '@/config.js';
import { DI } from '@/di-symbols.js';
@@ -152,43 +151,6 @@ export const meta = {
type: 'number',
optional: false, nullable: false,
},
- emojis: {
- type: 'array',
- optional: false, nullable: false,
- items: {
- type: 'object',
- optional: false, nullable: false,
- properties: {
- id: {
- type: 'string',
- optional: false, nullable: false,
- format: 'id',
- },
- aliases: {
- type: 'array',
- optional: false, nullable: false,
- items: {
- type: 'string',
- optional: false, nullable: false,
- },
- },
- category: {
- type: 'string',
- optional: false, nullable: true,
- },
- host: {
- type: 'string',
- optional: false, nullable: true,
- description: 'The local host is represented with `null`.',
- },
- url: {
- type: 'string',
- optional: false, nullable: false,
- format: 'url',
- },
- },
- },
- },
ads: {
type: 'array',
optional: false, nullable: false,
@@ -326,30 +288,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
@Inject(DI.adsRepository)
private adsRepository: AdsRepository,
- @Inject(DI.emojisRepository)
- private emojisRepository: EmojisRepository,
-
private userEntityService: UserEntityService,
- private emojiEntityService: EmojiEntityService,
private metaService: MetaService,
) {
super(meta, paramDef, async (ps, me) => {
const instance = await this.metaService.fetch(true);
- const emojis = await this.emojisRepository.find({
- where: {
- host: IsNull(),
- },
- order: {
- category: 'ASC',
- name: 'ASC',
- },
- cache: {
- id: 'meta_emojis',
- milliseconds: 3600000, // 1 hour
- },
- });
-
const ads = await this.adsRepository.find({
where: {
expiresAt: MoreThan(new Date()),
@@ -390,7 +334,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
backgroundImageUrl: instance.backgroundImageUrl,
logoImageUrl: instance.logoImageUrl,
maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため
- emojis: await this.emojiEntityService.packMany(emojis),
defaultLightTheme: instance.defaultLightTheme,
defaultDarkTheme: instance.defaultDarkTheme,
ads: ads.map(ad => ({
diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue
index 8ed60bc5dc..0d0c5edbae 100644
--- a/packages/frontend/src/components/MkAutocomplete.vue
+++ b/packages/frontend/src/components/MkAutocomplete.vue
@@ -47,6 +47,9 @@ import { emojilist } from '@/scripts/emojilist';
import { instance } from '@/instance';
import { i18n } from '@/i18n';
import { miLocalStorage } from '@/local-storage';
+import { getCustomEmojis } from '@/custom-emojis';
+
+const customEmojis = await getCustomEmojis();
type EmojiDef = {
emoji: string;
@@ -86,7 +89,6 @@ for (const x of lib) {
emjdb.sort((a, b) => a.name.length - b.name.length);
//#region Construct Emoji DB
-const customEmojis = instance.emojis;
const emojiDefinitions: EmojiDef[] = [];
for (const x of customEmojis) {
@@ -117,7 +119,6 @@ export default {
emojiDb,
emojiDefinitions,
emojilist,
- customEmojis,
};
</script>
diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue
index f3b3ac0b50..8df01f6c25 100644
--- a/packages/frontend/src/components/MkEmojiPicker.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.vue
@@ -6,7 +6,7 @@
<div v-if="searchResultCustom.length > 0" class="body">
<button
v-for="emoji in searchResultCustom"
- :key="emoji.id"
+ :key="emoji.name"
class="_button item"
:title="emoji.name"
tabindex="0"
@@ -85,9 +85,10 @@ import MkRippleEffect from '@/components/MkRippleEffect.vue';
import * as os from '@/os';
import { isTouchUsing } from '@/scripts/touch';
import { deviceKind } from '@/scripts/device-kind';
-import { emojiCategories, instance } from '@/instance';
+import { instance } from '@/instance';
import { i18n } from '@/i18n';
import { defaultStore } from '@/store';
+import { getCustomEmojiCategories, getCustomEmojis } from '@/custom-emojis';
const props = withDefaults(defineProps<{
showPinned?: boolean;
@@ -103,6 +104,7 @@ const emit = defineEmits<{
(ev: 'chosen', v: string): void;
}>();
+const customEmojis = await getCustomEmojis();
const search = shallowRef<HTMLInputElement>();
const emojis = shallowRef<HTMLDivElement>();
@@ -118,8 +120,7 @@ const {
const size = computed(() => props.asReactionPicker ? reactionPickerSize.value : 1);
const width = computed(() => props.asReactionPicker ? reactionPickerWidth.value : 3);
const height = computed(() => props.asReactionPicker ? reactionPickerHeight.value : 2);
-const customEmojiCategories = emojiCategories;
-const customEmojis = instance.emojis;
+const customEmojiCategories = await getCustomEmojiCategories();
const q = ref<string>('');
const searchResultCustom = ref<Misskey.entities.CustomEmoji[]>([]);
const searchResultUnicode = ref<UnicodeEmojiDef[]>([]);
diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts
new file mode 100644
index 0000000000..2a52753f84
--- /dev/null
+++ b/packages/frontend/src/custom-emojis.ts
@@ -0,0 +1,48 @@
+import { api } from './os';
+import { miLocalStorage } from './local-storage';
+
+const storageCache = miLocalStorage.getItem('emojis');
+let cached = storageCache ? JSON.parse(storageCache) : null;
+export async function getCustomEmojis() {
+ const now = Date.now();
+ const lastFetchedAt = miLocalStorage.getItem('lastEmojisFetchedAt');
+ if (cached && lastFetchedAt && (now - parseInt(lastFetchedAt)) < 1000 * 60 * 60) return cached;
+
+ const res = await api('emojis', {});
+
+ cached = res.emojis;
+ miLocalStorage.setItem('emojis', JSON.stringify(cached));
+ miLocalStorage.setItem('lastEmojisFetchedAt', now.toString());
+}
+
+let cachedCategories;
+export async function getCustomEmojiCategories() {
+ if (cachedCategories) return cachedCategories;
+
+ const customEmojis = await getCustomEmojis();
+
+ const categories = new Set();
+ for (const emoji of customEmojis) {
+ categories.add(emoji.category);
+ }
+ const res = Array.from(categories);
+ cachedCategories = res;
+ return res;
+}
+
+let cachedTags;
+export async function getCustomEmojiTags() {
+ if (cachedTags) return cachedTags;
+
+ const customEmojis = await getCustomEmojis();
+
+ const tags = new Set();
+ for (const emoji of customEmojis) {
+ for (const tag of emoji.aliases) {
+ tags.add(tag);
+ }
+ }
+ const res = Array.from(tags);
+ cachedTags = res;
+ return res;
+}
diff --git a/packages/frontend/src/instance.ts b/packages/frontend/src/instance.ts
index 82d3e7aea2..08dbd9737c 100644
--- a/packages/frontend/src/instance.ts
+++ b/packages/frontend/src/instance.ts
@@ -5,11 +5,11 @@ import { miLocalStorage } from './local-storage';
// TODO: 他のタブと永続化されたstateを同期
-const instanceData = miLocalStorage.getItem('instance');
+const cached = miLocalStorage.getItem('instance');
// TODO: instanceをリアクティブにするかは再考の余地あり
-export const instance: Misskey.entities.InstanceMetadata = reactive(instanceData ? JSON.parse(instanceData) : {
+export const instance: Misskey.entities.InstanceMetadata = reactive(cached ? JSON.parse(cached) : {
// TODO: set default values
});
@@ -24,23 +24,3 @@ export async function fetchInstance() {
miLocalStorage.setItem('instance', JSON.stringify(instance));
}
-
-export const emojiCategories = computed(() => {
- if (instance.emojis == null) return [];
- const categories = new Set();
- for (const emoji of instance.emojis) {
- categories.add(emoji.category);
- }
- return Array.from(categories);
-});
-
-export const emojiTags = computed(() => {
- if (instance.emojis == null) return [];
- const tags = new Set();
- for (const emoji of instance.emojis) {
- for (const tag of emoji.aliases) {
- tags.add(tag);
- }
- }
- return Array.from(tags);
-});
diff --git a/packages/frontend/src/local-storage.ts b/packages/frontend/src/local-storage.ts
index 50e28d621f..bb8192e980 100644
--- a/packages/frontend/src/local-storage.ts
+++ b/packages/frontend/src/local-storage.ts
@@ -2,6 +2,8 @@ type Keys =
'v' |
'lastVersion' |
'instance' |
+ 'emojis' | // TODO: indexed db
+ 'lastEmojisFetchedAt' |
'account' |
'accounts' |
'latestDonationInfoShownAt' |
diff --git a/packages/frontend/src/pages/about.emojis.vue b/packages/frontend/src/pages/about.emojis.vue
index e15a2b1bdf..acf6237c87 100644
--- a/packages/frontend/src/pages/about.emojis.vue
+++ b/packages/frontend/src/pages/about.emojis.vue
@@ -7,7 +7,7 @@
<!-- たくさんあると邪魔
<div class="tags">
- <span class="tag _button" v-for="tag in tags" :class="{ active: selectedTags.has(tag) }" @click="toggleTag(tag)">{{ tag }}</span>
+ <span class="tag _button" v-for="tag in customEmojiTags" :class="{ active: selectedTags.has(tag) }" @click="toggleTag(tag)">{{ tag }}</span>
</div>
-->
</div>
@@ -28,8 +28,8 @@
</div>
</template>
-<script lang="ts">
-import { defineComponent, computed } from 'vue';
+<script lang="ts" setup>
+import { defineComponent, computed, watch } from 'vue';
import XEmoji from './emojis.emoji.vue';
import MkButton from '@/components/MkButton.vue';
import MkInput from '@/components/MkInput.vue';
@@ -37,62 +37,43 @@ import MkSelect from '@/components/MkSelect.vue';
import MkFoldableSection from '@/components/MkFoldableSection.vue';
import MkTab from '@/components/MkTab.vue';
import * as os from '@/os';
-import { emojiCategories, emojiTags } from '@/instance';
+import { getCustomEmojis, getCustomEmojiCategories, getCustomEmojiTags } from '@/custom-emojis';
-export default defineComponent({
- components: {
- MkButton,
- MkInput,
- MkSelect,
- MkFoldableSection,
- MkTab,
- XEmoji,
- },
+const customEmojis = await getCustomEmojis();
+const customEmojiCategories = await getCustomEmojiCategories();
+const customEmojiTags = await getCustomEmojiTags();
+let q = $ref('');
+let searchEmojis = $ref(null);
+let selectedTags = $ref(new Set());
- data() {
- return {
- q: '',
- customEmojiCategories: emojiCategories,
- customEmojis: this.$instance.emojis,
- tags: emojiTags,
- selectedTags: new Set(),
- searchEmojis: null,
- };
- },
-
- watch: {
- q() { this.search(); },
- selectedTags: {
- handler() {
- this.search();
- },
- deep: true,
- },
- },
+function search() {
+ if ((q === '' || q == null) && selectedTags.size === 0) {
+ searchEmojis = null;
+ return;
+ }
- methods: {
- search() {
- if ((this.q === '' || this.q == null) && this.selectedTags.size === 0) {
- this.searchEmojis = null;
- return;
- }
+ if (selectedTags.size === 0) {
+ searchEmojis = customEmojis.filter(emoji => emoji.name.includes(q) || emoji.aliases.includes(q));
+ } else {
+ searchEmojis = customEmojis.filter(emoji => (emoji.name.includes(q) || emoji.aliases.includes(q)) && [...selectedTags].every(t => emoji.aliases.includes(t)));
+ }
+}
- if (this.selectedTags.size === 0) {
- this.searchEmojis = this.customEmojis.filter(emoji => emoji.name.includes(this.q) || emoji.aliases.includes(this.q));
- } else {
- this.searchEmojis = this.customEmojis.filter(emoji => (emoji.name.includes(this.q) || emoji.aliases.includes(this.q)) && [...this.selectedTags].every(t => emoji.aliases.includes(t)));
- }
- },
+function toggleTag(tag) {
+ if (selectedTags.has(tag)) {
+ selectedTags.delete(tag);
+ } else {
+ selectedTags.add(tag);
+ }
+}
- toggleTag(tag) {
- if (this.selectedTags.has(tag)) {
- this.selectedTags.delete(tag);
- } else {
- this.selectedTags.add(tag);
- }
- },
- },
+watch($$(q), () => {
+ search();
});
+
+watch($$(selectedTags), () => {
+ search();
+}, { deep: true });
</script>
<style lang="scss" scoped>
diff --git a/packages/frontend/src/pages/admin/emoji-edit-dialog.vue b/packages/frontend/src/pages/admin/emoji-edit-dialog.vue
index c0a997d7b4..0b6a5e1557 100644
--- a/packages/frontend/src/pages/admin/emoji-edit-dialog.vue
+++ b/packages/frontend/src/pages/admin/emoji-edit-dialog.vue
@@ -36,7 +36,7 @@ import MkInput from '@/components/MkInput.vue';
import * as os from '@/os';
import { unique } from '@/scripts/array';
import { i18n } from '@/i18n';
-import { emojiCategories } from '@/instance';
+import { getCustomEmojiCategories } from '@/custom-emojis';
const props = defineProps<{
emoji: any,
@@ -46,7 +46,7 @@ let dialog = $ref(null);
let name: string = $ref(props.emoji.name);
let category: string = $ref(props.emoji.category);
let aliases: string = $ref(props.emoji.aliases.join(' '));
-let categories: string[] = $ref(emojiCategories);
+const categories = await getCustomEmojiCategories();
const emit = defineEmits<{
(ev: 'done', v: { deleted?: boolean, updated?: any }): void,
diff --git a/packages/frontend/src/pages/admin/overview.stats.vue b/packages/frontend/src/pages/admin/overview.stats.vue
index 43a735cbf9..08f31676f3 100644
--- a/packages/frontend/src/pages/admin/overview.stats.vue
+++ b/packages/frontend/src/pages/admin/overview.stats.vue
@@ -36,7 +36,7 @@
<div class="icon"><i class="ti ti-icons"></i></div>
<div class="body">
<div class="value">
- <MkNumber :value="$instance.emojis.length" style="margin-right: 0.5em;"/>
+ <MkNumber :value="customEmojis.length" style="margin-right: 0.5em;"/>
</div>
<div class="label">Custom emojis</div>
</div>
@@ -63,6 +63,9 @@ import number from '@/filters/number';
import MkNumberDiff from '@/components/MkNumberDiff.vue';
import MkNumber from '@/components/MkNumber.vue';
import { i18n } from '@/i18n';
+import { getCustomEmojis } from '@/custom-emojis';
+
+const customEmojis = await getCustomEmojis();
let stats: any = $ref(null);
let usersComparedToThePrevDay = $ref<number>();
diff --git a/packages/frontend/src/pages/mfm-cheat-sheet.vue b/packages/frontend/src/pages/mfm-cheat-sheet.vue
index 697a692743..f49b6959c8 100644
--- a/packages/frontend/src/pages/mfm-cheat-sheet.vue
+++ b/packages/frontend/src/pages/mfm-cheat-sheet.vue
@@ -317,12 +317,15 @@ import MkTextarea from '@/components/MkTextarea.vue';
import { definePageMetadata } from '@/scripts/page-metadata';
import { i18n } from '@/i18n';
import { instance } from '@/instance';
+import { getCustomEmojis } from '@/custom-emojis';
+
+const customEmojis = await getCustomEmojis();
let preview_mention = $ref('@example');
let preview_hashtag = $ref('#test');
let preview_url = $ref('https://example.com');
let preview_link = $ref(`[${i18n.ts._mfm.dummy}](https://example.com)`);
-let preview_emoji = $ref(instance.emojis.length ? `:${instance.emojis[0].name}:` : ':emojiname:');
+let preview_emoji = $ref(customEmojis.length ? `:${customEmojis[0].name}:` : ':emojiname:');
let preview_bold = $ref(`**${i18n.ts._mfm.dummy}**`);
let preview_small = $ref(`<small>${i18n.ts._mfm.dummy}</small>`);
let preview_center = $ref(`<center>${i18n.ts._mfm.dummy}</center>`);
diff --git a/packages/frontend/src/pages/settings/index.vue b/packages/frontend/src/pages/settings/index.vue
index 3468d44e00..e1e050ee70 100644
--- a/packages/frontend/src/pages/settings/index.vue
+++ b/packages/frontend/src/pages/settings/index.vue
@@ -183,6 +183,8 @@ const menuDef = computed(() => [{
action: () => {
miLocalStorage.removeItem('locale');
miLocalStorage.removeItem('theme');
+ miLocalStorage.removeItem('emojis');
+ miLocalStorage.removeItem('lastEmojisFetchedAt');
unisonReload();
},
}, {