💄 Optimize the post item
This commit is contained in:
@@ -50,45 +50,18 @@ import type { SnAttachment } from "~/types/api"
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
item: SnAttachment
|
item: SnAttachment
|
||||||
original?: boolean
|
original?: boolean
|
||||||
maxHeight?: string
|
maxHeight?: number
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const itemType = computed(() => props.item.mimeType.split("/")[0] ?? "unknown")
|
const itemType = computed(() => props.item.mimeType.split("/")[0] ?? "unknown")
|
||||||
const blurhash = computed(() => props.item.fileMeta?.blur)
|
const blurhash = computed(() => props.item.fileMeta?.blur)
|
||||||
const imageWidth = computed(() => props.item.fileMeta?.width)
|
|
||||||
const imageHeight = computed(() => props.item.fileMeta?.height)
|
const imageHeight = computed(() => props.item.fileMeta?.height)
|
||||||
const aspectRatio = computed(
|
const aspectRatio = computed(
|
||||||
() =>
|
() =>
|
||||||
props.item.fileMeta?.ratio ??
|
props.item.fileMeta?.ratio ?? null
|
||||||
(imageWidth.value && imageHeight.value
|
|
||||||
? imageHeight.value / imageWidth.value
|
|
||||||
: null)
|
|
||||||
)
|
)
|
||||||
const imageLoaded = ref(false)
|
const imageLoaded = ref(false)
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
function openExternally() {
|
|
||||||
// Capture image position for transition
|
|
||||||
const img = event?.target as HTMLImageElement
|
|
||||||
if (img && itemType.value === "image") {
|
|
||||||
const rect = img.getBoundingClientRect()
|
|
||||||
const transitionData = {
|
|
||||||
src: remoteSource.value,
|
|
||||||
x: rect.left,
|
|
||||||
y: rect.top,
|
|
||||||
width: rect.width,
|
|
||||||
height: rect.height,
|
|
||||||
aspectRatio: aspectRatio.value == null ? 0 : aspectRatio.value
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store transition data
|
|
||||||
sessionStorage.setItem("imageTransition", JSON.stringify(transitionData))
|
|
||||||
}
|
|
||||||
|
|
||||||
router.push("/files/" + props.item.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
const blurCanvas = ref<HTMLCanvasElement | null>(null)
|
const blurCanvas = ref<HTMLCanvasElement | null>(null)
|
||||||
|
|
||||||
const apiBase = useSolarNetworkUrl()
|
const apiBase = useSolarNetworkUrl()
|
||||||
@@ -108,8 +81,8 @@ const blurhashContainerStyle = computed(() => {
|
|||||||
|
|
||||||
const containerStyle = computed(() => {
|
const containerStyle = computed(() => {
|
||||||
return {
|
return {
|
||||||
maxHeight: props.maxHeight ?? "720px",
|
maxHeight: Math.min(props.maxHeight ?? 720, imageHeight.value).toString() + "px",
|
||||||
aspectRatio: aspectRatio.value?.toString()
|
aspectRatio: aspectRatio.value != null ? aspectRatio.value.toString() : void 0
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -62,24 +62,28 @@ const carouselHeight = computed(() => {
|
|||||||
if (!isAllImages.value) return Math.min(400, props.maxHeight || 400)
|
if (!isAllImages.value) return Math.min(400, props.maxHeight || 400)
|
||||||
|
|
||||||
const aspectRatio = calculateAspectRatio()
|
const aspectRatio = calculateAspectRatio()
|
||||||
|
if (aspectRatio == null) return null
|
||||||
|
|
||||||
// Use a base width of 600px for calculation, adjust height accordingly
|
// Use a base width of 600px for calculation, adjust height accordingly
|
||||||
const baseWidth = 600
|
const baseWidth = 600
|
||||||
const calculatedHeight = Math.round(baseWidth / aspectRatio)
|
const calculatedHeight = Math.round(baseWidth / aspectRatio)
|
||||||
|
|
||||||
// Respect maxHeight constraint if provided
|
// Respect maxHeight constraint if provided
|
||||||
const constrainedHeight = props.maxHeight
|
return props.maxHeight
|
||||||
? Math.min(calculatedHeight, props.maxHeight)
|
? Math.min(calculatedHeight, props.maxHeight)
|
||||||
: calculatedHeight
|
: calculatedHeight
|
||||||
|
|
||||||
return constrainedHeight
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const carouselStyle = computed(() => {
|
const carouselStyle = computed(() => {
|
||||||
if (!isAllImages.value) return {}
|
if (!isAllImages.value) return {}
|
||||||
|
|
||||||
const aspectRatio = calculateAspectRatio()
|
const aspectRatio = calculateAspectRatio()
|
||||||
|
if (aspectRatio == null) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
const height = carouselHeight.value
|
const height = carouselHeight.value
|
||||||
const width = Math.round(height * aspectRatio)
|
const width = Math.round(height! * aspectRatio)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
width: `${width}px`,
|
width: `${width}px`,
|
||||||
@@ -88,7 +92,7 @@ const carouselStyle = computed(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function calculateAspectRatio(): number {
|
function calculateAspectRatio(): number | null {
|
||||||
const ratios: number[] = []
|
const ratios: number[] = []
|
||||||
|
|
||||||
// Collect all valid ratios
|
// Collect all valid ratios
|
||||||
@@ -110,8 +114,7 @@ function calculateAspectRatio(): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ratios.length === 0) {
|
if (ratios.length === 0) {
|
||||||
// Default to 4:3 aspect ratio when no valid ratios found
|
return null
|
||||||
return 4 / 3
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ratios.length === 1 && ratios[0]) {
|
if (ratios.length === 1 && ratios[0]) {
|
||||||
|
|||||||
@@ -86,14 +86,19 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Post Reactions -->
|
<!-- Post Reactions -->
|
||||||
<div v-if="!compact" @click.stop>
|
<div class="flex gap-2">
|
||||||
<post-reaction-list
|
<n-tag type="success">
|
||||||
:parent-id="props.item.id"
|
<template #icon>
|
||||||
:reactions="props.item.reactionsCount"
|
<n-icon :component="ArrowUpIcon" />
|
||||||
:reactions-made="props.item.reactionsMade"
|
</template>
|
||||||
:can-react="true"
|
{{ props.item.upvotes }}
|
||||||
@react="handleReaction"
|
</n-tag>
|
||||||
/>
|
<n-tag type="error">
|
||||||
|
<template #icon>
|
||||||
|
<n-icon :component="ArrowDownIcon" />
|
||||||
|
</template>
|
||||||
|
{{ props.item.downvotes }}
|
||||||
|
</n-tag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</n-card>
|
</n-card>
|
||||||
@@ -104,7 +109,7 @@ import { ref, watch } from "vue"
|
|||||||
import { useMarkdownProcessor } from "~/composables/useMarkdownProcessor"
|
import { useMarkdownProcessor } from "~/composables/useMarkdownProcessor"
|
||||||
import type { SnPost } from "~/types/api"
|
import type { SnPost } from "~/types/api"
|
||||||
import { useIntersectionObserver } from "@vueuse/core"
|
import { useIntersectionObserver } from "@vueuse/core"
|
||||||
import { ForwardIcon, ReplyIcon } from "lucide-vue-next"
|
import { ForwardIcon, ReplyIcon, ArrowUpIcon, ArrowDownIcon } from "lucide-vue-next"
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@@ -133,7 +138,6 @@ function handleReaction(symbol: string, attitude: number, delta: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleReplyReaction(
|
function handleReplyReaction(
|
||||||
postId: string,
|
|
||||||
symbol: string,
|
symbol: string,
|
||||||
attitude: number,
|
attitude: number,
|
||||||
delta: number
|
delta: number
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"cfturnstile-vue3": "^2.0.0",
|
"cfturnstile-vue3": "^2.0.0",
|
||||||
"eslint": "^9.39.1",
|
"eslint": "^9.39.1",
|
||||||
"highlightjs": "^9.16.2",
|
"highlightjs": "^9.16.2",
|
||||||
|
"html2canvas": "^1.4.1",
|
||||||
"katex": "^0.16.25",
|
"katex": "^0.16.25",
|
||||||
"lucide-vue-next": "^0.555.0",
|
"lucide-vue-next": "^0.555.0",
|
||||||
"luxon": "^3.7.2",
|
"luxon": "^3.7.2",
|
||||||
@@ -52,4 +53,4 @@
|
|||||||
"unplugin-auto-import": "^20.3.0",
|
"unplugin-auto-import": "^20.3.0",
|
||||||
"unplugin-vue-components": "^30.0.0"
|
"unplugin-vue-components": "^30.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user