♻️ Refactor post list

This commit is contained in:
LittleSheep 2024-08-17 00:43:08 +08:00
parent 4a51a85d9c
commit 2b9601640b
11 changed files with 136 additions and 29 deletions

View File

@ -27,7 +27,7 @@
</article>
<v-card v-if="post.body?.attachments?.length > 0" class="mb-5">
<attachment-carousel :attachments="post.body?.attachments" />
<attachment-carousel :no-clickable-attachment="props.noClickableAttachment" :attachments="post.body?.attachments" />
</v-card>
<div class="text-sm flex flex-col">
@ -53,6 +53,6 @@
</template>
<script setup lang="ts">
const props = defineProps<{ post: any, forceShowContent?: boolean }>()
const props = defineProps<{ post: any, forceShowContent?: boolean, noClickableAttachment?: boolean }>()
const config = useRuntimeConfig()
</script>

40
components/PostList.vue Normal file
View File

@ -0,0 +1,40 @@
<template>
<v-infinite-scroll :items="posts" :onLoad="loadPost">
<template v-for="item in posts" :key="item">
<post-item :post="item" no-clickable-attachment />
</template>
</v-infinite-scroll>
</template>
<script setup lang="ts">
const props = defineProps<{ author?: string, realmId?: number }>()
const config = useRuntimeConfig()
const posts = ref<any[]>([])
async function loadPost({ done }: any) {
const searchQueries = new URLSearchParams({
take: (10).toString(),
offset: posts.value.length.toString(),
})
if (props.author) {
searchQueries.set("author", props.author)
}
if (props.realmId) {
searchQueries.set("realmId", props.realmId.toString())
}
const res = await fetch(`${config.public.solarNetworkApi}/cgi/interactive/posts?` + searchQueries)
const result = await res.json()
if (result.data.length > 0) {
posts.value.push(...result.data)
done("ok")
} else {
done("empty")
}
}
</script>

View File

@ -0,0 +1,32 @@
<template>
<v-infinite-scroll :items="posts" :onLoad="loadPost">
<template v-for="item in posts" :key="item">
<post-item :post="item" no-clickable-attachment />
</template>
</v-infinite-scroll>
</template>
<script setup lang="ts">
const props = defineProps<{ postId: number }>()
const config = useRuntimeConfig()
const posts = ref<any[]>([])
async function loadPost({ done }: any) {
const searchQueries = new URLSearchParams({
take: (10).toString(),
offset: posts.value.length.toString(),
})
const res = await fetch(`${config.public.solarNetworkApi}/cgi/interactive/posts/${props.postId}/replies?` + searchQueries)
const result = await res.json()
if (result.data.length > 0) {
posts.value.push(...result.data)
done("ok")
} else {
done("empty")
}
}
</script>

View File

@ -7,13 +7,19 @@
height="auto"
>
<v-carousel-item v-for="item in metadata" class="fill-height">
<attachment-renderer :item="item" />
<nuxt-link v-if="item.mimetype.split('/')[0] == 'image' && !props.noClickableAttachment"
:to="`/gallery/${item.id}`">
<attachment-renderer :item="item" />
</nuxt-link>
<div v-else>
<attachment-renderer :item="item" />
</div>
</v-carousel-item>
</v-carousel>
</template>
<script setup lang="ts">
const props = defineProps<{ attachments: number[] }>()
const props = defineProps<{ attachments: number[], noClickableAttachment?: boolean }>()
const emits = defineEmits(["update:metadata"])
const config = useRuntimeConfig()

View File

@ -20,7 +20,7 @@
<v-img v-else-if="item.mimetype.split('/')[0] == 'image'" :src="getAttachmentUrl(item.id)" :alt="item.alt"
class="w-full h-full" cover />
<video v-else-if="item.mimetype.split('/')[0] == 'video'" :src="getAttachmentUrl(item.id)" class="w-full h-full"
controls />
controls @click.stop />
<v-sheet v-else color="rgba(0, 0, 0, .4)" height="calc(100% + 24px)" class="p-5">
<v-row class="fill-height" align="center" justify="center">
<v-col class="text-center">

View File

