feat: support custom emojis from other servers

This commit is contained in:
Anthony Fu 2022-11-23 07:42:20 +08:00
parent f3a0a5af3f
commit 6d66bbbc5d
10 changed files with 40 additions and 16 deletions

View file

@ -0,0 +1,11 @@
<script setup lang="ts">
import type { Account } from 'masto'
defineProps<{
account: Account
}>()
</script>
<template>
<img :src="account.avatar" :alt="account.username" rounded bg-gray:10>
</template>

View file

@ -21,11 +21,11 @@ const createdAt = $computed(() => {
<div flex flex-col gap-2>
<div p1>
<NuxtLink :to="`/@${account.acct}`">
<img :src="account.avatar" rounded w-20 h-20>
<AccountAvatar :account="account" w-20 h-20 />
</NuxtLink>
</div>
<NuxtLink flex flex-col :to="`/@${account.acct}`">
<CommonRichContent font-bold :content="getDisplayName(account)" />
<CommonRichContent font-bold :content="getDisplayName(account)" :emojis="account.emojis" />
<p op50>
@{{ account.acct }}
</p>

View file

@ -11,11 +11,11 @@ const { link = true } = defineProps<{
<div flex gap-2>
<div p1>
<NuxtLink :to="link ? `/@${account.acct}` : null">
<img :src="account.avatar" rounded w-10 h-10 bg-gray:10>
<AccountAvatar :account="account" w-10 h-10 />
</NuxtLink>
</div>
<NuxtLink flex flex-col :to="link ? `/@${account.acct}` : null">
<CommonRichContent font-bold :content="getDisplayName(account)" />
<CommonRichContent font-bold :content="getDisplayName(account)" :emojis="account.emojis" />
<p op35 text-sm>
@{{ account.acct }}
</p>

View file

@ -8,7 +8,7 @@ defineProps<{
<template>
<NuxtLink :href="`/@${account.acct}`" flex gap-2 font-bold items-center>
<img :src="account.avatar" class="w-5 h-5 rounded">
<CommonRichContent :content="getDisplayName(account)" />
<AccountAvatar :account="account" w-5 h-5 />
<CommonRichContent :content="getDisplayName(account)" :emojis="account.emojis" />
</NuxtLink>
</template>

View file

@ -1,16 +1,24 @@
import type { Emoji } from 'masto'
import type { PropType } from 'vue'
import { emojisArrayToObject } from '~/composables/utils'
export default defineComponent({
props: {
content: {
type: String,
required: true,
},
emojis: {
type: Array as PropType<Emoji[]>,
},
},
setup(props) {
const serverInfos = useServerInfo(currentServer.value)
const emojiObject = emojisArrayToObject(props.emojis || [])
return () => h(
'div',
{ class: 'rich-content' },
contentToVNode(props.content, undefined, serverInfos.value?.customEmojis),
contentToVNode(props.content, undefined, emojiObject),
)
},
})

View file

@ -8,6 +8,6 @@ const { status } = defineProps<{
<template>
<div class="status-body">
<CommonRichContent :content="status.content" />
<CommonRichContent :content="status.content" :emojis="status.emojis" />
</div>
</template>

View file

@ -1,3 +1,4 @@
import { emojisArrayToObject } from './utils'
import type { ServerInfo } from '~/types'
const ServerInfoTTL = 60 * 60 * 1000 * 12 // 12 hour
@ -19,7 +20,7 @@ async function _fetchServerInfo(server: string) {
Object.assign(serverInfos.value[server], r)
}),
masto.customEmojis.fetchAll().then((r) => {
serverInfos.value[server].customEmojis = Object.fromEntries(r.map(i => [i.shortcode, i]))
serverInfos.value[server].customEmojis = emojisArrayToObject(r)
}),
])
}

View file

@ -1,3 +1,5 @@
import type { Emoji } from 'masto'
export function getDataUrlFromArr(arr: Uint8ClampedArray, w: number, h: number) {
if (typeof w === 'undefined' || typeof h === 'undefined')
w = h = Math.sqrt(arr.length / 4)
@ -14,3 +16,7 @@ export function getDataUrlFromArr(arr: Uint8ClampedArray, w: number, h: number)
return canvas.toDataURL()
}
export function emojisArrayToObject(emojis: Emoji[]) {
return Object.fromEntries(emojis.map(i => [i.shortcode, i]))
}

View file

@ -1,4 +1,6 @@
<script setup lang="ts">
import AccountAvatar from '~~/components/account/AccountAvatar.vue'
const params = useRoute().params
const id = computed(() => params.post as string)
@ -12,8 +14,8 @@ const { data: context } = await useAsyncData(`${id}-context`, () => masto.status
<StatusCard :status="comment" border="t border" pt-4 />
</template>
<StatusDetails :status="status" border="t border" pt-4 />
<div border="t border" p6 flex gap-4>
<img :src="currentUser?.account?.avatar" rounded w-10 h-10 bg-gray:10>
<div v-if="currentUser" border="t border" p6 flex gap-4>
<AccountAvatar :account="currentUser.account" w-10 h-10 />
<PublishWidget
w-full
:draft-key="`reply-${id}`"

View file

@ -1,8 +1,4 @@
<script setup lang="ts">
const props = defineProps<{
modelValue?: boolean
}>()
const params = useRoute().params
const user = $computed(() => params.user as string)