:sparklesS: Post reaction

This commit is contained in:
2025-09-20 23:28:25 +08:00
parent dd6ff13228
commit e9de02b084
10 changed files with 732 additions and 89 deletions

View File

@@ -1,33 +1,42 @@
<template>
<div
v-if="itemType == 'image'"
class="relative rounded-md overflow-hidden"
:style="`width: 100%; max-height: 800px; aspect-ratio: ${aspectRatio}`"
>
<!-- Blurhash placeholder -->
<div
v-if="blurhash"
class="absolute inset-0 z-[-1]"
:style="blurhashContainerStyle"
>
<canvas
ref="blurCanvas"
class="absolute top-0 left-0 w-full h-full"
width="32"
height="32"
<div class="relative rounded-md overflow-hidden" :style="containerStyle">
<template v-if="itemType == 'image'">
<!-- Blurhash placeholder -->
<div
v-if="blurhash"
class="absolute inset-0 z-[-1]"
:style="blurhashContainerStyle"
>
<canvas
ref="blurCanvas"
class="absolute top-0 left-0 w-full h-full"
width="32"
height="32"
/>
</div>
<!-- Main image -->
<img
:src="remoteSource"
class="w-full h-auto rounded-md transition-opacity duration-500 object-cover cursor-pointer"
:class="{ 'opacity-0': !imageLoaded && blurhash }"
@load="imageLoaded = true"
@error="imageLoaded = true"
@click="openExternally"
/>
</div>
<!-- Main image -->
<img
</template>
<audio
v-else-if="itemType == 'audio'"
class="w-full h-auto"
:src="remoteSource"
class="w-full h-auto rounded-md transition-opacity duration-500"
:class="{ 'opacity-0': !imageLoaded && blurhash }"
@load="imageLoaded = true"
@error="imageLoaded = true"
controls
/>
<video
v-else-if="itemType == 'video'"
class="w-full h-auto"
:src="remoteSource"
controls
/>
</div>
<audio v-else-if="itemType == 'audio'" :src="remoteSource" controls />
<video v-else-if="itemType == 'video'" :src="remoteSource" controls />
</template>
<script lang="ts" setup>
@@ -35,7 +44,7 @@ import { computed, ref, onMounted, watch } from "vue"
import { decode } from "blurhash"
import type { SnAttachment } from "~/types/api"
const props = defineProps<{ item: SnAttachment }>()
const props = defineProps<{ item: SnAttachment; maxHeight?: string }>()
const itemType = computed(() => props.item.mimeType.split("/")[0] ?? "unknown")
const blurhash = computed(() => props.item.fileMeta?.blur)
@@ -50,6 +59,10 @@ const aspectRatio = computed(
)
const imageLoaded = ref(false)
function openExternally() {
window.open(remoteSource.value + "?original=true", "_blank")
}
const blurCanvas = ref<HTMLCanvasElement | null>(null)
const apiBase = useSolarNetworkUrl()
@@ -61,6 +74,13 @@ const blurhashContainerStyle = computed(() => {
}
})
const containerStyle = computed(() => {
return {
"max-height": props.maxHeight ?? "720px",
"aspect-ratio": aspectRatio.value
}
})
const decodeBlurhash = () => {
if (!blurhash.value || !blurCanvas.value) return