✨ 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/react": "^11.14.0",
|
||||||
"@emotion/server": "^11.11.0",
|
"@emotion/server": "^11.11.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@mui/icons-material": "^6.3.0",
|
"@mui/icons-material": "^6.3.1",
|
||||||
"@mui/material": "^6.3.0",
|
"@mui/material": "^6.3.1",
|
||||||
"@mui/material-nextjs": "^6.3.1",
|
"@mui/material-nextjs": "^6.3.1",
|
||||||
"@mui/x-charts": "^7.23.2",
|
"@mui/x-charts": "^7.23.2",
|
||||||
"@tailwindcss/typography": "^0.5.15",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@vercel/speed-insights": "^1.1.0",
|
"@vercel/speed-insights": "^1.1.0",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
@ -37,18 +37,18 @@
|
|||||||
"remark-rehype": "^11.1.1",
|
"remark-rehype": "^11.1.1",
|
||||||
"sitemap": "^8.0.0",
|
"sitemap": "^8.0.0",
|
||||||
"unified": "^11.0.5",
|
"unified": "^11.0.5",
|
||||||
"zustand": "^5.0.2"
|
"zustand": "^5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5",
|
"typescript": "^5.7.3",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20.17.12",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19.0.4",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19.0.2",
|
||||||
"postcss": "^8",
|
"postcss": "^8.4.49",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.17",
|
||||||
"eslint": "^9",
|
"eslint": "^9.17.0",
|
||||||
"eslint-config-next": "15.1.3",
|
"eslint-config-next": "15.1.3",
|
||||||
"@eslint/eslintrc": "^3"
|
"@eslint/eslintrc": "^3.2.0"
|
||||||
},
|
},
|
||||||
"trustedDependencies": [
|
"trustedDependencies": [
|
||||||
"@vercel/speed-insights"
|
"@vercel/speed-insights"
|
||||||
|
@ -4,18 +4,26 @@ import { QuestionMark } from '@mui/icons-material'
|
|||||||
import { Link, Paper, Typography } from '@mui/material'
|
import { Link, Paper, Typography } from '@mui/material'
|
||||||
import { ComponentProps } from 'react'
|
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]) {
|
switch (item.mimetype.split('/')[0]) {
|
||||||
case 'image':
|
case 'image':
|
||||||
return (
|
return (
|
||||||
<Paper {...rest}>
|
<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>
|
</Paper>
|
||||||
)
|
)
|
||||||
case 'video':
|
case 'video':
|
||||||
return (
|
return (
|
||||||
<Paper {...rest}>
|
<Paper {...rest}>
|
||||||
<video src={getAttachmentUrl(item.rid)} controls style={{ borderRadius: '8px' }} />
|
<video src={getAttachmentUrl(item.rid)} controls style={{ borderRadius: borderRadius ?? '8px' }} />
|
||||||
</Paper>
|
</Paper>
|
||||||
)
|
)
|
||||||
default:
|
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 { SnAttachment, listAttachment } from '@/services/attachment'
|
||||||
import { getAttachmentUrl, sni } from '@/services/network'
|
import { getAttachmentUrl, sni } from '@/services/network'
|
||||||
import { SnPost } from '@/services/post'
|
import { SnPost } from '@/services/post'
|
||||||
import {
|
import { Avatar, Box, Container, Divider, Grid2 as Grid, Link, Pagination, Paper, Typography } from '@mui/material'
|
||||||
Avatar,
|
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
Container,
|
|
||||||
Divider,
|
|
||||||
Grid2 as Grid,
|
|
||||||
Link,
|
|
||||||
Pagination,
|
|
||||||
Paper,
|
|
||||||
Typography,
|
|
||||||
} from '@mui/material'
|
|
||||||
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
|
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
|
||||||
import NextLink from 'next/link'
|
import NextLink from 'next/link'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
Loading…
Reference in New Issue
Block a user