summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/global/MkCustomEmoji.vue
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src/components/global/MkCustomEmoji.vue')
-rw-r--r--packages/frontend/src/components/global/MkCustomEmoji.vue112
1 files changed, 91 insertions, 21 deletions
diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue
index dda45ceaa2..ed114d8d31 100644
--- a/packages/frontend/src/components/global/MkCustomEmoji.vue
+++ b/packages/frontend/src/components/global/MkCustomEmoji.vue
@@ -5,7 +5,16 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<img
- v-if="errored && fallbackToImage"
+ v-if="shouldMute"
+ :class="[$style.root, { [$style.normal]: normal, [$style.noStyle]: noStyle }]"
+ src="/client-assets/unknown.png"
+ :title="alt"
+ draggable="false"
+ style="-webkit-user-drag: none;"
+ @click="onClick"
+/>
+<img
+ v-else-if="errored && fallbackToImage"
:class="[$style.root, { [$style.normal]: normal, [$style.noStyle]: noStyle }]"
src="/client-assets/dummy.png"
:title="alt"
@@ -40,6 +49,7 @@ import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialo
import { $i } from '@/i.js';
import { prefer } from '@/preferences.js';
import { DI } from '@/di.js';
+import { makeEmojiMuteKey, mute as muteEmoji, unmute as unmuteEmoji, checkMuted as checkEmojiMuted } from '@/utility/emoji-mute';
const props = defineProps<{
name: string;
@@ -51,12 +61,16 @@ const props = defineProps<{
menu?: boolean;
menuReaction?: boolean;
fallbackToImage?: boolean;
+ ignoreMuted?: boolean;
}>();
const react = inject(DI.mfmEmojiReactCallback);
const customEmojiName = computed(() => (props.name[0] === ':' ? props.name.substring(1, props.name.length - 1) : props.name).replace('@.', ''));
const isLocal = computed(() => !props.host && (customEmojiName.value.endsWith('@.') || !customEmojiName.value.includes('@')));
+const emojiCodeToMute = makeEmojiMuteKey(props);
+const isMuted = checkEmojiMuted(emojiCodeToMute);
+const shouldMute = computed(() => !props.ignoreMuted && isMuted.value);
const rawUrl = computed(() => {
if (props.url) {
@@ -95,14 +109,18 @@ function onClick(ev: MouseEvent) {
menuItems.push({
type: 'label',
text: `:${props.name}:`,
- }, {
- text: i18n.ts.copy,
- icon: 'ti ti-copy',
- action: () => {
- copyToClipboard(`:${props.name}:`);
- },
});
+ if (isLocal.value) {
+ menuItems.push({
+ text: i18n.ts.copy,
+ icon: 'ti ti-copy',
+ action: () => {
+ copyToClipboard(`:${props.name}:`);
+ },
+ });
+ }
+
if (props.menuReaction && react) {
menuItems.push({
text: i18n.ts.doReaction,
@@ -113,21 +131,43 @@ function onClick(ev: MouseEvent) {
});
}
- menuItems.push({
- text: i18n.ts.info,
- icon: 'ti ti-info-circle',
- action: async () => {
- const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
- emoji: await misskeyApiGet('emoji', {
- name: customEmojiName.value,
- }),
- }, {
- closed: () => dispose(),
- });
- },
- });
+ if (isLocal.value) {
+ menuItems.push({
+ type: 'divider',
+ }, {
+ text: i18n.ts.info,
+ icon: 'ti ti-info-circle',
+ action: async () => {
+ const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
+ emoji: await misskeyApiGet('emoji', {
+ name: customEmojiName.value,
+ }),
+ }, {
+ closed: () => dispose(),
+ });
+ },
+ });
+ }
- if ($i?.isModerator ?? $i?.isAdmin) {
+ if (isMuted.value) {
+ menuItems.push({
+ text: i18n.ts.emojiUnmute,
+ icon: 'ti ti-mood-smile',
+ action: async () => {
+ await unmute();
+ },
+ });
+ } else {
+ menuItems.push({
+ text: i18n.ts.emojiMute,
+ icon: 'ti ti-mood-off',
+ action: async () => {
+ await mute();
+ },
+ });
+ }
+
+ if (($i?.isModerator ?? $i?.isAdmin) && isLocal.value) {
menuItems.push({
text: i18n.ts.edit,
icon: 'ti ti-pencil',
@@ -152,6 +192,36 @@ async function edit(name: string) {
});
}
+function mute() {
+ const titleEmojiName = isLocal.value
+ ? `:${customEmojiName.value}:`
+ : emojiCodeToMute;
+ os.confirm({
+ type: 'question',
+ title: i18n.tsx.muteX({ x: titleEmojiName }),
+ }).then(({ canceled }) => {
+ if (canceled) {
+ return;
+ }
+ muteEmoji(emojiCodeToMute);
+ });
+}
+
+function unmute() {
+ const titleEmojiName = isLocal.value
+ ? `:${customEmojiName.value}:`
+ : emojiCodeToMute;
+ os.confirm({
+ type: 'question',
+ title: i18n.tsx.unmuteX({ x: titleEmojiName }),
+ }).then(({ canceled }) => {
+ if (canceled) {
+ return;
+ }
+ unmuteEmoji(emojiCodeToMute);
+ });
+}
+
</script>
<style lang="scss" module>