summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components
diff options
context:
space:
mode:
authorsyuilo <4439005+syuilo@users.noreply.github.com>2024-03-02 17:06:46 +0900
committerGitHub <noreply@github.com>2024-03-02 17:06:46 +0900
commit78ff90f2cc3bdb3b4119f51617614d1a32afd960 (patch)
treea1ea2398514425edef242fad247effb81f65d229 /packages/frontend/src/components
parentMerge pull request #13447 from misskey-dev/develop (diff)
parent2024.3.1 (diff)
downloadsharkey-78ff90f2cc3bdb3b4119f51617614d1a32afd960.tar.gz
sharkey-78ff90f2cc3bdb3b4119f51617614d1a32afd960.tar.bz2
sharkey-78ff90f2cc3bdb3b4119f51617614d1a32afd960.zip
Merge pull request #13493 from misskey-dev/develop
Release: 2024.3.1
Diffstat (limited to 'packages/frontend/src/components')
-rw-r--r--packages/frontend/src/components/MkAutocomplete.vue4
-rw-r--r--packages/frontend/src/components/MkEmojiPicker.section.vue4
-rw-r--r--packages/frontend/src/components/MkEmojiPicker.vue15
-rw-r--r--packages/frontend/src/components/MkReactionIcon.vue2
-rw-r--r--packages/frontend/src/components/MkReactionsViewer.details.vue2
-rw-r--r--packages/frontend/src/components/global/MkCustomEmoji.stories.impl.ts15
-rw-r--r--packages/frontend/src/components/global/MkCustomEmoji.vue9
-rw-r--r--packages/frontend/src/components/global/MkEmoji.vue5
-rw-r--r--packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts1
9 files changed, 41 insertions, 16 deletions
diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue
index cae6bc7111..932c4ecb2e 100644
--- a/packages/frontend/src/components/MkAutocomplete.vue
+++ b/packages/frontend/src/components/MkAutocomplete.vue
@@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</ol>
<ol v-else-if="emojis.length > 0" ref="suggests" :class="$style.list">
<li v-for="emoji in emojis" :key="emoji.emoji" :class="$style.item" tabindex="-1" @click="complete(type, emoji.emoji)" @keydown="onKeydown">
- <MkCustomEmoji v-if="'isCustomEmoji' in emoji && emoji.isCustomEmoji" :name="emoji.emoji" :class="$style.emoji"/>
+ <MkCustomEmoji v-if="'isCustomEmoji' in emoji && emoji.isCustomEmoji" :name="emoji.emoji" :class="$style.emoji" :fallbackToImage="true"/>
<MkEmoji v-else :emoji="emoji.emoji" :class="$style.emoji"/>
<!-- eslint-disable-next-line vue/no-v-html -->
<span v-if="q" :class="$style.emojiName" v-html="sanitizeHtml(emoji.name.replace(q, `<b>${q}</b>`))"></span>
@@ -77,7 +77,7 @@ const emojiDb = computed(() => {
unicodeEmojiDB.push({
emoji: emoji,
name: k,
- aliasOf: getEmojiName(emoji)!,
+ aliasOf: getEmojiName(emoji),
url: char2path(emoji),
});
}
diff --git a/packages/frontend/src/components/MkEmojiPicker.section.vue b/packages/frontend/src/components/MkEmojiPicker.section.vue
index c295ab6bb7..c13164c296 100644
--- a/packages/frontend/src/components/MkEmojiPicker.section.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.section.vue
@@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
@pointerenter="computeButtonTitle"
@click="emit('chosen', emoji, $event)"
>
- <MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
+ <MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true" :fallbackToImage="true"/>
<MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
</button>
</div>
@@ -87,7 +87,7 @@ const shown = ref(!!props.initialShown);
function computeButtonTitle(ev: MouseEvent): void {
const elm = ev.target as HTMLElement;
const emoji = elm.dataset.emoji as string;
- elm.title = getEmojiName(emoji) ?? emoji;
+ elm.title = getEmojiName(emoji);
}
function nestedChosen(emoji: any, ev: MouseEvent) {
diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue
index 06243e5b04..8a6bef54d8 100644
--- a/packages/frontend/src/components/MkEmojiPicker.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.vue
@@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
tabindex="0"
@click="chosen(emoji, $event)"
>
- <MkCustomEmoji class="emoji" :name="emoji.name"/>
+ <MkCustomEmoji class="emoji" :name="emoji.name" :fallbackToImage="true"/>
</button>
</div>
<div v-if="searchResultUnicode.length > 0" class="body">
@@ -353,7 +353,7 @@ watch(q, () => {
searchResultUnicode.value = Array.from(searchUnicode());
});
-function canReact(emoji: Misskey.entities.EmojiSimple | UnicodeEmojiDef): boolean {
+function canReact(emoji: Misskey.entities.EmojiSimple | UnicodeEmojiDef | string): boolean {
return !props.targetNote || checkReactionPermissions($i!, props.targetNote, emoji);
}
@@ -378,11 +378,14 @@ function getKey(emoji: string | Misskey.entities.EmojiSimple | UnicodeEmojiDef):
return typeof emoji === 'string' ? emoji : 'char' in emoji ? emoji.char : `:${emoji.name}:`;
}
-function getDef(emoji: string) {
+function getDef(emoji: string): string | Misskey.entities.EmojiSimple | UnicodeEmojiDef {
if (emoji.includes(':')) {
- return customEmojisMap.get(emoji.replace(/:/g, ''))!;
+ // カスタム絵文字が存在する場合はその情報を持つオブジェクトを返し、
+ // サーバの管理画面から削除された等で情報が見つからない場合は名前の文字列をそのまま返しておく(undefinedを返すとエラーになるため)
+ const name = emoji.replaceAll(':', '');
+ return customEmojisMap.get(name) ?? emoji;
} else {
- return getUnicodeEmoji(emoji)!;
+ return getUnicodeEmoji(emoji);
}
}
@@ -390,7 +393,7 @@ function getDef(emoji: string) {
function computeButtonTitle(ev: MouseEvent): void {
const elm = ev.target as HTMLElement;
const emoji = elm.dataset.emoji as string;
- elm.title = getEmojiName(emoji) ?? emoji;
+ elm.title = getEmojiName(emoji);
}
function chosen(emoji: any, ev?: MouseEvent) {
diff --git a/packages/frontend/src/components/MkReactionIcon.vue b/packages/frontend/src/components/MkReactionIcon.vue
index 59ceab27dc..068a2968db 100644
--- a/packages/frontend/src/components/MkReactionIcon.vue
+++ b/packages/frontend/src/components/MkReactionIcon.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<MkCustomEmoji v-if="reaction[0] === ':'" ref="elRef" :name="reaction" :normal="true" :noStyle="noStyle" :url="emojiUrl"/>
+<MkCustomEmoji v-if="reaction[0] === ':'" ref="elRef" :name="reaction" :normal="true" :noStyle="noStyle" :url="emojiUrl" :fallbackToImage="true"/>
<MkEmoji v-else ref="elRef" :emoji="reaction" :normal="true" :noStyle="noStyle"/>
</template>
diff --git a/packages/frontend/src/components/MkReactionsViewer.details.vue b/packages/frontend/src/components/MkReactionsViewer.details.vue
index 3158ba436e..8b5e6efdf3 100644
--- a/packages/frontend/src/components/MkReactionsViewer.details.vue
+++ b/packages/frontend/src/components/MkReactionsViewer.details.vue
@@ -44,7 +44,7 @@ function getReactionName(reaction: string): string {
if (trimLocal.startsWith(':')) {
return trimLocal;
}
- return getEmojiName(reaction) ?? reaction;
+ return getEmojiName(reaction);
}
</script>
diff --git a/packages/frontend/src/components/global/MkCustomEmoji.stories.impl.ts b/packages/frontend/src/components/global/MkCustomEmoji.stories.impl.ts
index e0da6a4a13..9e6177045d 100644
--- a/packages/frontend/src/components/global/MkCustomEmoji.stories.impl.ts
+++ b/packages/frontend/src/components/global/MkCustomEmoji.stories.impl.ts
@@ -48,3 +48,18 @@ export const Missing = {
name: Default.args.name,
},
} satisfies StoryObj<typeof MkCustomEmoji>;
+export const ErrorToText = {
+ ...Default,
+ args: {
+ url: 'https://example.com/404',
+ name: Default.args.name,
+ },
+} satisfies StoryObj<typeof MkCustomEmoji>;
+export const ErrorToImage = {
+ ...Default,
+ args: {
+ url: 'https://example.com/404',
+ name: Default.args.name,
+ fallbackToImage: true,
+ },
+} satisfies StoryObj<typeof MkCustomEmoji>;
diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue
index dbcb00460c..6123835340 100644
--- a/packages/frontend/src/components/global/MkCustomEmoji.vue
+++ b/packages/frontend/src/components/global/MkCustomEmoji.vue
@@ -4,7 +4,13 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<span v-if="errored">:{{ customEmojiName }}:</span>
+<img
+ v-if="errored && fallbackToImage"
+ :class="[$style.root, { [$style.normal]: normal, [$style.noStyle]: noStyle }]"
+ src="/client-assets/dummy.png"
+ :title="alt"
+/>
+<span v-else-if="errored">:{{ customEmojiName }}:</span>
<img
v-else
:class="[$style.root, { [$style.normal]: normal, [$style.noStyle]: noStyle }]"
@@ -39,6 +45,7 @@ const props = defineProps<{
useOriginalSize?: boolean;
menu?: boolean;
menuReaction?: boolean;
+ fallbackToImage?: boolean;
}>();
const react = inject<((name: string) => void) | null>('react', null);
diff --git a/packages/frontend/src/components/global/MkEmoji.vue b/packages/frontend/src/components/global/MkEmoji.vue
index ba4026f0f6..65f75642b2 100644
--- a/packages/frontend/src/components/global/MkEmoji.vue
+++ b/packages/frontend/src/components/global/MkEmoji.vue
@@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { computed, inject } from 'vue';
-import { char2twemojiFilePath, char2fluentEmojiFilePath } from '@/scripts/emoji-base.js';
+import { char2fluentEmojiFilePath, char2twemojiFilePath } from '@/scripts/emoji-base.js';
import { defaultStore } from '@/store.js';
import { colorizeEmoji, getEmojiName } from '@/scripts/emojilist.js';
import * as os from '@/os.js';
@@ -34,8 +34,7 @@ const colorizedNativeEmoji = computed(() => colorizeEmoji(props.emoji));
// Searching from an array with 2000 items for every emoji felt like too energy-consuming, so I decided to do it lazily on pointerenter
function computeTitle(event: PointerEvent): void {
- const title = getEmojiName(props.emoji as string) ?? props.emoji as string;
- (event.target as HTMLElement).title = title;
+ (event.target as HTMLElement).title = getEmojiName(props.emoji);
}
function onClick(ev: MouseEvent) {
diff --git a/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts b/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts
index 6ce3b6752f..4ed76f6bc4 100644
--- a/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts
+++ b/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts
@@ -407,6 +407,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
useOriginalSize: scale >= 2.5,
menu: props.enableEmojiMenu,
menuReaction: props.enableEmojiMenuReaction,
+ fallbackToImage: false,
})];
} else {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition