Rewind renders most of the data

This commit is contained in:
2025-12-27 02:22:19 +08:00
parent df44c4525e
commit 9d6eb5c378
8 changed files with 695 additions and 327 deletions

View File

@@ -0,0 +1,97 @@
<template>
<div v-if="loading" class="flex justify-center items-center py-4">
<n-spin size="large" />
</div>
<div v-else-if="error" class="text-red-500 text-center py-4">
{{ error }}
</div>
<post-item
v-else-if="post"
:item="post"
:compact="compact"
:flat="flat"
:slim="slim"
:show-referenced="showReferenced"
@react="handleReaction"
/>
</template>
<script lang="ts" setup>
import { ref, watch, onMounted } from "vue"
import { useSolarNetwork } from "~/composables/useSolarNetwork"
import type { SnPost } from "~/types/api"
import PostItem from "./PostItem.vue"
import { keysToCamel } from "~/utils/transformKeys"
const props = withDefaults(
defineProps<{
postId: string
showReferenced?: boolean
compact?: boolean
flat?: boolean
slim?: boolean
}>(),
{ showReferenced: true, compact: false, flat: false, slim: false }
)
const emit = defineEmits<{
react: [symbol: string, attitude: number, delta: number]
loaded: [post: SnPost]
}>()
const api = useSolarNetwork()
const post = ref<SnPost | null>(null)
const loading = ref(false)
const error = ref<string | null>(null)
const fetchPost = async () => {
if (!props.postId) {
error.value = "No post ID provided"
return
}
try {
loading.value = true
error.value = null
const response = await api<SnPost>(`/sphere/posts/${props.postId}`, {
method: "GET",
onResponse({ response }) {
if (response._data) {
response._data = keysToCamel(response._data)
}
}
})
post.value = response
emit("loaded", response)
} catch (err) {
console.error("Error fetching post:", err)
error.value = err instanceof Error ? err.message : "Failed to fetch post"
} finally {
loading.value = false
}
}
const handleReaction = (symbol: string, attitude: number, delta: number) => {
emit("react", symbol, attitude, delta)
}
// Watch for postId changes and refetch
watch(
() => props.postId,
(newId) => {
if (newId) {
fetchPost()
}
},
{ immediate: true }
)
// Initial fetch on mount
onMounted(() => {
if (props.postId) {
fetchPost()
}
})
</script>

View File

@@ -0,0 +1,41 @@
<template>
<n-card>
<div class="flex flex-col justify-center gap-4">
<img
v-if="userBackground"
:src="userBackground"
style="aspect-ratio: 16/7"
class="rounded-xl"
/>
<div class="flex items-center gap-4">
<n-avatar :src="userPicture" />
<div class="grow">
<div class="font-bold text-lg">{{ data.nick }}</div>
<div class="text-sm opacity-80">@{{ data.name }}</div>
</div>
<div><slot name="suffix" /></div>
</div>
</div>
</n-card>
</template>
<script setup lang="ts">
import type { SnAccount } from "~/types/api"
const props = defineProps<{ data: SnAccount }>()
const _ = defineSlots<{ suffix(): unknown }>()
const apiBase = useSolarNetworkUrl()
const userPicture = computed(() => {
return props.data.profile.picture
? `${apiBase}/drive/files/${props.data.profile.picture.id}`
: undefined
})
const userBackground = computed(() => {
return props.data.profile.background
? `${apiBase}/drive/files/${props.data.profile.background.id}`
: undefined
})
</script>

View File

@@ -0,0 +1,41 @@
<template>
<n-card>
<div class="flex flex-col justify-center gap-4">
<img
v-if="userBackground"
:src="userBackground"
style="aspect-ratio: 16/7"
class="rounded-xl"
/>
<div class="flex items-center gap-4">
<n-avatar :src="userPicture" />
<div class="grow">
<div class="font-bold text-lg">{{ data.nick }}</div>
<div class="text-sm opacity-80">@{{ data.name }}</div>
</div>
<div><slot name="suffix" /></div>
</div>
</div>
</n-card>
</template>
<script setup lang="ts">
import type { SnPublisher } from "~/types/api"
const props = defineProps<{ data: SnPublisher }>()
const _ = defineSlots<{ suffix(): unknown }>()
const apiBase = useSolarNetworkUrl()
const userPicture = computed(() => {
return props.data.picture
? `${apiBase}/drive/files/${props.data.picture.id}`
: undefined
})
const userBackground = computed(() => {
return props.data.background
? `${apiBase}/drive/files/${props.data.background.id}`
: undefined
})
</script>