From 19b1015277da8125ed0c23c8f9ebf26ddcd9c25a Mon Sep 17 00:00:00 2001 From: 1Step621 Date: Sat, 17 Feb 2024 08:32:36 +0900 Subject: [PATCH 1/7] =?UTF-8?q?=E6=89=93=E3=81=A6=E3=81=AA=E3=81=84?= =?UTF-8?q?=E7=B5=B5=E6=96=87=E5=AD=97=E3=82=92=E8=A1=A8=E7=A4=BA=E3=81=97?= =?UTF-8?q?=E3=81=AA=E3=81=84=E3=81=AE=E3=81=A7=E3=81=AF=E3=81=AA=E3=81=8F?= =?UTF-8?q?=E3=82=B0=E3=83=AC=E3=83=BC=E3=82=A2=E3=82=A6=E3=83=88=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=20=E3=81=AA=E3=81=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/MkEmojiPicker.section.vue | 3 ++ .../frontend/src/components/MkEmojiPicker.vue | 47 +++++++++++++++---- .../components/MkReactionsViewer.reaction.vue | 11 ++--- .../src/scripts/check-reaction-permissions.ts | 6 ++- 4 files changed, 52 insertions(+), 15 deletions(-) diff --git a/packages/frontend/src/components/MkEmojiPicker.section.vue b/packages/frontend/src/components/MkEmojiPicker.section.vue index 30ad2bcbbfd3..c295ab6bb7cd 100644 --- a/packages/frontend/src/components/MkEmojiPicker.section.vue +++ b/packages/frontend/src/components/MkEmojiPicker.section.vue @@ -16,6 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only :key="emoji" :data-emoji="emoji" class="_button item" + :disabled="disabledEmojis?.value.includes(emoji)" @pointerenter="computeButtonTitle" @click="emit('chosen', emoji, $event)" > @@ -48,6 +49,7 @@ SPDX-License-Identifier: AGPL-3.0-only :key="emoji" :data-emoji="emoji" class="_button item" + :disabled="disabledEmojis?.value.includes(emoji)" @pointerenter="computeButtonTitle" @click="emit('chosen', emoji, $event)" > @@ -67,6 +69,7 @@ import MkEmojiPickerSection from '@/components/MkEmojiPicker.section.vue'; const props = defineProps<{ emojis: string[] | Ref; + disabledEmojis?: Ref; initialShown?: boolean; hasChildSection?: boolean; customEmojiTree?: CustomEmojiFolderTree[]; diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 366273118b47..ae188fdf0c8e 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -57,15 +57,16 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.recentUsed }}
@@ -76,7 +77,8 @@ SPDX-License-Identifier: AGPL-3.0-only v-for="child in customEmojiFolderRoot.children" :key="`custom:${child.value}`" :initialShown="false" - :emojis="computed(() => customEmojis.filter(e => child.value === '' ? (e.category === 'null' || !e.category) : e.category === child.value).filter(filterAvailable).map(e => `:${e.name}:`))" + :emojis="computed(() => customEmojis.filter(e => filterCategory(e, child.value)).map(e => `:${e.name}:`))" + :disabledEmojis="computed(() => customEmojis.filter(e => filterCategory(e, child.value)).filter(e => !canReact(e)).map(e => `:${e.name}:`))" :hasChildSection="child.children.length !== 0" :customEmojiTree="child.children" @chosen="chosen" @@ -146,6 +148,16 @@ const { recentlyUsedEmojis, } = defaultStore.reactiveState; +const recentlyUsedEmojisDef = computed(() => { + return recentlyUsedEmojis.value.map((emoji: string) => { + if (emoji.includes(':')) { + return customEmojisMap.get(emoji.replace(/:/g, ''))!; + } else { + return emojilist.find(e => e.char === emoji)!; + } + }); +}); + const pinned = computed(() => props.pinnedEmojis); const size = computed(() => emojiPickerScale.value); const width = computed(() => emojiPickerWidth.value); @@ -337,14 +349,18 @@ watch(q, () => { return matches; }; - searchResultCustom.value = Array.from(searchCustom()).filter(filterAvailable); + searchResultCustom.value = Array.from(searchCustom()); searchResultUnicode.value = Array.from(searchUnicode()); }); -function filterAvailable(emoji: Misskey.entities.EmojiSimple): boolean { +function canReact(emoji: Misskey.entities.EmojiSimple | UnicodeEmojiDef): boolean { return !props.targetNote || checkReactionPermissions($i!, props.targetNote, emoji); } +function filterCategory(emoji: Misskey.entities.EmojiSimple, category: string): boolean { + return category === '' ? (emoji.category === 'null' || !emoji.category) : emoji.category === category; +} + function focus() { if (!['smartphone', 'tablet'].includes(deviceKind) && !isTouchUsing) { searchEl.value?.focus({ @@ -526,6 +542,11 @@ defineExpose({ width: auto; height: auto; min-width: 0; + + &:disabled { + opacity: 1; + filter: grayscale(1); + } } } } @@ -548,6 +569,11 @@ defineExpose({ width: auto; height: auto; min-width: 0; + + &:disabled { + opacity: 1; + filter: grayscale(1); + } } } } @@ -663,6 +689,11 @@ defineExpose({ box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15); } + &:disabled { + opacity: 1; + filter: grayscale(1); + } + > .emoji { height: 1.25em; vertical-align: -.25em; diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue index 0dcd8b0ea25b..9b50cc1d9cc7 100644 --- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue +++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue @@ -33,7 +33,8 @@ import { defaultStore } from '@/store.js'; import { i18n } from '@/i18n.js'; import * as sound from '@/scripts/sound.js'; import { checkReactionPermissions } from '@/scripts/check-reaction-permissions.js'; -import { customEmojis } from '@/custom-emojis.js'; +import { customEmojisMap } from '@/custom-emojis.js'; +import { emojilist } from '@/scripts/emojilist.js'; const props = defineProps<{ reaction: string; @@ -50,13 +51,11 @@ const emit = defineEmits<{ const buttonEl = shallowRef(); -const isCustomEmoji = computed(() => props.reaction.includes(':')); -const emoji = computed(() => isCustomEmoji.value ? customEmojis.value.find(emoji => emoji.name === props.reaction.replace(/:/g, '').replace(/@\./, '')) : null); +const emojiName = computed(() => props.reaction.replace(/:/g, '').replace(/@\./, '')); +const emoji = computed(() => customEmojisMap.get(emojiName.value) ?? emojilist.find(emoji => emoji.char === emojiName.value)); const canToggle = computed(() => { - return !props.reaction.match(/@\w/) && $i - && (emoji.value && checkReactionPermissions($i, props.note, emoji.value)) - || !isCustomEmoji.value; + return !props.reaction.match(/@\w/) && $i && emoji.value && checkReactionPermissions($i, props.note, emoji.value); }); const canGetInfo = computed(() => !props.reaction.match(/@\w/) && props.reaction.includes(':')); diff --git a/packages/frontend/src/scripts/check-reaction-permissions.ts b/packages/frontend/src/scripts/check-reaction-permissions.ts index c9d2a5bfc6bf..f2185e7c50ed 100644 --- a/packages/frontend/src/scripts/check-reaction-permissions.ts +++ b/packages/frontend/src/scripts/check-reaction-permissions.ts @@ -1,6 +1,10 @@ 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): boolean { +export function checkReactionPermissions(me: Misskey.entities.MeDetailed, note: Misskey.entities.Note, emoji: Misskey.entities.EmojiSimple | UnicodeEmojiDef): boolean { + if (emoji.hasOwnProperty('char')) return true; // UnicodeEmojiDefなら常にリアクション可能 + + emoji = emoji as Misskey.entities.EmojiSimple; const roleIdsThatCanBeUsedThisEmojiAsReaction = emoji.roleIdsThatCanBeUsedThisEmojiAsReaction ?? []; return !(emoji.localOnly && note.user.host !== me.host) && !(emoji.isSensitive && (note.reactionAcceptance === 'nonSensitiveOnly' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote')) From 8e06e3174cb55435708938d9dcff68b3296892dc Mon Sep 17 00:00:00 2001 From: 1Step621 Date: Sat, 17 Feb 2024 09:10:14 +0900 Subject: [PATCH 2/7] =?UTF-8?q?fix:=20=E4=BB=8A=E5=BA=A6=E3=81=AF=E6=A4=9C?= =?UTF-8?q?=E7=B4=A2=E3=81=A8=E3=83=94=E3=83=B3=E7=95=99=E3=82=81=E3=81=AB?= =?UTF-8?q?=E5=8A=B9=E3=81=84=E3=81=A6=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/src/components/MkEmojiPicker.vue | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index ae188fdf0c8e..5f6358222928 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -14,6 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only v-for="emoji in searchResultCustom" :key="emoji.name" class="_button item" + :disabled="!canReact(emoji)" :title="emoji.name" tabindex="0" @click="chosen(emoji, $event)" @@ -39,16 +40,17 @@ SPDX-License-Identifier: AGPL-3.0-only
@@ -149,13 +151,10 @@ const { } = defaultStore.reactiveState; const recentlyUsedEmojisDef = computed(() => { - return recentlyUsedEmojis.value.map((emoji: string) => { - if (emoji.includes(':')) { - return customEmojisMap.get(emoji.replace(/:/g, ''))!; - } else { - return emojilist.find(e => e.char === emoji)!; - } - }); + return recentlyUsedEmojis.value.map(getDef); +}); +const pinnedEmojisDef = computed(() => { + return pinned.value?.map(getDef); }); const pinned = computed(() => props.pinnedEmojis); @@ -378,6 +377,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) { + if (emoji.includes(':')) { + return customEmojisMap.get(emoji.replace(/:/g, ''))!; + } else { + return emojilist.find(e => e.char === emoji)!; + } +} + /** @see MkEmojiPicker.section.vue */ function computeButtonTitle(ev: MouseEvent): void { const elm = ev.target as HTMLElement; From 90c3f96447ce765cd72854b7f60a1c32a4f5036e Mon Sep 17 00:00:00 2001 From: 1Step621 Date: Sat, 17 Feb 2024 09:12:57 +0900 Subject: [PATCH 3/7] lint fix --- packages/frontend/src/scripts/check-reaction-permissions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/scripts/check-reaction-permissions.ts b/packages/frontend/src/scripts/check-reaction-permissions.ts index f2185e7c50ed..da704717c127 100644 --- a/packages/frontend/src/scripts/check-reaction-permissions.ts +++ b/packages/frontend/src/scripts/check-reaction-permissions.ts @@ -2,7 +2,7 @@ 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 (emoji.hasOwnProperty('char')) return true; // UnicodeEmojiDefなら常にリアクション可能 + if ('char' in emoji) return true; // UnicodeEmojiDefなら常にリアクション可能 emoji = emoji as Misskey.entities.EmojiSimple; const roleIdsThatCanBeUsedThisEmojiAsReaction = emoji.roleIdsThatCanBeUsedThisEmojiAsReaction ?? []; From 60e30bc44d601566a9b881885d28716aa56e01d2 Mon Sep 17 00:00:00 2001 From: 1Step621 Date: Sat, 17 Feb 2024 13:57:23 +0900 Subject: [PATCH 4/7] use Map --- packages/frontend/src/components/MkEmojiPicker.vue | 3 ++- .../frontend/src/components/MkReactionsViewer.reaction.vue | 4 ++-- packages/frontend/src/scripts/emojilist.ts | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 5f6358222928..3af31b13d489 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -108,6 +108,7 @@ import * as Misskey from 'misskey-js'; import XSection from '@/components/MkEmojiPicker.section.vue'; import { emojilist, + unicodeEmojisMap, emojiCharByCategory, UnicodeEmojiDef, unicodeEmojiCategories as categories, @@ -381,7 +382,7 @@ function getDef(emoji: string) { if (emoji.includes(':')) { return customEmojisMap.get(emoji.replace(/:/g, ''))!; } else { - return emojilist.find(e => e.char === emoji)!; + return unicodeEmojisMap.get(emoji)!; } } diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue index 9b50cc1d9cc7..bccee5109de9 100644 --- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue +++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue @@ -34,7 +34,7 @@ import { i18n } from '@/i18n.js'; import * as sound from '@/scripts/sound.js'; import { checkReactionPermissions } from '@/scripts/check-reaction-permissions.js'; import { customEmojisMap } from '@/custom-emojis.js'; -import { emojilist } from '@/scripts/emojilist.js'; +import { unicodeEmojisMap } from '@/scripts/emojilist.js'; const props = defineProps<{ reaction: string; @@ -52,7 +52,7 @@ const emit = defineEmits<{ const buttonEl = shallowRef(); const emojiName = computed(() => props.reaction.replace(/:/g, '').replace(/@\./, '')); -const emoji = computed(() => customEmojisMap.get(emojiName.value) ?? emojilist.find(emoji => emoji.char === emojiName.value)); +const emoji = computed(() => customEmojisMap.get(emojiName.value) ?? unicodeEmojisMap.get(props.reaction)); const canToggle = computed(() => { return !props.reaction.match(/@\w/) && $i && emoji.value && checkReactionPermissions($i, props.note, emoji.value); diff --git a/packages/frontend/src/scripts/emojilist.ts b/packages/frontend/src/scripts/emojilist.ts index 54d45e025f60..2a6120f3bad6 100644 --- a/packages/frontend/src/scripts/emojilist.ts +++ b/packages/frontend/src/scripts/emojilist.ts @@ -20,6 +20,10 @@ export const emojilist: UnicodeEmojiDef[] = _emojilist.map(x => ({ category: unicodeEmojiCategories[x[2]], })); +export const unicodeEmojisMap = new Map( + emojilist.map(x => [x.char, x]) +); + const _indexByChar = new Map(); const _charGroupByCategory = new Map(); for (let i = 0; i < emojilist.length; i++) { From 77a88bcf05f1c261a9cc73a026ed6097666c5565 Mon Sep 17 00:00:00 2001 From: 1Step621 Date: Sat, 17 Feb 2024 14:36:19 +0900 Subject: [PATCH 5/7] =?UTF-8?q?=E6=96=9C=E3=82=81=E3=81=AB=E7=B7=9A?= =?UTF-8?q?=E3=82=92=E5=BC=95=E3=81=84=E3=81=A6=E3=82=8F=E3=81=8B=E3=82=8A?= =?UTF-8?q?=E3=82=84=E3=81=99=E3=81=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/MkEmojiPicker.vue | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 3af31b13d489..e5e335b2f001 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -552,8 +552,9 @@ defineExpose({ min-width: 0; &:disabled { - opacity: 1; filter: grayscale(1); + cursor: not-allowed; + background: linear-gradient(45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); } } } @@ -579,8 +580,9 @@ defineExpose({ min-width: 0; &:disabled { - opacity: 1; filter: grayscale(1); + cursor: not-allowed; + background: linear-gradient(45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); } } } @@ -698,8 +700,9 @@ defineExpose({ } &:disabled { - opacity: 1; filter: grayscale(1); + cursor: not-allowed; + background: linear-gradient(45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); } > .emoji { From 5188b1243f31ea8d3bfb14c9e131ca464df6f001 Mon Sep 17 00:00:00 2001 From: 1Step621 Date: Sat, 17 Feb 2024 14:39:46 +0900 Subject: [PATCH 6/7] =?UTF-8?q?=E6=96=9C=E3=82=81=E7=B7=9A=E3=81=AF?= =?UTF-8?q?=E5=8F=B3=E4=B8=8A=E3=81=8B=E3=82=89=E3=81=AE=E3=81=BB=E3=81=86?= =?UTF-8?q?=E3=81=8C=E8=89=AF=E3=81=8B=E3=81=A3=E3=81=9F=E3=81=8B=E3=82=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/MkEmojiPicker.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index e5e335b2f001..89ebd5efb166 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -554,7 +554,7 @@ defineExpose({ &:disabled { filter: grayscale(1); cursor: not-allowed; - background: linear-gradient(45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); + background: linear-gradient(-45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); } } } @@ -582,7 +582,7 @@ defineExpose({ &:disabled { filter: grayscale(1); cursor: not-allowed; - background: linear-gradient(45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); + background: linear-gradient(-45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); } } } @@ -702,7 +702,7 @@ defineExpose({ &:disabled { filter: grayscale(1); cursor: not-allowed; - background: linear-gradient(45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); + background: linear-gradient(-45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); } > .emoji { From 030e933f97188791485bf4f2d7ce005fc8874591 Mon Sep 17 00:00:00 2001 From: 1Step621 Date: Sun, 18 Feb 2024 12:32:29 +0900 Subject: [PATCH 7/7] =?UTF-8?q?=E3=83=87=E3=82=B6=E3=82=A4=E3=83=B3?= =?UTF-8?q?=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/src/components/MkEmojiPicker.vue | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 89ebd5efb166..061afa66ac03 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -552,9 +552,15 @@ defineExpose({ min-width: 0; &:disabled { - filter: grayscale(1); cursor: not-allowed; - background: linear-gradient(-45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); + background: linear-gradient(-45deg, transparent 0% 48%, var(--X6) 48% 52%, transparent 52% 100%); + opacity: 1; + + > .emoji { + filter: grayscale(1); + mix-blend-mode: exclusion; + opacity: 0.8; + } } } } @@ -580,9 +586,15 @@ defineExpose({ min-width: 0; &:disabled { - filter: grayscale(1); cursor: not-allowed; - background: linear-gradient(-45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); + background: linear-gradient(-45deg, transparent 0% 48%, var(--X6) 48% 52%, transparent 52% 100%); + opacity: 1; + + > .emoji { + filter: grayscale(1); + mix-blend-mode: exclusion; + opacity: 0.8; + } } } } @@ -700,9 +712,15 @@ defineExpose({ } &:disabled { - filter: grayscale(1); cursor: not-allowed; - background: linear-gradient(-45deg, transparent 0% 48%, var(--accent) 48% 52%, transparent 52% 100%); + background: linear-gradient(-45deg, transparent 0% 48%, var(--X6) 48% 52%, transparent 52% 100%); + opacity: 1; + + > .emoji { + filter: grayscale(1); + mix-blend-mode: exclusion; + opacity: 0.8; + } } > .emoji {