forked from Mirrors/elk
feat: improve status image quality
This commit is contained in:
parent
a36a26d745
commit
cab3ed4ad4
2 changed files with 56 additions and 2 deletions
|
@ -8,11 +8,20 @@ const props = defineProps<{
|
||||||
/** When it is root card in the list, not appear as a child card */
|
/** When it is root card in the list, not appear as a child card */
|
||||||
root?: boolean
|
root?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
const image = ref(props.card.image)
|
||||||
const alt = $computed(() => `${props.card.title} - ${props.card.title}`)
|
const alt = $computed(() => `${props.card.title} - ${props.card.title}`)
|
||||||
const isSquare = $computed(() => props.smallPictureOnly || props.card.width === props.card.height)
|
const isSquare = $computed(() => props.smallPictureOnly || props.card.width === props.card.height)
|
||||||
const description = $computed(() => props.card.description ? props.card.description : new URL(props.card.url).hostname)
|
const description = $computed(() => props.card.description ? props.card.description : new URL(props.card.url).hostname)
|
||||||
|
|
||||||
// TODO: handle card.type: 'photo' | 'video' | 'rich';
|
// TODO: handle card.type: 'photo' | 'video' | 'rich';
|
||||||
|
|
||||||
|
$fetch<string>('/api/og-image', {
|
||||||
|
params: { cardUrl: props.card.url },
|
||||||
|
}).then((ogImageUrl) => {
|
||||||
|
// Only override if ogImageUrl is not empty
|
||||||
|
if (ogImageUrl)
|
||||||
|
image.value = ogImageUrl
|
||||||
|
}).catch(() => {})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -29,7 +38,7 @@ const description = $computed(() => props.card.description ? props.card.descript
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="card.image"
|
v-if="image"
|
||||||
flex flex-col
|
flex flex-col
|
||||||
display-block of-hidden
|
display-block of-hidden
|
||||||
|
|
||||||
|
@ -42,7 +51,7 @@ const description = $computed(() => props.card.description ? props.card.descript
|
||||||
>
|
>
|
||||||
<CommonBlurhash
|
<CommonBlurhash
|
||||||
:blurhash="card.blurhash"
|
:blurhash="card.blurhash"
|
||||||
:src="card.image"
|
:src="image"
|
||||||
:width="card.width"
|
:width="card.width"
|
||||||
:height="card.height"
|
:height="card.height"
|
||||||
:alt="alt"
|
:alt="alt"
|
||||||
|
|
45
server/api/og-image.ts
Normal file
45
server/api/og-image.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
const inMemoryCache = new Map<string, { url: string; lastUsed: number }>()
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const { cardUrl } = getQuery(event)
|
||||||
|
|
||||||
|
if (!cardUrl) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: 422,
|
||||||
|
statusMessage: 'Missing cardUrl.',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof cardUrl !== 'string') {
|
||||||
|
throw createError({
|
||||||
|
statusCode: 422,
|
||||||
|
statusMessage: 'cardUrl must be string.',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inMemoryCache.has(cardUrl)) {
|
||||||
|
const { url } = inMemoryCache.get(cardUrl)!
|
||||||
|
await send(event, url)
|
||||||
|
|
||||||
|
// Remove oldest entry if cache is too big
|
||||||
|
if (inMemoryCache.size > 5000) {
|
||||||
|
const oldestEntry = [...inMemoryCache.entries()].reduce(
|
||||||
|
(acc, [key, { lastUsed }]) => (lastUsed < acc.lastUsed ? { key, lastUsed } : acc),
|
||||||
|
{ key: '', lastUsed: Infinity },
|
||||||
|
)
|
||||||
|
inMemoryCache.delete(oldestEntry.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await $fetch<string>(cardUrl)
|
||||||
|
let ogImageUrl: string | null | undefined = null
|
||||||
|
|
||||||
|
const match = result.match(/<meta property="og:image" content="([^"]+)" \/>/)
|
||||||
|
ogImageUrl = match?.[1] ?? ''
|
||||||
|
|
||||||
|
inMemoryCache.set(cardUrl, { url: ogImageUrl, lastUsed: Date.now() })
|
||||||
|
|
||||||
|
await send(event, ogImageUrl)
|
||||||
|
})
|
Loading…
Reference in a new issue