Compare commits

..

No commits in common. "eaef7f304ced067e4bda1e090d8baa46af03e9bf" and "92f6f0d2a8b074fd802d87a234e5f5eddb3cd8f7" have entirely different histories.

6 changed files with 47 additions and 105 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -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.1", "@mui/icons-material": "^6.3.0",
"@mui/material": "^6.3.1", "@mui/material": "^6.3.0",
"@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.16", "@tailwindcss/typography": "^0.5.15",
"@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.3" "zustand": "^5.0.2"
}, },
"devDependencies": { "devDependencies": {
"typescript": "^5.7.3", "typescript": "^5",
"@types/node": "^20.17.12", "@types/node": "^20",
"@types/react": "^19.0.4", "@types/react": "^19",
"@types/react-dom": "^19.0.2", "@types/react-dom": "^19",
"postcss": "^8.4.49", "postcss": "^8",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.1",
"eslint": "^9.17.0", "eslint": "^9",
"eslint-config-next": "15.1.3", "eslint-config-next": "15.1.3",
"@eslint/eslintrc": "^3.2.0" "@eslint/eslintrc": "^3"
}, },
"trustedDependencies": [ "trustedDependencies": [
"@vercel/speed-insights" "@vercel/speed-insights"

View File

@ -9,29 +9,26 @@ import {
Drawer, Drawer,
Toolbar, Toolbar,
Typography, Typography,
Link,
} from '@mui/material' } from '@mui/material'
import { JSX } from 'react' import { JSX } from 'react'
import Image from 'next/image' import Image from 'next/image'
import ExploreIcon from '@mui/icons-material/Explore' import FeedIcon from '@mui/icons-material/Feed'
import PhotoLibraryIcon from '@mui/icons-material/PhotoLibrary' import PhotoLibraryIcon from '@mui/icons-material/PhotoLibrary'
import NextLink from 'next/link' import PolicyIcon from '@mui/icons-material/Policy'
import { useRouter } from 'next/router' import Link from 'next/link'
interface NavLink { interface NavLink {
title: string title: string
icon?: JSX.Element icon: JSX.Element
href: string href: string
} }
export function CapDrawer({ width, open, onClose }: { width: number; open: boolean; onClose: () => void }) { export function CapDrawer({ width, open, onClose }: { width: number; open: boolean; onClose: () => void }) {
const router = useRouter()
const functionLinks: NavLink[] = [ const functionLinks: NavLink[] = [
{ {
title: 'Explore', title: 'Posts',
icon: <ExploreIcon />, icon: <FeedIcon />,
href: '/posts', href: '/posts',
}, },
{ {
@ -44,6 +41,7 @@ export function CapDrawer({ width, open, onClose }: { width: number; open: boole
const additionalLinks: NavLink[] = [ const additionalLinks: NavLink[] = [
{ {
title: 'Terms & Conditions', title: 'Terms & Conditions',
icon: <PolicyIcon />,
href: '/terms', href: '/terms',
}, },
] ]
@ -76,26 +74,29 @@ export function CapDrawer({ width, open, onClose }: { width: number; open: boole
<List> <List>
{functionLinks.map((l) => ( {functionLinks.map((l) => (
<NextLink passHref href={l.href} key={l.href}> <Link passHref href={l.href} key={l.href}>
<ListItem disablePadding> <ListItem disablePadding>
<ListItemButton selected={router.pathname == l.href}> <ListItemButton>
<ListItemIcon>{l.icon}</ListItemIcon> <ListItemIcon>{l.icon}</ListItemIcon>
<ListItemText primary={l.title} /> <ListItemText primary={l.title} />
</ListItemButton> </ListItemButton>
</ListItem> </ListItem>
</NextLink> </Link>
))} ))}
</List> </List>
<Divider /> <Divider />
<Box sx={{ display: 'flex', flexWrap: 'wrap', px: 2, py: 1.5 }}> <List dense>
{additionalLinks.map((l) => ( {additionalLinks.map((l) => (
<NextLink passHref href={l.href} key={l.href}> <Link passHref href={l.href} key={l.href}>
<Link variant="body2" color={'textSecondary'} fontSize={13}> <ListItem disablePadding>
{l.title} <ListItemButton>
</Link> <ListItemIcon>{l.icon}</ListItemIcon>
</NextLink> <ListItemText primary={l.title} />
</ListItemButton>
</ListItem>
</Link>
))} ))}
</Box> </List>
</Box> </Box>
</Drawer> </Drawer>
) )

View File

@ -4,26 +4,18 @@ 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({ export function AttachmentItem({ item, ...rest }: { item: SnAttachment } & ComponentProps<'div'>) {
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 <img src={getAttachmentUrl(item.rid)} alt={item.alt} style={{ objectFit: 'cover', borderRadius: '8px' }} />
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: borderRadius ?? '8px' }} /> <video src={getAttachmentUrl(item.rid)} controls style={{ borderRadius: '8px' }} />
</Paper> </Paper>
) )
default: default:

View File

@ -1,62 +0,0 @@
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>
)
}

View File

@ -2,7 +2,18 @@ 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 { Avatar, Box, Container, Divider, Grid2 as Grid, Link, Pagination, Paper, Typography } from '@mui/material' import {
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'