From e123aabf0ff5528f526eff82b3c44f784f00347a Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 4 Jan 2025 13:27:33 +0800 Subject: [PATCH] :sparkles: Post list --- src/components/attachments/AttachmentItem.tsx | 9 +- src/pages/_app.tsx | 2 +- src/pages/auth/login.tsx | 2 +- src/pages/posts/[...id].tsx | 2 +- src/pages/posts/index.tsx | 135 ++++++++++++++++++ 5 files changed, 143 insertions(+), 7 deletions(-) create mode 100644 src/pages/posts/index.tsx diff --git a/src/components/attachments/AttachmentItem.tsx b/src/components/attachments/AttachmentItem.tsx index 63181a7..a4e1530 100644 --- a/src/components/attachments/AttachmentItem.tsx +++ b/src/components/attachments/AttachmentItem.tsx @@ -2,24 +2,25 @@ import { SnAttachment } from '@/services/attachment' import { getAttachmentUrl } from '@/services/network' import { QuestionMark } from '@mui/icons-material' import { Link, Paper, Typography } from '@mui/material' +import { ComponentProps } from 'react' -export function AttachmentItem({ item }: { item: SnAttachment }) { +export function AttachmentItem({ item, ...rest }: { item: SnAttachment } & ComponentProps<'div'>) { switch (item.mimetype.split('/')[0]) { case 'image': return ( - + {item.alt} ) case 'video': return ( - + ) default: return ( - + Unknown {item.name} diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 877363b..8cda8ad 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -44,7 +44,7 @@ export default function App({ Component, pageProps }: AppProps) { - + diff --git a/src/pages/auth/login.tsx b/src/pages/auth/login.tsx index 21444be..ea4e841 100644 --- a/src/pages/auth/login.tsx +++ b/src/pages/auth/login.tsx @@ -83,7 +83,7 @@ export default function Login() { sx={{ display: 'grid', placeItems: 'center', - height: '100%', + height: 'calc(100vh - 64px)', textAlign: 'center', }} > diff --git a/src/pages/posts/[...id].tsx b/src/pages/posts/[...id].tsx index ce5a879..b1d807d 100644 --- a/src/pages/posts/[...id].tsx +++ b/src/pages/posts/[...id].tsx @@ -216,7 +216,7 @@ export default function Post({ post, attachments }: InferGetServerSidePropsType< }} > {attachments.map((a) => ( - + ))} diff --git a/src/pages/posts/index.tsx b/src/pages/posts/index.tsx new file mode 100644 index 0000000..86f0a58 --- /dev/null +++ b/src/pages/posts/index.tsx @@ -0,0 +1,135 @@ +import { AttachmentItem } from '@/components/attachments/AttachmentItem' +import { SnAttachment, listAttachment } from '@/services/attachment' +import { getAttachmentUrl, sni } from '@/services/network' +import { SnPost } from '@/services/post' +import { Avatar, Box, Container, Divider, Grid2 as Grid, Pagination, Paper, Typography } from '@mui/material' +import { GetServerSideProps, InferGetServerSidePropsType } from 'next' +import Link from 'next/link' +import { useRouter } from 'next/router' +import rehypeSanitize from 'rehype-sanitize' +import rehypeStringify from 'rehype-stringify' +import remarkBreaks from 'remark-breaks' +import remarkParse from 'remark-parse' +import remarkRehype from 'remark-rehype' +import { unified } from 'unified' + +type SnPostWithAttachments = SnPost & { attachments: SnAttachment[] } + +export const getServerSideProps = (async (context) => { + let page: number = parseInt(context.query.page as string) + if (isNaN(page)) page = 1 + + const countPerPage = 10 + + try { + const { data: resp } = await sni.get<{ data: SnPost[]; count: number }>('/cgi/co/posts', { + params: { + take: countPerPage, + offset: (page - 1) * countPerPage, + }, + }) + + let posts: SnPostWithAttachments[] = resp.data as SnPostWithAttachments[] + for (let idx = 0; idx < posts.length; idx++) { + let post = posts[idx] + if (post.body.content) { + let processor: any = unified().use(remarkParse) + if (post.type != 'article') { + processor = processor.use(remarkBreaks) + } + const out = await processor + .use(remarkRehype) + .use(rehypeSanitize) + .use(rehypeStringify) + .process(post.body.content) + post.body.rawContent = post.body.content + post.body.content = String(out) + } + if (post.body.attachments) { + post.attachments = await listAttachment(post.body.attachments) + } + posts[idx] = post + } + + return { props: { posts, page, pages: Math.ceil(resp.count / countPerPage) } } + } catch (err) { + console.error(err) + return { + notFound: true, + } + } +}) satisfies GetServerSideProps<{ posts: SnPostWithAttachments[]; page: number; pages: number }> + +export default function PostList({ posts, page, pages }: InferGetServerSidePropsType) { + const router = useRouter() + + return ( + + {posts.map((p) => ( + + + + + + {p.publisher.nick} + + @{p.publisher.name} + + + + + + + + + {(p.body.title || p.body.content) && ( + + {p.body.title && {p.body.title}} + {p.body.description && {p.body.description}} + + )} + + + Published at {new Date(p.publishedAt ?? p.createdAt).toLocaleString()} + + + + + + + + {p.body.content &&
} + + + + + {p.attachments && ( + + {p.attachments.map((a) => ( + + + + ))} + + )} + + ))} + + router.push('/posts?page=' + page)} + /> + + ) +}