diff --git a/bun.lockb b/bun.lockb index 0c00167..2e09d4e 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/next.config.ts b/next.config.ts index b441baf..e33df0a 100644 --- a/next.config.ts +++ b/next.config.ts @@ -4,7 +4,16 @@ const nextConfig: NextConfig = { /* config options here */ reactStrictMode: true, images: { - domains: ['raw.sn.solsynth.dev', 'api.sn.solsynth.dev'], + remotePatterns: [ + { + protocol: 'https', + hostname: 'raw.sn.solsynth.dev', + }, + { + protocol: 'https', + hostname: 'api.sn.solsynth.dev', + }, + ], }, } diff --git a/package.json b/package.json index 12fb9d3..c93b86e 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "react-hook-form": "^7.54.2", "rehype-sanitize": "^6.0.0", "rehype-stringify": "^10.0.1", + "remark-breaks": "^4.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "unified": "^11.0.5", diff --git a/src/components/CapAppBar.tsx b/src/components/CapAppBar.tsx index c600af6..e7226ab 100644 --- a/src/components/CapAppBar.tsx +++ b/src/components/CapAppBar.tsx @@ -3,11 +3,10 @@ import { AppBar, AppBarProps, Avatar, - createTheme, IconButton, - ThemeProvider, Toolbar, Typography, + useMediaQuery, useScrollTrigger, useTheme, } from '@mui/material' @@ -15,11 +14,13 @@ import { getAttachmentUrl } from '@/services/network' import MenuIcon from '@mui/icons-material/Menu' import AccountCircle from '@mui/icons-material/AccountCircle' import Link from 'next/link' -import React from 'react' +import React, { useState } from 'react' +import { CapDrawer } from './CapDrawer' interface ElevationAppBarProps { elevation?: number color?: any + isMobile: boolean children?: React.ReactElement<{ elevation?: number } & AppBarProps> } @@ -51,38 +52,63 @@ export function CapAppBar() { const userStore = useUserStore() const theme = useTheme() - return ( - - - - - - - - - Capital - - + const isMobile = useMediaQuery(theme.breakpoints.down('md')) - + const [open, setOpen] = useState(false) + + const drawerWidth = 280 + + return ( + <> + setOpen(false)} /> + + + + setOpen(true)} > - {userStore.account ? ( - - ) : ( - - - - )} + - - - - + + + Capital + + + + + + {userStore.account ? ( + + ) : ( + + + + )} + + + + + + ) } diff --git a/src/components/CapDrawer.tsx b/src/components/CapDrawer.tsx new file mode 100644 index 0000000..8c7e1e2 --- /dev/null +++ b/src/components/CapDrawer.tsx @@ -0,0 +1,87 @@ +import { + Box, + List, + ListItem, + ListItemButton, + ListItemIcon, + ListItemText, + Divider, + Drawer, + Toolbar, +} from '@mui/material' +import { JSX } from 'react' + +import FeedIcon from '@mui/icons-material/Feed' +import PhotoLibraryIcon from '@mui/icons-material/PhotoLibrary' +import InfoIcon from '@mui/icons-material/Info' +import PolicyIcon from '@mui/icons-material/Policy' +import Link from 'next/link' + +interface NavLink { + title: string + icon: JSX.Element + href: string +} + +export function CapDrawer({ width, open, onClose }: { width: number; open: boolean; onClose: () => void }) { + const functionLinks: NavLink[] = [ + { + title: 'Posts', + icon: , + href: '/posts', + }, + { + title: 'Gallery', + icon: , + href: '/attachments', + }, + ] + + const additionalLinks: NavLink[] = [ + { + title: 'About', + icon: , + href: '/about', + }, + { + title: 'Term & Conditions', + icon: , + href: '/terms', + }, + ] + + return ( + + + Solsynth LLC + + + + {functionLinks.map((l) => ( + + + + {l.icon} + + + + + ))} + + + + {additionalLinks.map((l) => ( + + + + {l.icon} + + + + + ))} + + + + ) +} diff --git a/src/pages/posts/[...id].tsx b/src/pages/posts/[...id].tsx index f50a9d4..ce5a879 100644 --- a/src/pages/posts/[...id].tsx +++ b/src/pages/posts/[...id].tsx @@ -22,6 +22,7 @@ import Head from 'next/head' import Image from 'next/image' 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' @@ -32,15 +33,12 @@ export const getServerSideProps = (async (context) => { try { const { data: post } = await sni.get('/cgi/co/posts/' + id.join(':')) if (post.body.content) { - if (!post.body.description) { - post.body.description = post.body.content.replaceAll('\n', ' ').substring(0, 200) + let processor: any = unified().use(remarkParse) + if (post.type != 'article') { + processor = processor.use(remarkBreaks) } - const out = await unified() - .use(remarkParse) - .use(remarkRehype) - .use(rehypeSanitize) - .use(rehypeStringify) - .process(post.body.content) + 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) } let attachments: SnAttachment[] = [] @@ -49,6 +47,7 @@ export const getServerSideProps = (async (context) => { } return { props: { post, attachments } } } catch (err) { + console.error(err) return { notFound: true, } @@ -72,7 +71,11 @@ export default function Post({ post, attachments }: InferGetServerSidePropsType< : `Post #${post.id} / @${post.publisher.name} / Solar Network`, [post], ) - const description = useMemo(() => post.body.description, [post]) + const description = useMemo( + () => + post.body.description ? post.body.description : post.body.rawContent.replaceAll('\n', ' ').substring(0, 200), + [post], + ) const image = useMemo(() => { if (post.body.thumbnail) { @@ -80,21 +83,21 @@ export default function Post({ post, attachments }: InferGetServerSidePropsType< } if (attachments) { const images = attachments.filter((a) => a.mimetype.startsWith('image')) - if (images) return getAttachmentUrl(images[0].rid) + if (images && images[0]) return getAttachmentUrl(images[0].rid) } return null }, [post]) const video = useMemo(() => { if (attachments) { const videos = attachments.filter((a) => a.mimetype.startsWith('video')) - if (videos) return getAttachmentUrl(videos[0].rid) + if (videos && videos[0]) return getAttachmentUrl(videos[0].rid) } return null }, [post]) const audio = useMemo(() => { if (attachments) { const audios = attachments.filter((a) => a.mimetype.startsWith('audio')) - if (audios) return getAttachmentUrl(audios[0].rid) + if (audios && audios[0]) return getAttachmentUrl(audios[0].rid) } return null }, [post]) @@ -201,9 +204,21 @@ export default function Post({ post, attachments }: InferGetServerSidePropsType< {attachments && ( - + {attachments.map((a) => ( - + + + ))} )}