summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorおさむのひと <46447427+samunohito@users.noreply.github.com>2024-03-02 13:28:10 +0900
committerGitHub <noreply@github.com>2024-03-02 13:28:10 +0900
commit32690f576f75f7bd8fe141c5e3ae524a64e61614 (patch)
tree9a0b1d2e111e042dfebaaf374277886b70570c1a
parentchore(client): 絵文字の画像読み込みに失敗した際はテキス... (diff)
downloadmisskey-32690f576f75f7bd8fe141c5e3ae524a64e61614.tar.gz
misskey-32690f576f75f7bd8fe141c5e3ae524a64e61614.tar.bz2
misskey-32690f576f75f7bd8fe141c5e3ae524a64e61614.zip
fix(frontend): ピン留め or 履歴に表示されるカスタム絵文字がサーバから削除されるとリアクションが出来なくなる (#13486)
* fix(frontend): ピン留めに登録されているカスタム絵文字がサーバから削除されるとリアクションが出来なくなる * fix CHANGELOG.md * fix Unicode Emojis * fix Unicode Emojis * fix
-rw-r--r--CHANGELOG.md13
-rw-r--r--packages/frontend/src/components/MkAutocomplete.vue2
-rw-r--r--packages/frontend/src/components/MkEmojiPicker.section.vue2
-rw-r--r--packages/frontend/src/components/MkEmojiPicker.vue13
-rw-r--r--packages/frontend/src/components/MkReactionsViewer.details.vue2
-rw-r--r--packages/frontend/src/components/global/MkEmoji.vue5
-rw-r--r--packages/frontend/src/scripts/check-reaction-permissions.ts10
-rw-r--r--packages/frontend/src/scripts/emojilist.ts20
8 files changed, 45 insertions, 22 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 15028e7008..6ce43b12d1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,19 @@
-->
+## 202x.x.x (unreleased)
+
+### General
+-
+
+### Client
+- Fix: 絵文字関係の不具合を修正 (#13485)
+ - 履歴に残っている or ピン留めされた絵文字がコントロールパネルより削除されていた際にリアクションデッキが表示できなくなる
+ - Unicode絵文字が履歴に残っている or ピン留めされているとリアクションデッキが表示できなくなる
+
+### Server
+-
+
## 2024.3.0
### General
diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue
index cae6bc7111..2f3855266c 100644
--- a/packages/frontend/src/components/MkAutocomplete.vue
+++ b/packages/frontend/src/components/MkAutocomplete.vue
@@ -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..012972d8eb 100644
--- a/packages/frontend/src/components/MkEmojiPicker.section.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.section.vue
@@ -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..e30d5969d9 100644
--- a/packages/frontend/src/components/MkEmojiPicker.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.vue
@@ -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/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/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/scripts/check-reaction-permissions.ts b/packages/frontend/src/scripts/check-reaction-permissions.ts
index da704717c1..e7b473dd75 100644
--- a/packages/frontend/src/scripts/check-reaction-permissions.ts
+++ b/packages/frontend/src/scripts/check-reaction-permissions.ts
@@ -1,12 +1,12 @@
import * as Misskey from 'misskey-js';
import { UnicodeEmojiDef } from './emojilist.js';
-export function checkReactionPermissions(me: Misskey.entities.MeDetailed, note: Misskey.entities.Note, emoji: Misskey.entities.EmojiSimple | UnicodeEmojiDef): boolean {
- if ('char' in emoji) return true; // UnicodeEmojiDefなら常にリアクション可能
+export function checkReactionPermissions(me: Misskey.entities.MeDetailed, note: Misskey.entities.Note, emoji: Misskey.entities.EmojiSimple | UnicodeEmojiDef | string): boolean {
+ if (typeof emoji === 'string') return true; // UnicodeEmojiDefにも無い絵文字であれば文字列で来る。Unicode絵文字であることには変わりないので常にリアクション可能とする;
+ if ('char' in emoji) return true; // UnicodeEmojiDefなら常にリアクション可能
- emoji = emoji as Misskey.entities.EmojiSimple;
- const roleIdsThatCanBeUsedThisEmojiAsReaction = emoji.roleIdsThatCanBeUsedThisEmojiAsReaction ?? [];
- return !(emoji.localOnly && note.user.host !== me.host)
+ const roleIdsThatCanBeUsedThisEmojiAsReaction = emoji.roleIdsThatCanBeUsedThisEmojiAsReaction ?? [];
+ return !(emoji.localOnly && note.user.host !== me.host)
&& !(emoji.isSensitive && (note.reactionAcceptance === 'nonSensitiveOnly' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote'))
&& (roleIdsThatCanBeUsedThisEmojiAsReaction.length === 0 || me.roles.some(role => roleIdsThatCanBeUsedThisEmojiAsReaction.includes(role.id)));
}
diff --git a/packages/frontend/src/scripts/emojilist.ts b/packages/frontend/src/scripts/emojilist.ts
index 35a08ef331..6565feba97 100644
--- a/packages/frontend/src/scripts/emojilist.ts
+++ b/packages/frontend/src/scripts/emojilist.ts
@@ -39,21 +39,29 @@ for (let i = 0; i < emojilist.length; i++) {
export const emojiCharByCategory = _charGroupByCategory;
-export function getUnicodeEmoji(char: string): UnicodeEmojiDef | null {
+export function getUnicodeEmoji(char: string): UnicodeEmojiDef | string {
// Colorize it because emojilist.json assumes that
- return unicodeEmojisMap.get(colorizeEmoji(char)) ?? unicodeEmojisMap.get(char) ?? null;
+ return unicodeEmojisMap.get(colorizeEmoji(char))
+ // カラースタイル絵文字がjsonに無い場合はテキストスタイル絵文字にフォールバックする
+ ?? unicodeEmojisMap.get(char)
+ // それでも見つからない場合はそのまま返す(絵文字情報がjsonに無い場合、このフォールバックが無いとレンダリングに失敗する)
+ ?? char;
}
-export function getEmojiName(char: string): string | null {
+export function getEmojiName(char: string): string {
// Colorize it because emojilist.json assumes that
- const idx = _indexByChar.get(colorizeEmoji(char));
- if (idx == null) {
- return null;
+ const idx = _indexByChar.get(colorizeEmoji(char)) ?? _indexByChar.get(char);
+ if (idx === undefined) {
+ // 絵文字情報がjsonに無い場合は名前の取得が出来ないのでそのまま返すしか無い
+ return char;
} else {
return emojilist[idx].name;
}
}
+/**
+ * テキストスタイル絵文字(U+260Eなどの1文字で表現される絵文字)をカラースタイル絵文字に変換します(VS16:U+FE0Fを付与)。
+ */
export function colorizeEmoji(char: string) {
return char.length === 1 ? `${char}\uFE0F` : char;
}