summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/global/MkEmoji.vue
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src/components/global/MkEmoji.vue')
-rw-r--r--packages/frontend/src/components/global/MkEmoji.vue47
1 files changed, 46 insertions, 1 deletions
diff --git a/packages/frontend/src/components/global/MkEmoji.vue b/packages/frontend/src/components/global/MkEmoji.vue
index fa55fd888b..792f9c7d6f 100644
--- a/packages/frontend/src/components/global/MkEmoji.vue
+++ b/packages/frontend/src/components/global/MkEmoji.vue
@@ -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);
}
}