From f8af7bfd36ba32068850c1757ea2defe1ba7b80b Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 27 Dec 2025 13:07:27 +0800 Subject: [PATCH] :lipstick: Optimize the post item --- app/components/Attachment/AttachmentItem.vue | 35 +++----------------- app/components/Attachment/AttachmentList.vue | 17 ++++++---- app/components/Post/PostItem.vue | 24 ++++++++------ package.json | 3 +- 4 files changed, 30 insertions(+), 49 deletions(-) diff --git a/app/components/Attachment/AttachmentItem.vue b/app/components/Attachment/AttachmentItem.vue index c9ae295..383d519 100644 --- a/app/components/Attachment/AttachmentItem.vue +++ b/app/components/Attachment/AttachmentItem.vue @@ -50,45 +50,18 @@ import type { SnAttachment } from "~/types/api" const props = defineProps<{ item: SnAttachment original?: boolean - maxHeight?: string + maxHeight?: number }>() const itemType = computed(() => props.item.mimeType.split("/")[0] ?? "unknown") const blurhash = computed(() => props.item.fileMeta?.blur) -const imageWidth = computed(() => props.item.fileMeta?.width) const imageHeight = computed(() => props.item.fileMeta?.height) const aspectRatio = computed( () => - props.item.fileMeta?.ratio ?? - (imageWidth.value && imageHeight.value - ? imageHeight.value / imageWidth.value - : null) + props.item.fileMeta?.ratio ?? null ) 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(null) const apiBase = useSolarNetworkUrl() @@ -108,8 +81,8 @@ const blurhashContainerStyle = computed(() => { const containerStyle = computed(() => { return { - maxHeight: props.maxHeight ?? "720px", - aspectRatio: aspectRatio.value?.toString() + maxHeight: Math.min(props.maxHeight ?? 720, imageHeight.value).toString() + "px", + aspectRatio: aspectRatio.value != null ? aspectRatio.value.toString() : void 0 } }) diff --git a/app/components/Attachment/AttachmentList.vue b/app/components/Attachment/AttachmentList.vue index f28300b..f78369c 100644 --- a/app/components/Attachment/AttachmentList.vue +++ b/app/components/Attachment/AttachmentList.vue @@ -62,24 +62,28 @@ const carouselHeight = computed(() => { if (!isAllImages.value) return Math.min(400, props.maxHeight || 400) const aspectRatio = calculateAspectRatio() + if (aspectRatio == null) return null + // Use a base width of 600px for calculation, adjust height accordingly const baseWidth = 600 const calculatedHeight = Math.round(baseWidth / aspectRatio) // Respect maxHeight constraint if provided - const constrainedHeight = props.maxHeight + return props.maxHeight ? Math.min(calculatedHeight, props.maxHeight) : calculatedHeight - - return constrainedHeight }) const carouselStyle = computed(() => { if (!isAllImages.value) return {} const aspectRatio = calculateAspectRatio() + if (aspectRatio == null) { + return {} + } + const height = carouselHeight.value - const width = Math.round(height * aspectRatio) + const width = Math.round(height! * aspectRatio) return { width: `${width}px`, @@ -88,7 +92,7 @@ const carouselStyle = computed(() => { } }) -function calculateAspectRatio(): number { +function calculateAspectRatio(): number | null { const ratios: number[] = [] // Collect all valid ratios @@ -110,8 +114,7 @@ function calculateAspectRatio(): number { } if (ratios.length === 0) { - // Default to 4:3 aspect ratio when no valid ratios found - return 4 / 3 + return null } if (ratios.length === 1 && ratios[0]) { diff --git a/app/components/Post/PostItem.vue b/app/components/Post/PostItem.vue index de12bae..331b603 100644 --- a/app/components/Post/PostItem.vue +++ b/app/components/Post/PostItem.vue @@ -86,14 +86,19 @@ -
- +
+ + + {{ props.item.upvotes }} + + + + {{ props.item.downvotes }} +
@@ -104,7 +109,7 @@ import { ref, watch } from "vue" import { useMarkdownProcessor } from "~/composables/useMarkdownProcessor" import type { SnPost } from "~/types/api" import { useIntersectionObserver } from "@vueuse/core" -import { ForwardIcon, ReplyIcon } from "lucide-vue-next" +import { ForwardIcon, ReplyIcon, ArrowUpIcon, ArrowDownIcon } from "lucide-vue-next" const props = withDefaults( defineProps<{ @@ -133,7 +138,6 @@ function handleReaction(symbol: string, attitude: number, delta: number) { } function handleReplyReaction( - postId: string, symbol: string, attitude: number, delta: number diff --git a/package.json b/package.json index 65c3b16..feee428 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "cfturnstile-vue3": "^2.0.0", "eslint": "^9.39.1", "highlightjs": "^9.16.2", + "html2canvas": "^1.4.1", "katex": "^0.16.25", "lucide-vue-next": "^0.555.0", "luxon": "^3.7.2", @@ -52,4 +53,4 @@ "unplugin-auto-import": "^20.3.0", "unplugin-vue-components": "^30.0.0" } -} \ No newline at end of file +}