From 21e4c3dfe9b439a76782ab86be93298de2878ab9 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 16 Jan 2023 09:39:58 +0000 Subject: [PATCH 01/25] wip --- .../src/server/api/endpoints/emojis.ts | 4 +- .../src/components/MkAutocomplete.vue | 90 +++++++++---------- .../frontend/src/components/MkEmojiPicker.vue | 4 +- packages/frontend/src/custom-emojis.ts | 18 ++-- packages/frontend/src/pages/about.emojis.vue | 7 +- .../src/pages/custom-emojis-manager.vue | 8 ++ .../frontend/src/pages/mfm-cheat-sheet.vue | 2 +- packages/frontend/src/scripts/aiscript/api.ts | 2 +- 8 files changed, 74 insertions(+), 61 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/emojis.ts b/packages/backend/src/server/api/endpoints/emojis.ts index 97dcfde59..67538b0bd 100644 --- a/packages/backend/src/server/api/endpoints/emojis.ts +++ b/packages/backend/src/server/api/endpoints/emojis.ts @@ -10,6 +10,8 @@ export const meta = { tags: ['meta'], requireCredential: false, + allowGet: true, + cacheSec: 60, res: { type: 'object', @@ -75,7 +77,7 @@ export default class extends Endpoint { }, cache: { id: 'meta_emojis', - milliseconds: 3600000, // 1 hour + milliseconds: 60000, // 1 minute }, }); diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue index 702fba979..ab4bf4f79 100644 --- a/packages/frontend/src/components/MkAutocomplete.vue +++ b/packages/frontend/src/components/MkAutocomplete.vue @@ -33,7 +33,7 @@ @@ -230,7 +230,7 @@ function exec() { } else if (props.type === 'emoji') { if (!props.q || props.q === '') { // 最近使った絵文字をサジェスト - emojis.value = defaultStore.state.recentlyUsedEmojis.map(emoji => emojiDb.find(dbEmoji => dbEmoji.emoji === emoji)).filter(x => x) as EmojiDef[]; + emojis.value = defaultStore.state.recentlyUsedEmojis.map(emoji => emojiDb.value.find(dbEmoji => dbEmoji.emoji === emoji)).filter(x => x) as EmojiDef[]; return; } diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 9c6d62ce8..abb14564f 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -138,7 +138,7 @@ watch(q, () => { const searchCustom = () => { const max = 8; - const emojis = customEmojis; + const emojis = customEmojis.value; const matches = new Set(); const exactMatch = emojis.find(emoji => emoji.name === newQ); @@ -323,7 +323,7 @@ function done(query?: string): boolean | void { if (query == null || typeof query !== 'string') return; const q2 = query.replace(/:/g, ''); - const exactMatchCustom = customEmojis.find(emoji => emoji.name === q2); + const exactMatchCustom = customEmojis.value.find(emoji => emoji.name === q2); if (exactMatchCustom) { chosen(exactMatchCustom); return true; diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts index 19469999b..52a114823 100644 --- a/packages/frontend/src/custom-emojis.ts +++ b/packages/frontend/src/custom-emojis.ts @@ -1,20 +1,22 @@ -import { api } from './os'; +import { apiGet } from './os'; import { miLocalStorage } from './local-storage'; +import { shallowRef } from 'vue'; +import * as Misskey from 'misskey-js'; const storageCache = miLocalStorage.getItem('emojis'); -export let customEmojis = storageCache ? JSON.parse(storageCache) : []; +export const customEmojis = shallowRef(storageCache ? JSON.parse(storageCache) : []); fetchCustomEmojis(); export async function fetchCustomEmojis() { const now = Date.now(); const lastFetchedAt = miLocalStorage.getItem('lastEmojisFetchedAt'); - if (lastFetchedAt && (now - parseInt(lastFetchedAt)) < 1000 * 60 * 60) return; + if (lastFetchedAt && (now - parseInt(lastFetchedAt)) < 1000 * 60) return; - const res = await api('emojis', {}); + const res = await apiGet('emojis', {}); - customEmojis = res.emojis; - miLocalStorage.setItem('emojis', JSON.stringify(customEmojis)); + customEmojis.value = res.emojis; + miLocalStorage.setItem('emojis', JSON.stringify(res.emojis)); miLocalStorage.setItem('lastEmojisFetchedAt', now.toString()); } @@ -23,7 +25,7 @@ export function getCustomEmojiCategories() { if (cachedCategories) return cachedCategories; const categories = new Set(); - for (const emoji of customEmojis) { + for (const emoji of customEmojis.value) { categories.add(emoji.category); } const res = Array.from(categories); @@ -36,7 +38,7 @@ export function getCustomEmojiTags() { if (cachedTags) return cachedTags; const tags = new Set(); - for (const emoji of customEmojis) { + for (const emoji of customEmojis.value) { for (const tag of emoji.aliases) { tags.add(tag); } diff --git a/packages/frontend/src/pages/about.emojis.vue b/packages/frontend/src/pages/about.emojis.vue index c0145a503..7d146d1fd 100644 --- a/packages/frontend/src/pages/about.emojis.vue +++ b/packages/frontend/src/pages/about.emojis.vue @@ -41,11 +41,12 @@ import MkTab from '@/components/MkTab.vue'; import * as os from '@/os'; import { customEmojis, getCustomEmojiCategories, getCustomEmojiTags } from '@/custom-emojis'; import { i18n } from '@/i18n'; +import * as Misskey from 'misskey-js'; const customEmojiCategories = getCustomEmojiCategories(); const customEmojiTags = getCustomEmojiTags(); let q = $ref(''); -let searchEmojis = $ref(null); +let searchEmojis = $ref(null); let selectedTags = $ref(new Set()); function search() { @@ -55,9 +56,9 @@ function search() { } if (selectedTags.size === 0) { - searchEmojis = customEmojis.filter(emoji => emoji.name.includes(q) || emoji.aliases.includes(q)); + searchEmojis = customEmojis.value.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))); + searchEmojis = customEmojis.value.filter(emoji => (emoji.name.includes(q) || emoji.aliases.includes(q)) && [...selectedTags].every(t => emoji.aliases.includes(t))); } } diff --git a/packages/frontend/src/pages/custom-emojis-manager.vue b/packages/frontend/src/pages/custom-emojis-manager.vue index 87d205ed7..e113c38a1 100644 --- a/packages/frontend/src/pages/custom-emojis-manager.vue +++ b/packages/frontend/src/pages/custom-emojis-manager.vue @@ -79,6 +79,7 @@ import { selectFile, selectFiles } from '@/scripts/select-file'; import * as os from '@/os'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; +import { fetchCustomEmojis } from '@/custom-emojis'; const emojisPaginationComponent = shallowRef>(); @@ -130,6 +131,7 @@ const add = async (ev: MouseEvent) => { }))); promise.then(() => { emojisPaginationComponent.value.reload(); + fetchCustomEmojis(); }); os.promiseDialog(promise); }; @@ -147,6 +149,7 @@ const edit = (emoji) => { } else if (result.deleted) { emojisPaginationComponent.value.removeItem((item) => item.id === emoji.id); } + fetchCustomEmojis(); }, }, 'closed'); }; @@ -220,6 +223,7 @@ const setCategoryBulk = async () => { category: result, }); emojisPaginationComponent.value.reload(); + fetchCustomEmojis(); }; const addTagBulk = async () => { @@ -232,6 +236,7 @@ const addTagBulk = async () => { aliases: result.split(' '), }); emojisPaginationComponent.value.reload(); + fetchCustomEmojis(); }; const removeTagBulk = async () => { @@ -244,6 +249,7 @@ const removeTagBulk = async () => { aliases: result.split(' '), }); emojisPaginationComponent.value.reload(); + fetchCustomEmojis(); }; const setTagBulk = async () => { @@ -256,6 +262,7 @@ const setTagBulk = async () => { aliases: result.split(' '), }); emojisPaginationComponent.value.reload(); + fetchCustomEmojis(); }; const delBulk = async () => { @@ -268,6 +275,7 @@ const delBulk = async () => { ids: selectedEmojis.value, }); emojisPaginationComponent.value.reload(); + fetchCustomEmojis(); }; const headerActions = $computed(() => [{ diff --git a/packages/frontend/src/pages/mfm-cheat-sheet.vue b/packages/frontend/src/pages/mfm-cheat-sheet.vue index b3932ff7c..73a571623 100644 --- a/packages/frontend/src/pages/mfm-cheat-sheet.vue +++ b/packages/frontend/src/pages/mfm-cheat-sheet.vue @@ -313,7 +313,7 @@ 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(customEmojis.length ? `:${customEmojis[0].name}:` : ':emojiname:'); +let preview_emoji = $ref(customEmojis.value.length ? `:${customEmojis.value[0].name}:` : ':emojiname:'); let preview_bold = $ref(`**${i18n.ts._mfm.dummy}**`); let preview_small = $ref(`${i18n.ts._mfm.dummy}`); let preview_center = $ref(`
${i18n.ts._mfm.dummy}
`); diff --git a/packages/frontend/src/scripts/aiscript/api.ts b/packages/frontend/src/scripts/aiscript/api.ts index 29736ac60..12f00bd32 100644 --- a/packages/frontend/src/scripts/aiscript/api.ts +++ b/packages/frontend/src/scripts/aiscript/api.ts @@ -10,7 +10,7 @@ export function createAiScriptEnv(opts) { USER_ID: $i ? values.STR($i.id) : values.NULL, USER_NAME: $i ? values.STR($i.name) : values.NULL, USER_USERNAME: $i ? values.STR($i.username) : values.NULL, - CUSTOM_EMOJIS: utils.jsToVal(customEmojis), + CUSTOM_EMOJIS: utils.jsToVal(customEmojis.value), 'Mk:dialog': values.FN_NATIVE(async ([title, text, type]) => { await os.alert({ type: type ? type.value : 'info', From 4cd70df7f465be53dd4fa48e2ab5724b36f4d167 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 16 Jan 2023 09:52:45 +0000 Subject: [PATCH 02/25] setInterval --- packages/frontend/src/components/MkAutocomplete.vue | 6 +++--- packages/frontend/src/custom-emojis.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue index ab4bf4f79..f85c92cec 100644 --- a/packages/frontend/src/components/MkAutocomplete.vue +++ b/packages/frontend/src/components/MkAutocomplete.vue @@ -237,20 +237,20 @@ function exec() { const matched: EmojiDef[] = []; const max = 30; - emojiDb.some(x => { + emojiDb.value.some(x => { if (x.name.startsWith(props.q ?? '') && !x.aliasOf && !matched.some(y => y.emoji === x.emoji)) matched.push(x); return matched.length === max; }); if (matched.length < max) { - emojiDb.some(x => { + emojiDb.value.some(x => { if (x.name.startsWith(props.q ?? '') && !matched.some(y => y.emoji === x.emoji)) matched.push(x); return matched.length === max; }); } if (matched.length < max) { - emojiDb.some(x => { + emojiDb.value.some(x => { if (x.name.includes(props.q ?? '') && !matched.some(y => y.emoji === x.emoji)) matched.push(x); return matched.length === max; }); diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts index 52a114823..6d20187ab 100644 --- a/packages/frontend/src/custom-emojis.ts +++ b/packages/frontend/src/custom-emojis.ts @@ -6,7 +6,7 @@ import * as Misskey from 'misskey-js'; const storageCache = miLocalStorage.getItem('emojis'); export const customEmojis = shallowRef(storageCache ? JSON.parse(storageCache) : []); -fetchCustomEmojis(); +window.setInterval(fetchCustomEmojis, 1000 * 60 * 10); export async function fetchCustomEmojis() { const now = Date.now(); From f2a9194c79524298a23f7fcba7abe8ef1f6077c7 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 16 Jan 2023 10:13:19 +0000 Subject: [PATCH 03/25] :v: --- packages/frontend/src/custom-emojis.ts | 1 + .../src/pages/custom-emojis-manager.vue | 21 +++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts index 6d20187ab..8fd5078bd 100644 --- a/packages/frontend/src/custom-emojis.ts +++ b/packages/frontend/src/custom-emojis.ts @@ -6,6 +6,7 @@ import * as Misskey from 'misskey-js'; const storageCache = miLocalStorage.getItem('emojis'); export const customEmojis = shallowRef(storageCache ? JSON.parse(storageCache) : []); +fetchCustomEmojis(); window.setInterval(fetchCustomEmojis, 1000 * 60 * 10); export async function fetchCustomEmojis() { diff --git a/packages/frontend/src/pages/custom-emojis-manager.vue b/packages/frontend/src/pages/custom-emojis-manager.vue index e113c38a1..00c736a6a 100644 --- a/packages/frontend/src/pages/custom-emojis-manager.vue +++ b/packages/frontend/src/pages/custom-emojis-manager.vue @@ -79,7 +79,7 @@ import { selectFile, selectFiles } from '@/scripts/select-file'; import * as os from '@/os'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; -import { fetchCustomEmojis } from '@/custom-emojis'; +import { fetchCustomEmojis, customEmojis } from '@/custom-emojis'; const emojisPaginationComponent = shallowRef>(); @@ -146,10 +146,27 @@ const edit = (emoji) => { ...oldEmoji, ...result.updated, })); + + if (customEmojis.value.some(e => e.name === emoji.name)) { + customEmojis.value = [ + { + name: result.updated.name, + aliases: result.updated.aliases, + category: result.updated.category, + }, + ...customEmojis.value, + ]; + } else { + customEmojis.value = customEmojis.value.map(e => e.name !== emoji.name ? e : { + name: result.updated.name, + aliases: result.updated.aliases, + category: result.updated.category, + }); + } } else if (result.deleted) { emojisPaginationComponent.value.removeItem((item) => item.id === emoji.id); + customEmojis.value = customEmojis.value.filter(e => e.name !== emoji.name); } - fetchCustomEmojis(); }, }, 'closed'); }; From 43956f3ffb616e6813f179b7a9040f158812fbac Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 16 Jan 2023 10:36:29 +0000 Subject: [PATCH 04/25] customEmojiCategories as computed --- .../frontend/src/components/MkEmojiPicker.vue | 3 +-- packages/frontend/src/custom-emojis.ts | 22 +++++++------------ packages/frontend/src/pages/about.emojis.vue | 3 +-- .../frontend/src/pages/emoji-edit-dialog.vue | 5 ++--- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index abb14564f..3399124e8 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -88,7 +88,7 @@ import { deviceKind } from '@/scripts/device-kind'; import { instance } from '@/instance'; import { i18n } from '@/i18n'; import { defaultStore } from '@/store'; -import { getCustomEmojiCategories, customEmojis } from '@/custom-emojis'; +import { customEmojiCategories, customEmojis } from '@/custom-emojis'; const props = withDefaults(defineProps<{ showPinned?: boolean; @@ -104,7 +104,6 @@ const emit = defineEmits<{ (ev: 'chosen', v: string): void; }>(); -const customEmojiCategories = getCustomEmojiCategories(); const searchEl = shallowRef(); const emojisEl = shallowRef(); diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts index 8fd5078bd..57842459b 100644 --- a/packages/frontend/src/custom-emojis.ts +++ b/packages/frontend/src/custom-emojis.ts @@ -1,10 +1,17 @@ import { apiGet } from './os'; import { miLocalStorage } from './local-storage'; -import { shallowRef } from 'vue'; +import { shallowRef, computed, markRaw } from 'vue'; import * as Misskey from 'misskey-js'; const storageCache = miLocalStorage.getItem('emojis'); export const customEmojis = shallowRef(storageCache ? JSON.parse(storageCache) : []); +export const customEmojiCategories = computed(() => { + const categories = new Set(); + for (const emoji of customEmojis.value) { + categories.add(emoji.category); + } + return markRaw(Array.from(categories)); +}); fetchCustomEmojis(); window.setInterval(fetchCustomEmojis, 1000 * 60 * 10); @@ -21,19 +28,6 @@ export async function fetchCustomEmojis() { miLocalStorage.setItem('lastEmojisFetchedAt', now.toString()); } -let cachedCategories; -export function getCustomEmojiCategories() { - if (cachedCategories) return cachedCategories; - - const categories = new Set(); - for (const emoji of customEmojis.value) { - categories.add(emoji.category); - } - const res = Array.from(categories); - cachedCategories = res; - return res; -} - let cachedTags; export function getCustomEmojiTags() { if (cachedTags) return cachedTags; diff --git a/packages/frontend/src/pages/about.emojis.vue b/packages/frontend/src/pages/about.emojis.vue index 7d146d1fd..d964e48b3 100644 --- a/packages/frontend/src/pages/about.emojis.vue +++ b/packages/frontend/src/pages/about.emojis.vue @@ -39,11 +39,10 @@ import MkSelect from '@/components/MkSelect.vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; import MkTab from '@/components/MkTab.vue'; import * as os from '@/os'; -import { customEmojis, getCustomEmojiCategories, getCustomEmojiTags } from '@/custom-emojis'; +import { customEmojis, customEmojiCategories, getCustomEmojiTags } from '@/custom-emojis'; import { i18n } from '@/i18n'; import * as Misskey from 'misskey-js'; -const customEmojiCategories = getCustomEmojiCategories(); const customEmojiTags = getCustomEmojiTags(); let q = $ref(''); let searchEmojis = $ref(null); diff --git a/packages/frontend/src/pages/emoji-edit-dialog.vue b/packages/frontend/src/pages/emoji-edit-dialog.vue index b2880b60b..4d84ed7f1 100644 --- a/packages/frontend/src/pages/emoji-edit-dialog.vue +++ b/packages/frontend/src/pages/emoji-edit-dialog.vue @@ -15,7 +15,7 @@ - + @@ -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 { getCustomEmojiCategories } from '@/custom-emojis'; +import { customEmojiCategories } from '@/custom-emojis'; const props = defineProps<{ emoji: any, @@ -46,7 +46,6 @@ 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(' ')); -const categories = getCustomEmojiCategories(); const emit = defineEmits<{ (ev: 'done', v: { deleted?: boolean, updated?: any }): void, From 002f98987d8b26b7a86c5bb6505cefa439701a94 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 16 Jan 2023 10:51:51 +0000 Subject: [PATCH 05/25] fix --- packages/frontend/src/pages/custom-emojis-manager.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/pages/custom-emojis-manager.vue b/packages/frontend/src/pages/custom-emojis-manager.vue index 00c736a6a..20b6c32e8 100644 --- a/packages/frontend/src/pages/custom-emojis-manager.vue +++ b/packages/frontend/src/pages/custom-emojis-manager.vue @@ -147,7 +147,7 @@ const edit = (emoji) => { ...result.updated, })); - if (customEmojis.value.some(e => e.name === emoji.name)) { + if (!customEmojis.value.some(e => e.name === emoji.name)) { customEmojis.value = [ { name: result.updated.name, From 890564e1daeec3b4b08e933945640ecead48a12e Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 16 Jan 2023 10:56:43 +0000 Subject: [PATCH 06/25] refactor --- packages/frontend/src/components/MkAutocomplete.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue index f85c92cec..2cb3aeb3d 100644 --- a/packages/frontend/src/components/MkAutocomplete.vue +++ b/packages/frontend/src/components/MkAutocomplete.vue @@ -62,6 +62,7 @@ type EmojiDef = { const lib = emojilist.filter(x => x.category !== 'flags'); const emojiDb = computed(() => { + //#region Unicode Emoji const char2path = defaultStore.reactiveState.emojiStyle.value === 'twemoji' ? char2twemojiFilePath : char2fluentEmojiFilePath; const unicodeEmojiDB: EmojiDef[] = lib.map(x => ({ @@ -84,8 +85,9 @@ const emojiDb = computed(() => { } unicodeEmojiDB.sort((a, b) => a.name.length - b.name.length); + //#endregion - //#region Construct Emoji DB + //#region Custom Emoji const customEmojiDB: EmojiDef[] = []; for (const x of customEmojis.value) { @@ -108,6 +110,7 @@ const emojiDb = computed(() => { } customEmojiDB.sort((a, b) => a.name.length - b.name.length); + //#endregion return markRaw([ ...customEmojiDB, ...unicodeEmojiDB ]); }); From a5f54580a9a069d824ac0c52149682d34349ddfc Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 22 Jan 2023 12:57:51 +0000 Subject: [PATCH 07/25] fix --- packages/frontend/src/components/global/MkEmoji.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/global/MkEmoji.vue b/packages/frontend/src/components/global/MkEmoji.vue index 93f50da20..691392d73 100644 --- a/packages/frontend/src/components/global/MkEmoji.vue +++ b/packages/frontend/src/components/global/MkEmoji.vue @@ -32,7 +32,7 @@ const url = computed(() => { if (char.value) { return char2path(char.value); } else if (props.host == null && !customEmojiName.includes('@')) { - const found = customEmojis.find(x => x.name === customEmojiName); + const found = customEmojis.value.find(x => x.name === customEmojiName); return found ? found.url : null; } else { const rawUrl = props.host ? `/emoji/${customEmojiName}@${props.host}.webp` : `/emoji/${customEmojiName}.webp`; From 2f6c45e11842cde64c2b724a45b2c316b09af57c Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 22 Jan 2023 14:53:24 +0000 Subject: [PATCH 08/25] wip --- .../backend/src/core/CustomEmojiService.ts | 8 ++++ .../endpoints/admin/emoji/add-aliases-bulk.ts | 9 +++++ .../server/api/endpoints/admin/emoji/add.ts | 39 +++++-------------- .../api/endpoints/admin/emoji/delete-bulk.ts | 10 ++++- .../api/endpoints/admin/emoji/delete.ts | 8 ++++ .../admin/emoji/remove-aliases-bulk.ts | 9 +++++ .../endpoints/admin/emoji/set-aliases-bulk.ts | 9 +++++ .../admin/emoji/set-category-bulk.ts | 9 +++++ .../api/endpoints/admin/emoji/update.ts | 21 ++++++++++ .../backend/src/server/api/stream/types.ts | 10 +++++ packages/frontend/src/custom-emojis.ts | 14 ++++++- packages/frontend/src/init.ts | 5 --- 12 files changed, 114 insertions(+), 37 deletions(-) diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts index 18b4067f6..1f0b21415 100644 --- a/packages/backend/src/core/CustomEmojiService.ts +++ b/packages/backend/src/core/CustomEmojiService.ts @@ -2,6 +2,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { DataSource, In, IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; import { IdService } from '@/core/IdService.js'; +import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; import type { DriveFile } from '@/models/entities/DriveFile.js'; import type { Emoji } from '@/models/entities/Emoji.js'; import type { EmojisRepository } from '@/models/index.js'; @@ -17,6 +19,8 @@ export class CustomEmojiService { private emojisRepository: EmojisRepository, private idService: IdService, + private emojiEntityService: EmojiEntityService, + private globalEventService: GlobalEventService, ) { } @@ -42,6 +46,10 @@ export class CustomEmojiService { await this.db.queryResultCache!.remove(['meta_emojis']); + this.globalEventService.publishBroadcastStream('emojiAdded', { + emoji: await this.emojiEntityService.pack(emoji.id), + }); + return emoji; } } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts index 9b6c774f0..c683cd24c 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts @@ -3,6 +3,8 @@ import { DataSource, In } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { EmojisRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; +import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; export const meta = { tags: ['admin'], @@ -35,6 +37,9 @@ export default class extends Endpoint { @Inject(DI.emojisRepository) private emojisRepository: EmojisRepository, + + private emojiEntityService: EmojiEntityService, + private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { const emojis = await this.emojisRepository.findBy({ @@ -49,6 +54,10 @@ export default class extends Endpoint { } await this.db.queryResultCache!.remove(['meta_emojis']); + + this.globalEventService.publishBroadcastStream('emojiUpdated', { + emojis: await this.emojiEntityService.packMany(ps.ids), + }); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts index abca1d169..1bb05c15c 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts @@ -2,12 +2,10 @@ import { Inject, Injectable } from '@nestjs/common'; import rndstr from 'rndstr'; import { DataSource } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository, EmojisRepository } from '@/models/index.js'; -import { IdService } from '@/core/IdService.js'; +import type { DriveFilesRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { CustomEmojiService } from '@/core/CustomEmojiService.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; -import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; import { ApiError } from '../../../error.js'; export const meta = { @@ -39,43 +37,26 @@ export const paramDef = { @Injectable() export default class extends Endpoint { constructor( - @Inject(DI.db) - private db: DataSource, - @Inject(DI.driveFilesRepository) private driveFilesRepository: DriveFilesRepository, - @Inject(DI.emojisRepository) - private emojisRepository: EmojisRepository, + private customEmojiService: CustomEmojiService, - private emojiEntityService: EmojiEntityService, - private idService: IdService, - private globalEventService: GlobalEventService, private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { - const file = await this.driveFilesRepository.findOneBy({ id: ps.fileId }); + const driveFile = await this.driveFilesRepository.findOneBy({ id: ps.fileId }); - if (file == null) throw new ApiError(meta.errors.noSuchFile); + if (driveFile == null) throw new ApiError(meta.errors.noSuchFile); - const name = file.name.split('.')[0].match(/^[a-z0-9_]+$/) ? file.name.split('.')[0] : `_${rndstr('a-z0-9', 8)}_`; + const name = driveFile.name.split('.')[0].match(/^[a-z0-9_]+$/) ? driveFile.name.split('.')[0] : `_${rndstr('a-z0-9', 8)}_`; - const emoji = await this.emojisRepository.insert({ - id: this.idService.genId(), - updatedAt: new Date(), - name: name, + const emoji = await this.customEmojiService.add({ + driveFile, + name, category: null, - host: null, aliases: [], - originalUrl: file.url, - publicUrl: file.webpublicUrl ?? file.url, - type: file.webpublicType ?? file.type, - }).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0])); - - await this.db.queryResultCache!.remove(['meta_emojis']); - - this.globalEventService.publishBroadcastStream('emojiAdded', { - emoji: await this.emojiEntityService.pack(emoji.id), + host: null, }); this.moderationLogService.insertModerationLog(me, 'addEmoji', { diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts index ae45105b2..0c337237d 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts @@ -4,6 +4,8 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; import type { EmojisRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; export const meta = { tags: ['admin'], @@ -35,6 +37,8 @@ export default class extends Endpoint { private emojisRepository: EmojisRepository, private moderationLogService: ModerationLogService, + private emojiEntityService: EmojiEntityService, + private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { const emojis = await this.emojisRepository.findBy({ @@ -43,13 +47,15 @@ export default class extends Endpoint { for (const emoji of emojis) { await this.emojisRepository.delete(emoji.id); - await this.db.queryResultCache!.remove(['meta_emojis']); - this.moderationLogService.insertModerationLog(me, 'deleteEmoji', { emoji: emoji, }); } + + this.globalEventService.publishBroadcastStream('emojiDeleted', { + emojis: await this.emojiEntityService.packMany(emojis), + }); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts index e237d87d3..c1a60a277 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts @@ -5,6 +5,8 @@ import type { EmojisRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; import { ApiError } from '../../../error.js'; +import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; export const meta = { tags: ['admin'], @@ -42,6 +44,8 @@ export default class extends Endpoint { private emojisRepository: EmojisRepository, private moderationLogService: ModerationLogService, + private emojiEntityService: EmojiEntityService, + private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { const emoji = await this.emojisRepository.findOneBy({ id: ps.id }); @@ -52,6 +56,10 @@ export default class extends Endpoint { await this.db.queryResultCache!.remove(['meta_emojis']); + this.globalEventService.publishBroadcastStream('emojiDeleted', { + emojis: [ await this.emojiEntityService.pack(emoji) ], + }); + this.moderationLogService.insertModerationLog(me, 'deleteEmoji', { emoji: emoji, }); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts index 5fc9e024b..065965f64 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts @@ -3,6 +3,8 @@ import { DataSource, In } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { EmojisRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; +import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; export const meta = { tags: ['admin'], @@ -35,6 +37,9 @@ export default class extends Endpoint { @Inject(DI.emojisRepository) private emojisRepository: EmojisRepository, + + private emojiEntityService: EmojiEntityService, + private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { const emojis = await this.emojisRepository.findBy({ @@ -49,6 +54,10 @@ export default class extends Endpoint { } await this.db.queryResultCache!.remove(['meta_emojis']); + + this.globalEventService.publishBroadcastStream('emojiUpdated', { + emojis: await this.emojiEntityService.packMany(ps.ids), + }); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts index 8b5ba8fbf..51c0f329a 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts @@ -3,6 +3,8 @@ import { DataSource, In } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { EmojisRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; +import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; export const meta = { tags: ['admin'], @@ -35,6 +37,9 @@ export default class extends Endpoint { @Inject(DI.emojisRepository) private emojisRepository: EmojisRepository, + + private emojiEntityService: EmojiEntityService, + private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { await this.emojisRepository.update({ @@ -45,6 +50,10 @@ export default class extends Endpoint { }); await this.db.queryResultCache!.remove(['meta_emojis']); + + this.globalEventService.publishBroadcastStream('emojiUpdated', { + emojis: await this.emojiEntityService.packMany(ps.ids), + }); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts index 827b5ace7..3329cab7b 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts @@ -3,6 +3,8 @@ import { DataSource, In } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { EmojisRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; +import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; export const meta = { tags: ['admin'], @@ -37,6 +39,9 @@ export default class extends Endpoint { @Inject(DI.emojisRepository) private emojisRepository: EmojisRepository, + + private emojiEntityService: EmojiEntityService, + private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { await this.emojisRepository.update({ @@ -47,6 +52,10 @@ export default class extends Endpoint { }); await this.db.queryResultCache!.remove(['meta_emojis']); + + this.globalEventService.publishBroadcastStream('emojiUpdated', { + emojis: await this.emojiEntityService.packMany(ps.ids), + }); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts index fb0ef1287..6c4c8d0e6 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -4,6 +4,8 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; import type { EmojisRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; +import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; export const meta = { tags: ['admin'], @@ -48,6 +50,9 @@ export default class extends Endpoint { @Inject(DI.emojisRepository) private emojisRepository: EmojisRepository, + + private emojiEntityService: EmojiEntityService, + private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { const emoji = await this.emojisRepository.findOneBy({ id: ps.id }); @@ -62,6 +67,22 @@ export default class extends Endpoint { }); await this.db.queryResultCache!.remove(['meta_emojis']); + + const updated = await this.emojiEntityService.pack(emoji.id); + + if (emoji.name === ps.name) { + this.globalEventService.publishBroadcastStream('emojiUpdated', { + emojis: [ updated ], + }); + } else { + this.globalEventService.publishBroadcastStream('emojiDeleted', { + emojis: [ emoji ], + }); + + this.globalEventService.publishBroadcastStream('emojiAdded', { + emoji: updated, + }); + } }); } } diff --git a/packages/backend/src/server/api/stream/types.ts b/packages/backend/src/server/api/stream/types.ts index a442529bb..9daaa4acf 100644 --- a/packages/backend/src/server/api/stream/types.ts +++ b/packages/backend/src/server/api/stream/types.ts @@ -49,6 +49,16 @@ export interface BroadcastTypes { emojiAdded: { emoji: Packed<'Emoji'>; }; + emojiUpdated: { + emojis: Packed<'Emoji'>[]; + }; + emojiDeleted: { + emojis: { + id?: string; + name: string; + [other: string]: any; + }[]; + }; } export interface UserStreamTypes { diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts index 57842459b..5b13176cd 100644 --- a/packages/frontend/src/custom-emojis.ts +++ b/packages/frontend/src/custom-emojis.ts @@ -2,6 +2,7 @@ import { apiGet } from './os'; import { miLocalStorage } from './local-storage'; import { shallowRef, computed, markRaw } from 'vue'; import * as Misskey from 'misskey-js'; +import { stream } from '@/stream'; const storageCache = miLocalStorage.getItem('emojis'); export const customEmojis = shallowRef(storageCache ? JSON.parse(storageCache) : []); @@ -14,7 +15,18 @@ export const customEmojiCategories = computed(() => { }); fetchCustomEmojis(); -window.setInterval(fetchCustomEmojis, 1000 * 60 * 10); + +stream.on('emojiAdded', emojiData => { + customEmojis.value = [ emojiData.emoji, ...customEmojis.value ] +}); + +stream.on('emojiUpdated', emojiData => { + customEmojis.value = customEmojis.value.map(item => emojiData.emojis.find(search => search.name === item.name) as Misskey.entities.CustomEmoji ?? item); +}); + +stream.on('emojiDeleted', emojiData => { + customEmojis.value = customEmojis.value.filter(item => !emojiData.emojis.some(search => search.name === item.name)) +}); export async function fetchCustomEmojis() { const now = Date.now(); diff --git a/packages/frontend/src/init.ts b/packages/frontend/src/init.ts index 36897545e..2432b5f6f 100644 --- a/packages/frontend/src/init.ts +++ b/packages/frontend/src/init.ts @@ -338,11 +338,6 @@ import { fetchCustomEmojis } from './custom-emojis'; } }); - stream.on('emojiAdded', emojiData => { - // TODO - //store.commit('instance/set', ); - }); - for (const plugin of ColdDeviceStorage.get('plugins').filter(p => p.active)) { import('./plugin').then(({ install }) => { install(plugin); From 0b2f945bb61fc5c3a33ab93d0134f4bfe3a05c9d Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 22 Jan 2023 15:13:03 +0000 Subject: [PATCH 09/25] wip --- .../backend/src/server/api/endpoints/admin/emoji/update.ts | 2 +- packages/frontend/src/custom-emojis.ts | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts index 6c4c8d0e6..22bedc710 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -76,7 +76,7 @@ export default class extends Endpoint { }); } else { this.globalEventService.publishBroadcastStream('emojiDeleted', { - emojis: [ emoji ], + emojis: [ await this.emojiEntityService.pack(emoji) ], }); this.globalEventService.publishBroadcastStream('emojiAdded', { diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts index 5b13176cd..b080eca40 100644 --- a/packages/frontend/src/custom-emojis.ts +++ b/packages/frontend/src/custom-emojis.ts @@ -17,7 +17,9 @@ export const customEmojiCategories = computed(() => { fetchCustomEmojis(); stream.on('emojiAdded', emojiData => { - customEmojis.value = [ emojiData.emoji, ...customEmojis.value ] + setTimeout(() => { + customEmojis.value = [ emojiData.emoji, ...customEmojis.value ] + }, 100); }); stream.on('emojiUpdated', emojiData => { @@ -25,7 +27,7 @@ stream.on('emojiUpdated', emojiData => { }); stream.on('emojiDeleted', emojiData => { - customEmojis.value = customEmojis.value.filter(item => !emojiData.emojis.some(search => search.name === item.name)) + customEmojis.value = customEmojis.value.filter(item => !emojiData.emojis.some(search => search.name === item.name)); }); export async function fetchCustomEmojis() { From 226e0c4714c2d02598141e3e408c4fb29d90354b Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 22 Jan 2023 15:17:20 +0000 Subject: [PATCH 10/25] :v: --- .../src/pages/custom-emojis-manager.vue | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/packages/frontend/src/pages/custom-emojis-manager.vue b/packages/frontend/src/pages/custom-emojis-manager.vue index 20b6c32e8..87d205ed7 100644 --- a/packages/frontend/src/pages/custom-emojis-manager.vue +++ b/packages/frontend/src/pages/custom-emojis-manager.vue @@ -79,7 +79,6 @@ import { selectFile, selectFiles } from '@/scripts/select-file'; import * as os from '@/os'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; -import { fetchCustomEmojis, customEmojis } from '@/custom-emojis'; const emojisPaginationComponent = shallowRef>(); @@ -131,7 +130,6 @@ const add = async (ev: MouseEvent) => { }))); promise.then(() => { emojisPaginationComponent.value.reload(); - fetchCustomEmojis(); }); os.promiseDialog(promise); }; @@ -146,26 +144,8 @@ const edit = (emoji) => { ...oldEmoji, ...result.updated, })); - - if (!customEmojis.value.some(e => e.name === emoji.name)) { - customEmojis.value = [ - { - name: result.updated.name, - aliases: result.updated.aliases, - category: result.updated.category, - }, - ...customEmojis.value, - ]; - } else { - customEmojis.value = customEmojis.value.map(e => e.name !== emoji.name ? e : { - name: result.updated.name, - aliases: result.updated.aliases, - category: result.updated.category, - }); - } } else if (result.deleted) { emojisPaginationComponent.value.removeItem((item) => item.id === emoji.id); - customEmojis.value = customEmojis.value.filter(e => e.name !== emoji.name); } }, }, 'closed'); @@ -240,7 +220,6 @@ const setCategoryBulk = async () => { category: result, }); emojisPaginationComponent.value.reload(); - fetchCustomEmojis(); }; const addTagBulk = async () => { @@ -253,7 +232,6 @@ const addTagBulk = async () => { aliases: result.split(' '), }); emojisPaginationComponent.value.reload(); - fetchCustomEmojis(); }; const removeTagBulk = async () => { @@ -266,7 +244,6 @@ const removeTagBulk = async () => { aliases: result.split(' '), }); emojisPaginationComponent.value.reload(); - fetchCustomEmojis(); }; const setTagBulk = async () => { @@ -279,7 +256,6 @@ const setTagBulk = async () => { aliases: result.split(' '), }); emojisPaginationComponent.value.reload(); - fetchCustomEmojis(); }; const delBulk = async () => { @@ -292,7 +268,6 @@ const delBulk = async () => { ids: selectedEmojis.value, }); emojisPaginationComponent.value.reload(); - fetchCustomEmojis(); }; const headerActions = $computed(() => [{ From d347f0a087747d4ae19255372ced2d69f62fc00d Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 22 Jan 2023 16:07:17 +0000 Subject: [PATCH 11/25] wip --- .../src/core/entities/EmojiEntityService.ts | 4 +++- .../api/endpoints/admin/emoji/list-remote.ts | 2 +- .../src/server/api/endpoints/admin/emoji/list.ts | 2 +- .../frontend/src/components/global/MkEmoji.vue | 15 ++++++++------- packages/frontend/src/custom-emojis.ts | 10 +++++----- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/backend/src/core/entities/EmojiEntityService.ts b/packages/backend/src/core/entities/EmojiEntityService.ts index 611552d89..7d248e634 100644 --- a/packages/backend/src/core/entities/EmojiEntityService.ts +++ b/packages/backend/src/core/entities/EmojiEntityService.ts @@ -22,8 +22,10 @@ export class EmojiEntityService { @bindThis public async pack( src: Emoji['id'] | Emoji, - opts: { omitHost?: boolean; omitId?: boolean; withUrl?: boolean; } = {}, + opts: { omitHost?: boolean; omitId?: boolean; withUrl?: boolean; } = { omitHost: true, omitId: true, withUrl: true }, ): Promise> { + opts = { omitHost: true, omitId: true, withUrl: true, ...opts } + const emoji = typeof src === 'object' ? src : await this.emojisRepository.findOneByOrFail({ id: src }); return { diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts index d9ce97194..8e0ea2e11 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts @@ -101,7 +101,7 @@ export default class extends Endpoint { .take(ps.limit) .getMany(); - return this.emojiEntityService.packMany(emojis); + return this.emojiEntityService.packMany(emojis, { omitHost: false, omitId: false, withUrl: false }); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts index 1a6096f36..1b1931f8e 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts @@ -98,7 +98,7 @@ export default class extends Endpoint { emojis = await q.take(ps.limit).getMany(); } - return this.emojiEntityService.packMany(emojis); + return this.emojiEntityService.packMany(emojis, { omitHost: false, omitId: false, withUrl: false }); }); } } diff --git a/packages/frontend/src/components/global/MkEmoji.vue b/packages/frontend/src/components/global/MkEmoji.vue index 691392d73..5eba8764b 100644 --- a/packages/frontend/src/components/global/MkEmoji.vue +++ b/packages/frontend/src/components/global/MkEmoji.vue @@ -1,6 +1,6 @@ diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 3399124e8..b288cb22f 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -60,7 +60,7 @@
{{ i18n.ts.customEmojis }}
- {{ category || i18n.ts.other }} + {{ category || i18n.ts.other }}
{{ i18n.ts.emoji }}
From 0cffe60abc9a9e14f5815af472c100e630166c29 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 22 Jan 2023 17:14:05 +0000 Subject: [PATCH 13/25] =?UTF-8?q?1=E6=99=82=E9=96=93=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/server/api/endpoints/emojis.ts | 4 ++-- packages/frontend/src/custom-emojis.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/emojis.ts b/packages/backend/src/server/api/endpoints/emojis.ts index 9dfb12b76..77854afb3 100644 --- a/packages/backend/src/server/api/endpoints/emojis.ts +++ b/packages/backend/src/server/api/endpoints/emojis.ts @@ -11,7 +11,7 @@ export const meta = { requireCredential: false, allowGet: true, - cacheSec: 60, + cacheSec: 3600, res: { type: 'object', @@ -77,7 +77,7 @@ export default class extends Endpoint { }, cache: { id: 'meta_emojis', - milliseconds: 60000, // 1 minute + milliseconds: 3600000, // 1 hour }, }); diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts index 33f006b2a..89b8887b2 100644 --- a/packages/frontend/src/custom-emojis.ts +++ b/packages/frontend/src/custom-emojis.ts @@ -33,7 +33,7 @@ stream.on('emojiDeleted', emojiData => { export async function fetchCustomEmojis() { const now = Date.now(); const lastFetchedAt = miLocalStorage.getItem('lastEmojisFetchedAt'); - if (lastFetchedAt && (now - parseInt(lastFetchedAt)) < 1000 * 60) return; + if (lastFetchedAt && (now - parseInt(lastFetchedAt)) < 1000 * 60 * 60) return; const res = await apiGet('emojis', {}); From 0d44129ae34526503d391cbade18f26e9bba9c77 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 22 Jan 2023 17:20:53 +0000 Subject: [PATCH 14/25] remove console.log --- packages/frontend/src/components/global/MkEmoji.vue | 1 - packages/frontend/src/custom-emojis.ts | 4 ---- 2 files changed, 5 deletions(-) diff --git a/packages/frontend/src/components/global/MkEmoji.vue b/packages/frontend/src/components/global/MkEmoji.vue index 5eba8764b..c489ab5fa 100644 --- a/packages/frontend/src/components/global/MkEmoji.vue +++ b/packages/frontend/src/components/global/MkEmoji.vue @@ -33,7 +33,6 @@ const url = computed(() => { return char2path(char.value); } else if (props.host == null && !customEmojiName.value.includes('@')) { const found = customEmojis.value.find(x => x.name === customEmojiName.value); - console.log(found) return found ? found.url : null; } else { const rawUrl = props.host ? `/emoji/${customEmojiName.value}@${props.host}.webp` : `/emoji/${customEmojiName.value}.webp`; diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts index 89b8887b2..2cd088993 100644 --- a/packages/frontend/src/custom-emojis.ts +++ b/packages/frontend/src/custom-emojis.ts @@ -14,10 +14,6 @@ export const customEmojiCategories = computed(() => { return markRaw(Array.from(categories)); }); -watch(customEmojis, (newVal) => { - console.log('new', newVal) -}); - stream.on('emojiAdded', emojiData => { customEmojis.value = [ emojiData.emoji, ...customEmojis.value ]; }); From 93dd0638ade0ba896365f5f9cc1acba103db386e Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 22 Jan 2023 17:33:20 +0000 Subject: [PATCH 15/25] better category null handling --- packages/frontend/src/components/MkEmojiPicker.vue | 10 +++++++++- packages/frontend/src/custom-emojis.ts | 10 ++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index b288cb22f..479d8eb7f 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -60,7 +60,15 @@
{{ i18n.ts.customEmojis }}
- {{ category || i18n.ts.other }} + + {{ category || i18n.ts.other }} +
{{ i18n.ts.emoji }}
diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts index 2cd088993..4dd2e0909 100644 --- a/packages/frontend/src/custom-emojis.ts +++ b/packages/frontend/src/custom-emojis.ts @@ -1,17 +1,19 @@ import { apiGet } from './os'; import { miLocalStorage } from './local-storage'; -import { shallowRef, computed, markRaw, watch } from 'vue'; +import { shallowRef, computed, markRaw } from 'vue'; import * as Misskey from 'misskey-js'; import { stream } from '@/stream'; const storageCache = miLocalStorage.getItem('emojis'); export const customEmojis = shallowRef(storageCache ? JSON.parse(storageCache) : []); -export const customEmojiCategories = computed(() => { +export const customEmojiCategories = computed<[ ...string[], null ]>(() => { const categories = new Set(); for (const emoji of customEmojis.value) { - categories.add(emoji.category); + if (emoji.category && emoji.category !== 'null') { + categories.add(emoji.category); + } } - return markRaw(Array.from(categories)); + return markRaw([ ...Array.from(categories), null ]); }); stream.on('emojiAdded', emojiData => { From 26fbb3a5603096615ec304c1ca4b3da22ad6b456 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 22 Jan 2023 17:39:11 +0000 Subject: [PATCH 16/25] fix --- packages/frontend/src/components/MkEmojiPicker.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 479d8eb7f..f64cc6e9a 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -64,7 +64,7 @@ v-for="category in customEmojiCategories" :key="`custom:${category}`" :initial-shown="false" - :emojis="computed(() => customEmojis.filter(e => category === null ? e.category == null || e.category === 'null' : e.category === category).map(e => `:${e.name}:`))" + :emojis="computed(() => customEmojis.filter(e => category === null ? (e.category === 'null' || !e.category) : e.category === category).map(e => `:${e.name}:`))" @chosen="chosen" > {{ category || i18n.ts.other }} From 5f49ac1b11ab7927ab17df2bd8a30eaf803e94f4 Mon Sep 17 00:00:00 2001 From: tamaina Date: Wed, 25 Jan 2023 06:21:08 +0000 Subject: [PATCH 17/25] =?UTF-8?q?fix(client):=20=E3=82=A2=E3=83=8B?= =?UTF-8?q?=E3=83=A1=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92=E3=82=AA?= =?UTF-8?q?=E3=83=95=E3=81=AB=E8=A8=AD=E5=AE=9A=E3=81=97=E3=81=A6=E3=82=82?= =?UTF-8?q?=E7=B5=B5=E6=96=87=E5=AD=97=E3=81=AE=E3=82=A2=E3=83=8B=E3=83=A1?= =?UTF-8?q?=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=81=8C=E6=AD=A2=E3=81=BE?= =?UTF-8?q?=E3=82=89=E3=81=AA=E3=81=84=20Fix=20#9720?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/global/MkEmoji.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/global/MkEmoji.vue b/packages/frontend/src/components/global/MkEmoji.vue index 93f50da20..991c6fb7c 100644 --- a/packages/frontend/src/components/global/MkEmoji.vue +++ b/packages/frontend/src/components/global/MkEmoji.vue @@ -33,7 +33,7 @@ const url = computed(() => { return char2path(char.value); } else if (props.host == null && !customEmojiName.includes('@')) { const found = customEmojis.find(x => x.name === customEmojiName); - return found ? found.url : null; + return found ? defaultStore.state.disableShowingAnimatedImages ? getStaticImageUrl(found.url) : found.url : null; } else { const rawUrl = props.host ? `/emoji/${customEmojiName}@${props.host}.webp` : `/emoji/${customEmojiName}.webp`; return defaultStore.state.disableShowingAnimatedImages From 5ffa106cc1ada8c0680a57cef027114232258870 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 25 Jan 2023 19:34:10 +0900 Subject: [PATCH 18/25] =?UTF-8?q?=E3=82=B5=E3=83=BC=E3=83=89=E3=83=91?= =?UTF-8?q?=E3=83=BC=E3=83=86=E3=82=A3=E3=81=8B=E3=82=89=E3=82=82=E8=87=AA?= =?UTF-8?q?=E8=BA=AB=E3=81=AE=E3=83=AD=E3=83=BC=E3=83=AB=E3=82=92=E7=A2=BA?= =?UTF-8?q?=E8=AA=8D=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close #9700 --- packages/backend/src/core/entities/UserEntityService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 34b523e14..f532b5bf6 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -496,10 +496,10 @@ export class UserEntityService implements OnModuleInit { showTimelineReplies: user.showTimelineReplies ?? falsy, achievements: profile!.achievements, loggedInDays: profile!.loggedInDates.length, + policies: this.roleService.getUserPolicies(user.id), } : {}), ...(opts.includeSecrets ? { - policies: this.roleService.getUserPolicies(user.id), email: profile!.email, emailVerified: profile!.emailVerified, securityKeysList: profile!.twoFactorEnabled From 1e3447bccbbabf09bafabf6df79d9ce3da04a506 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 25 Jan 2023 19:45:25 +0900 Subject: [PATCH 19/25] :art: --- packages/frontend/src/components/MkSuperMenu.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/components/MkSuperMenu.vue b/packages/frontend/src/components/MkSuperMenu.vue index bb2a789b3..5d33ad0ad 100644 --- a/packages/frontend/src/components/MkSuperMenu.vue +++ b/packages/frontend/src/components/MkSuperMenu.vue @@ -6,15 +6,15 @@
From 80d2e157f6a08d593367b2b933beb2a30b666b83 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 25 Jan 2023 19:49:17 +0900 Subject: [PATCH 20/25] :art: --- packages/frontend/src/components/MkMenu.vue | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue index 94dabcac9..eee77a947 100644 --- a/packages/frontend/src/components/MkMenu.vue +++ b/packages/frontend/src/components/MkMenu.vue @@ -335,8 +335,7 @@ onBeforeUnmount(() => { } .icon { - margin-right: 5px; - width: 20px; + margin-right: 8px; } .caret { From 7131eb1827311186698ebd5aa75d30c5ceafafe4 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 26 Jan 2023 11:31:43 +0900 Subject: [PATCH 21/25] fix(server): turnstile-failed: missing-input-secret Fix #9726 --- packages/backend/src/core/CaptchaService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/CaptchaService.ts b/packages/backend/src/core/CaptchaService.ts index c8428a26b..7aaa1b833 100644 --- a/packages/backend/src/core/CaptchaService.ts +++ b/packages/backend/src/core/CaptchaService.ts @@ -23,9 +23,9 @@ export class CaptchaService { const res = await this.httpRequestService.send(url, { method: 'POST', - body: JSON.stringify(params), + body: params.toString(), headers: { - 'Content-Type': 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', }, }, { throwErrorWhenResponseNotOk: false }); From ec8074cd494da59f35e20cb8bc4e896060343877 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 26 Jan 2023 11:32:43 +0900 Subject: [PATCH 22/25] New Crowdin updates (#9724) * New translations ja-JP.yml (Ukrainian) * New translations ja-JP.yml (Ukrainian) * New translations ja-JP.yml (Ukrainian) * New translations ja-JP.yml (Ukrainian) * New translations ja-JP.yml (Ukrainian) --- locales/uk-UA.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index a77bfa4f8..a85233996 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -956,9 +956,11 @@ _achievements: _login3: title: "Новачок I" description: "3 дні користування загально" + flavor: "Відсьогодні називайте мене \"Місскіст\"" _login7: title: "Новачок II" description: "7 днів користування загально" + flavor: "Ви звикли до цього?" _login15: title: "Новачок III" description: "15 днів користування загально" @@ -971,6 +973,7 @@ _achievements: _login100: title: "Міскієць III" description: "100 днів користування загально" + flavor: "Цей юзер лютий місскіст" _login200: title: "Завсідник I" description: "200 днів користування загально" @@ -983,6 +986,7 @@ _achievements: _login500: title: "Ветеран I" description: "500 днів користування загально" + flavor: "Meine Kameraden, ich liebe sie, die Notizen." _login600: title: "Ветеран II" description: "600 днів користування загально" @@ -990,13 +994,25 @@ _achievements: title: "Ветеран III" description: "700 днів користування загально" _login800: + title: "Майстер нотаток I" description: "800 днів користування загально" _login900: + title: "Майстер нотаток II" description: "900 днів користування загально" _login1000: + title: "Майстер нотаток III" description: "1000 днів користування загально" flavor: "Дякуємо, що користуєтеся Misskey!" + _myNoteFavorited1: + title: "У пошуках зірок" + _markedAsCat: + flavor: "Я дам тобі ім'я пізніше" + _following1: + title: "Перша підписка" + _following10: + title: "Продовжуй, продовжуй" _following50: + title: "Багато друзів" description: "Кількість підписок сягнула 50" _following100: title: "100 друзів" @@ -1013,6 +1029,7 @@ _achievements: _followers50: description: "Кількість підписників досягла 50" _followers100: + title: "Популярна особа" description: "Кількість підписників досягла 100" _followers300: description: "Кількість підписників досягла 300" @@ -1021,11 +1038,17 @@ _achievements: _followers1000: title: "Інфлюенсер" description: "Кількість підписників досягла 1000" + _passedSinceAccountCreated1: + title: "Перша річниця" + _passedSinceAccountCreated2: + title: "Друга річниця" _passedSinceAccountCreated3: + title: "Третя річниця" description: "Минуло 3 роки з моменту створення акаунта" _loggedInOnBirthday: title: "З Днем народження!" _brainDiver: + title: "Brain Diver" flavor: "Misskey-Misskey La-Tu-Ma" _role: priority: "Пріоритет" From 41a6ed0de01f5ddb711e874e6d9cf0f97ab8cb2a Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 26 Jan 2023 11:33:31 +0900 Subject: [PATCH 23/25] lint --- packages/frontend/src/custom-emojis.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts index 4dd2e0909..0ba7cab5e 100644 --- a/packages/frontend/src/custom-emojis.ts +++ b/packages/frontend/src/custom-emojis.ts @@ -1,7 +1,7 @@ -import { apiGet } from './os'; -import { miLocalStorage } from './local-storage'; import { shallowRef, computed, markRaw } from 'vue'; import * as Misskey from 'misskey-js'; +import { apiGet } from './os'; +import { miLocalStorage } from './local-storage'; import { stream } from '@/stream'; const storageCache = miLocalStorage.getItem('emojis'); @@ -13,11 +13,11 @@ export const customEmojiCategories = computed<[ ...string[], null ]>(() => { categories.add(emoji.category); } } - return markRaw([ ...Array.from(categories), null ]); + return markRaw([...Array.from(categories), null]); }); stream.on('emojiAdded', emojiData => { - customEmojis.value = [ emojiData.emoji, ...customEmojis.value ]; + customEmojis.value = [emojiData.emoji, ...customEmojis.value]; }); stream.on('emojiUpdated', emojiData => { From d87bb807c30597dd050607b5d37030cc9f27f922 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 26 Jan 2023 11:39:21 +0900 Subject: [PATCH 24/25] tweak error screen --- packages/backend/src/server/web/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index e635959fc..c6cb25e43 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -154,7 +154,7 @@

An error has occurred!

-

Don't worry, it's (probably) not your fault.

From aa8adc07aa225838a090bde499343514200bf55c Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 26 Jan 2023 11:40:36 +0900 Subject: [PATCH 25/25] 13.2.3 --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dd21ce6d..b0dbb6e24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ You should also include the user name that made the change. --> +## 13.2.3 (2023/01/26) +### Improvements +- カスタム絵文字の更新をリアルタイムで反映するように + +### Bugfixes +- turnstile-failed: missing-input-secret + ## 13.2.2 (2023/01/25) ### Improvements - サーバーのパフォーマンスを改善 diff --git a/package.json b/package.json index 800ca39ef..c5a556aea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "13.2.2", + "version": "13.2.3", "codename": "nasubi", "repository": { "type": "git",