summaryrefslogtreecommitdiff
path: root/packages/client/src/components/global/emoji.vue
blob: 0075e0867de1595baa2cb1085608b52d76dda6a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<template>
<img v-if="customEmoji" class="mk-emoji custom" :class="{ normal, noStyle }" :src="url" :alt="alt" :title="alt" decoding="async"/>
<img v-else-if="char && !useOsNativeEmojis" class="mk-emoji" :src="url" :alt="alt" :title="alt" decoding="async"/>
<span v-else-if="char && useOsNativeEmojis">{{ char }}</span>
<span v-else>{{ emoji }}</span>
</template>

<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue';
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
import { twemojiSvgBase } from '@/scripts/twemoji-base';
import { defaultStore } from '@/store';
import { instance } from '@/instance';

export default defineComponent({
	props: {
		emoji: {
			type: String,
			required: true
		},
		normal: {
			type: Boolean,
			required: false,
			default: false
		},
		noStyle: {
			type: Boolean,
			required: false,
			default: false
		},
		customEmojis: {
			required: false
		},
		isReaction: {
			type: Boolean,
			default: false
		},
	},

	setup(props) {
		const isCustom = computed(() => props.emoji.startsWith(':'));
		const char = computed(() => isCustom.value ? null : props.emoji);
		const useOsNativeEmojis = computed(() => defaultStore.state.useOsNativeEmojis && !props.isReaction);
		const ce = computed(() => props.customEmojis || instance.emojis || []);
		const customEmoji = computed(() => isCustom.value ? ce.value.find(x => x.name === props.emoji.substr(1, props.emoji.length - 2)) : null);
		const url = computed(() => {
			if (char.value) {
				let codes = Array.from(char.value).map(x => x.codePointAt(0).toString(16));
				if (!codes.includes('200d')) codes = codes.filter(x => x !== 'fe0f');
				codes = codes.filter(x => x && x.length);
				return `${twemojiSvgBase}/${codes.join('-')}.svg`;
			} else {
				return defaultStore.state.disableShowingAnimatedImages
					? getStaticImageUrl(customEmoji.value.url)
					: customEmoji.value.url;
			}
		});
		const alt = computed(() => customEmoji.value ? `:${customEmoji.value.name}:` : char.value);

		return {
			url,
			char,
			alt,
			customEmoji,
			useOsNativeEmojis,
		};
	},
});
</script>

<style lang="scss" scoped>
.mk-emoji {
	height: 1.25em;
	vertical-align: -0.25em;

	&.custom {
		height: 2.5em;
		vertical-align: middle;
		transition: transform 0.2s ease;

		&:hover {
			transform: scale(1.2);
		}

		&.normal {
			height: 1.25em;
			vertical-align: -0.25em;

			&:hover {
				transform: none;
			}
		}
	}

	&.noStyle {
		height: auto !important;
	}
}
</style>