enhance(frontend): ノート内のカスタム絵文字をクリックすることで、コピーおよびリアクションができるように

This commit is contained in:
syuilo 2023-11-04 18:27:22 +09:00
parent ca1cda0db0
commit 5e9f6a90df
18 changed files with 82 additions and 21 deletions

View file

@ -5,14 +5,27 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<span v-if="errored">:{{ customEmojiName }}:</span>
<img v-else :class="[$style.root, { [$style.normal]: normal, [$style.noStyle]: noStyle }]" :src="url" :alt="alt" :title="alt" decoding="async" @error="errored = true" @load="errored = false"/>
<img
v-else
:class="[$style.root, { [$style.normal]: normal, [$style.noStyle]: noStyle }]"
:src="url"
:alt="alt"
:title="alt"
decoding="async"
@error="errored = true"
@load="errored = false"
@click="onClick"
/>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { computed, inject } from 'vue';
import { getProxiedImageUrl, getStaticImageUrl } from '@/scripts/media-proxy.js';
import { defaultStore } from '@/store.js';
import { customEmojisMap } from '@/custom-emojis.js';
import * as os from '@/os.js';
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
import { i18n } from '@/i18n.js';
const props = defineProps<{
name: string;
@ -21,8 +34,12 @@ const props = defineProps<{
host?: string | null;
url?: string;
useOriginalSize?: boolean;
menu?: boolean;
menuReaction?: boolean;
}>();
const react = inject<((name: string) => void) | null>('react', null);
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('@')));
@ -55,6 +72,28 @@ const url = computed(() => {
const alt = computed(() => `:${customEmojiName.value}:`);
let errored = $ref(url.value == null);
function onClick(ev: MouseEvent) {
if (props.menu) {
os.popupMenu([{
type: 'label',
text: `:${props.name}:`,
}, {
text: i18n.ts.copy,
icon: 'ti ti-copy',
action: () => {
copyToClipboard(`:${props.name}:`);
os.success();
},
}, ...(props.menuReaction && react ? [{
text: i18n.ts.doReaction,
icon: 'ti ti-plus',
action: () => {
react(`:${props.name}:`);
},
}] : [])], ev.currentTarget ?? ev.target);
}
}
</script>
<style lang="scss" module>