✨ Attachment list (Gallery)
This commit is contained in:
parent
94ae812822
commit
eaef7f304c
24
package.json
24
package.json
@ -13,11 +13,11 @@
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/server": "^11.11.0",
|
||||
"@emotion/styled": "^11.14.0",
|
||||
"@mui/icons-material": "^6.3.0",
|
||||
"@mui/material": "^6.3.0",
|
||||
"@mui/icons-material": "^6.3.1",
|
||||
"@mui/material": "^6.3.1",
|
||||
"@mui/material-nextjs": "^6.3.1",
|
||||
"@mui/x-charts": "^7.23.2",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@vercel/speed-insights": "^1.1.0",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.7.9",
|
||||
@ -37,18 +37,18 @@
|
||||
"remark-rehype": "^11.1.1",
|
||||
"sitemap": "^8.0.0",
|
||||
"unified": "^11.0.5",
|
||||
"zustand": "^5.0.2"
|
||||
"zustand": "^5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"postcss": "^8",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"eslint": "^9",
|
||||
"typescript": "^5.7.3",
|
||||
"@types/node": "^20.17.12",
|
||||
"@types/react": "^19.0.4",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"postcss": "^8.4.49",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"eslint": "^9.17.0",
|
||||
"eslint-config-next": "15.1.3",
|
||||
"@eslint/eslintrc": "^3"
|
||||
"@eslint/eslintrc": "^3.2.0"
|
||||
},
|
||||
"trustedDependencies": [
|
||||
"@vercel/speed-insights"
|
||||
|
@ -4,18 +4,26 @@ import { QuestionMark } from '@mui/icons-material'
|
||||
import { Link, Paper, Typography } from '@mui/material'
|
||||
import { ComponentProps } from 'react'
|
||||
|
||||
export function AttachmentItem({ item, ...rest }: { item: SnAttachment } & ComponentProps<'div'>) {
|
||||
export function AttachmentItem({
|
||||
item,
|
||||
borderRadius,
|
||||
...rest
|
||||
}: { item: SnAttachment; borderRadius?: string } & ComponentProps<'div'>) {
|
||||
switch (item.mimetype.split('/')[0]) {
|
||||
case 'image':
|
||||
return (
|
||||
<Paper {...rest}>
|
||||
<img src={getAttachmentUrl(item.rid)} alt={item.alt} style={{ objectFit: 'cover', borderRadius: '8px' }} />
|
||||
<img
|
||||
src={getAttachmentUrl(item.rid)}
|
||||
alt={item.alt}
|
||||
style={{ objectFit: 'cover', borderRadius: borderRadius ?? '8px' }}
|
||||
/>
|
||||
</Paper>
|
||||
)
|
||||
case 'video':
|
||||
return (
|
||||
<Paper {...rest}>
|
||||
<video src={getAttachmentUrl(item.rid)} controls style={{ borderRadius: '8px' }} />
|
||||
<video src={getAttachmentUrl(item.rid)} controls style={{ borderRadius: borderRadius ?? '8px' }} />
|
||||
</Paper>
|
||||
)
|
||||
default:
|
||||
|
62
src/pages/attachments/index.tsx
Normal file
62
src/pages/attachments/index.tsx
Normal file
@ -0,0 +1,62 @@
|
||||
import { AttachmentItem } from '@/components/attachments/AttachmentItem'
|
||||
import { SnAttachment } from '@/services/attachment'
|
||||
import { sni } from '@/services/network'
|
||||
import { Box, ImageList, ImageListItem, Pagination, useMediaQuery, useTheme } from '@mui/material'
|
||||
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
let page: number = parseInt(context.query.page as string)
|
||||
if (isNaN(page)) page = 1
|
||||
|
||||
const countPerPage = 20
|
||||
|
||||
const { data: resp } = await sni.get<{ data: SnAttachment[]; count: number }>('/cgi/uc/attachments', {
|
||||
params: {
|
||||
take: countPerPage,
|
||||
offset: (page - 1) * countPerPage,
|
||||
},
|
||||
})
|
||||
|
||||
const attachments = resp.data
|
||||
|
||||
return { props: { attachments, page, pages: Math.ceil(resp.count / countPerPage) } }
|
||||
}
|
||||
|
||||
export default function AttachmentsPage({
|
||||
attachments,
|
||||
page,
|
||||
pages,
|
||||
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||
const router = useRouter()
|
||||
const theme = useTheme()
|
||||
const breakpoints = useMediaQuery(theme.breakpoints.up('md'))
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<ImageList variant="masonry" cols={breakpoints ? 3 : 2} gap={8} sx={{ mx: 2 }}>
|
||||
{attachments.map((item: SnAttachment) => (
|
||||
<ImageListItem key={item.rid}>
|
||||
<AttachmentItem item={item} borderRadius="0" />
|
||||
</ImageListItem>
|
||||
))}
|
||||
</ImageList>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
mx: 'auto',
|
||||
mb: 5,
|
||||
mt: 3,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
placeItems: 'center',
|
||||
gap: 1.5,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
<Pagination count={pages} page={page} onChange={(_, page) => router.push('/attachments?page=' + page)} />
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
@ -2,18 +2,7 @@ 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,
|
||||
Button,
|
||||
Container,
|
||||
Divider,
|
||||
Grid2 as Grid,
|
||||
Link,
|
||||
Pagination,
|
||||
Paper,
|
||||
Typography,
|
||||
} from '@mui/material'
|
||||
import { Avatar, Box, Container, Divider, Grid2 as Grid, Link, Pagination, Paper, Typography } from '@mui/material'
|
||||
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
|
||||
import NextLink from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
|
Loading…
Reference in New Issue
Block a user