@ -6,6 +6,8 @@
"navActivityCaption": "Explore our official recent activities.",
"navGallery": "Gallery",
"navGalleryCaption": "Explore files that uploaded by Solar Network users.",
"navPosts": "Posts",
"navPostsCaption": "Explore posts that posted by Solar Network users.",
"indexIntroduce": "An energetic software company that create wonderful software which everyone love.",
"indexProductListHint": "See some of our products just there",
"indexActivities": "Activities",
@ -54,5 +56,7 @@
"callbackHint": "You need to sign in before access that page. After you signed in, you will be redirected to:",
"lastUpdatedAt": "Last updated at {0}",
"learnMore": "Learn more",
"open": "Open"
"open": "Open",
"postReplies": "Replies",
"postRepliesCaption": "All replies of this post"
}

View File

@ -6,6 +6,8 @@
"navActivityCaption": "了解我们官方近期的活动。",
"navGallery": "相簿",
"navGalleryCaption": "探索整个 Solar Network 上的文件。",
"navPosts": "帖子",
"navPostsCaption": "探索整个 Solar Network 上的帖子。",
"indexIntroduce": "一家充满活力的软件公司,创造了人人喜爱的精彩软件。",
"indexProductListHint": "在这里看看我们的一些产品",
"indexActivities": "动态",
@ -54,5 +56,7 @@
"approve": "批准",
"lastUpdatedAt": "最后更新于 {0}",
"learnMore": "了解更多",
"open": "打开"
"open": "打开",
"postReplies": "回复",
"postRepliesCaption": "该帖子的全部回复"
}

View File

@ -5,11 +5,7 @@
<span>{{ t("navActivityCaption") }}</span>
</div>
<v-infinite-scroll :items="items" :onLoad="load">
<template v-for="item in items" :key="item">
<post-item :post="item" />
</template>
</v-infinite-scroll>
<post-list :realm-id="config.public.solarRealmId" />
</v-container>
</template>
@ -29,17 +25,6 @@ useSeoMeta({
})
const config = useRuntimeConfig()
const items = ref<any[]>([])
async function load({ done }: any) {
const res = await fetch(`${config.public.solarNetworkApi}/cgi/interactive/posts?take=10&offset=${items.value.length}&realmId=${config.public.solarRealmId}`)
const result = await res.json()
items.value.push(...result.data)
done("ok")
}
</script>
<style scoped>

View File

@ -45,10 +45,16 @@
<span v-for="tag in post.tags">#{{ tag.alias }}</span>
</div>
<div class="text-xs text-grey flex flex-col">
<div class="text-xs text-grey flex flex-col mb-5">
<span>Solar Network Post Web Preview</span>
<span>To get full view of this post, open it on <a class="underline" :href="externalOpenLink">Solian</a></span>
</div>
<div v-if="post.metric.reply_count" class="mb-5">
<v-card variant="outlined" :title="t('postReplies')" :subtitle="t('postRepliesCaption')">
<post-reply-list class="mt-[-20px] mx-[-1ch] mb-3" :post-id="post.id" />
</v-card>
</div>
</v-container>
</template>
@ -60,6 +66,8 @@ const attachments = ref<any[]>([])
const firstImage = ref<string | null>()
const firstVideo = ref<string | null>()
const { t } = useI18n()
const { data: post } = await useFetch<any>(`${config.public.solarNetworkApi}/cgi/interactive/posts/${route.params.id}`)
if (!post.value) {

32
pages/posts/index.vue Normal file
View File

@ -0,0 +1,32 @@
<template>
<v-container class="content-container mx-auto">
<div class="my-3 mx-[3.5ch]">
<h1 class="text-2xl">{{ t("navPosts") }}</h1>
<span>{{ t("navPostsCaption") }}</span>
</div>
<post-list />
</v-container>
</template>
<script setup lang="ts">
const { t } = useI18n()
useHead({
title: t("navActivity"),
})
useSeoMeta({
title: t("navActivity"),
ogTitle: t("navActivity"),
description: t("navActivityCaption"),
ogDescription: t("navActivityCaption"),
ogType: "website",
})
</script>
<style scoped>
.content-container {
max-width: 70ch !important;
}
</style>

View File

@ -24,11 +24,7 @@
</div>
</div>
<v-infinite-scroll :items="posts" :onLoad="loadPost">
<template v-for="item in posts" :key="item">
<post-item :post="item" />
</template>
</v-infinite-scroll>
<post-list v-if="account" :author="account.name" />
</v-container>
</template>