mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-30 21:33:56 +02:00
feat(frontend): 絵文字をミュート可能にする機能 (#15966)
* wip ( 絵文字ミュートの基礎実装, PoC )
* refactor: 絵文字のmute/unmute処理の共通化
* SPDX
* リアクションからも絵文字ミュート可能に
* emojiMute/emojiUnmute
* replace resource of emojiMute
* add vitest preferstate for mutedEmojis
* add vitest to preferReactive
* 混入削除
* Fix typo (mutedEmojis -> mutingEmojis)
* reactiveやめる
* add時の判定ミスを修正
* Add CHANGELOG
* Revert "reactiveやめる"
This reverts commit 442742c371.
* Update Changelog
This commit is contained in:
@@ -4,7 +4,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<img v-if="!useOsNativeEmojis" :class="$style.root" :src="url" :alt="props.emoji" decoding="async" @pointerenter="computeTitle" @click="onClick"/>
|
||||
<img v-if="shouldMute" :class="$style.root" src="/client-assets/unknown.png" :alt="props.emoji" decoding="async" @pointerenter="computeTitle" @click="onClick"/>
|
||||
<img v-else-if="!useOsNativeEmojis" :class="$style.root" :src="url" :alt="props.emoji" decoding="async" @pointerenter="computeTitle" @click="onClick"/>
|
||||
<span v-else :alt="props.emoji" @pointerenter="computeTitle" @click="onClick">{{ colorizedNativeEmoji }}</span>
|
||||
</template>
|
||||
|
||||
@@ -18,11 +19,13 @@ import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
import { DI } from '@/di.js';
|
||||
import { mute as muteEmoji, unmute as unmuteEmoji, checkMuted as checkMutedEmoji } from '@/utility/emoji-mute.js';
|
||||
|
||||
const props = defineProps<{
|
||||
emoji: string;
|
||||
menu?: boolean;
|
||||
menuReaction?: boolean;
|
||||
ignoreMuted?: boolean;
|
||||
}>();
|
||||
|
||||
const react = inject(DI.mfmEmojiReactCallback, null);
|
||||
@@ -32,12 +35,38 @@ const char2path = prefer.s.emojiStyle === 'twemoji' ? char2twemojiFilePath : cha
|
||||
const useOsNativeEmojis = computed(() => prefer.s.emojiStyle === 'native');
|
||||
const url = computed(() => char2path(props.emoji));
|
||||
const colorizedNativeEmoji = computed(() => colorizeEmoji(props.emoji));
|
||||
const isMuted = checkMutedEmoji(props.emoji);
|
||||
const shouldMute = computed(() => isMuted.value && !props.ignoreMuted);
|
||||
|
||||
// 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 {
|
||||
(event.target as HTMLElement).title = getEmojiName(props.emoji);
|
||||
}
|
||||
|
||||
function mute() {
|
||||
os.confirm({
|
||||
type: 'question',
|
||||
title: i18n.tsx.muteX({ x: props.emoji }),
|
||||
}).then(({ canceled }) => {
|
||||
if (canceled) {
|
||||
return;
|
||||
}
|
||||
muteEmoji(props.emoji);
|
||||
});
|
||||
}
|
||||
|
||||
function unmute() {
|
||||
os.confirm({
|
||||
type: 'question',
|
||||
title: i18n.tsx.unmuteX({ x: props.emoji }),
|
||||
}).then(({ canceled }) => {
|
||||
if (canceled) {
|
||||
return;
|
||||
}
|
||||
unmuteEmoji(props.emoji);
|
||||
});
|
||||
}
|
||||
|
||||
function onClick(ev: MouseEvent) {
|
||||
if (props.menu) {
|
||||
const menuItems: MenuItem[] = [];
|
||||
@@ -63,6 +92,22 @@ function onClick(ev: MouseEvent) {
|
||||
});
|
||||
}
|
||||
|
||||
menuItems.push({
|
||||
type: 'divider',
|
||||
}, isMuted.value ? {
|
||||
text: i18n.ts.emojiUnmute,
|
||||
icon: 'ti ti-mood-smile',
|
||||
action: () => {
|
||||
unmute();
|
||||
},
|
||||
} : {
|
||||
text: i18n.ts.emojiMute,
|
||||
icon: 'ti ti-mood-off',
|
||||
action: () => {
|
||||
mute();
|
||||
},
|
||||
});
|
||||
|
||||
os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user