Realm QR Code

This commit is contained in:
LittleSheep 2025-02-10 18:59:04 +08:00
parent f26d29e2f0
commit 05de2e1799
3 changed files with 86 additions and 57 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -31,6 +31,7 @@
"next": "^15.1.5", "next": "^15.1.5",
"next-i18next": "^15.4.2", "next-i18next": "^15.4.2",
"next-nprogress-bar": "^2.4.3", "next-nprogress-bar": "^2.4.3",
"qrcode.react": "^4.2.0",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",

View File

@ -14,10 +14,13 @@ import {
ListItemIcon, ListItemIcon,
ListItemText, ListItemText,
Typography, Typography,
useTheme,
} from '@mui/material' } from '@mui/material'
import { GetServerSideProps } from 'next' import { GetServerSideProps } from 'next'
import { checkAuthenticatedClient, getAttachmentUrl, redirectToLogin, sni, useUserStore } from 'solar-js-sdk' import { checkAuthenticatedClient, getAttachmentUrl, redirectToLogin, sni, useUserStore } from 'solar-js-sdk'
import { useEffect, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import { useSearchParams } from 'next/navigation'
import { QRCodeSVG } from 'qrcode.react'
import PublicIcon from '@mui/icons-material/Public' import PublicIcon from '@mui/icons-material/Public'
import ErrorIcon from '@mui/icons-material/Error' import ErrorIcon from '@mui/icons-material/Error'
@ -48,6 +51,10 @@ export default function Realm({ realm }: any) {
const [publicChannels, setPublicChannels] = useState<any[]>([]) const [publicChannels, setPublicChannels] = useState<any[]>([])
const [checkedChannels, setCheckedChannels] = useState<string[]>([]) const [checkedChannels, setCheckedChannels] = useState<string[]>([])
const searchParams = useSearchParams()
const isShare = useMemo(() => searchParams.has('share'), [searchParams])
function handleCheckChannel(value: string) { function handleCheckChannel(value: string) {
const currentIndex = checkedChannels.indexOf(value) const currentIndex = checkedChannels.indexOf(value)
const newChecked = [...checkedChannels] const newChecked = [...checkedChannels]
@ -104,6 +111,8 @@ export default function Realm({ realm }: any) {
} }
} }
const theme = useTheme()
return ( return (
<Box <Box
sx={{ sx={{
@ -133,65 +142,84 @@ export default function Realm({ realm }: any) {
</Typography> </Typography>
<Typography sx={{ mt: 3 }}>{realm.description}</Typography> <Typography sx={{ mt: 3 }}>{realm.description}</Typography>
{publicChannels.length > 0 && ( {isShare ? (
<Box sx={{ mt: 3 }}> <Box mt={3} mx="auto" width={256}>
<Typography fontSize={14} mx={1} sx={{ opacity: 0.75, mb: 0.5, textAlign: 'center' }}> <QRCodeSVG
Public channels in this realm you can join title="Realm QR Code"
value={'https://solsynth.dev/realms/' + realm.alias}
level="H"
bgColor="#00000000"
fgColor={theme.palette.text.primary}
size={256}
/>
<Typography textAlign="center" mt={2}>
Scan the QR Code above to join
</Typography> </Typography>
<List sx={{ width: '100%', p: 0, borderRadius: '8px', bgcolor: 'rgba(255, 255, 255, .2)' }}>
{publicChannels.map((value) => {
const labelId = `checkbox-list-label-${value}`
return (
<ListItem key={value.id} disablePadding>
<ListItemButton
sx={{ borderRadius: '8px' }}
onClick={() => handleCheckChannel(value.alias)}
dense
>
<ListItemIcon>
<Checkbox
edge="start"
checked={checkedChannels.includes(value.alias)}
tabIndex={-1}
disableRipple
inputProps={{ 'aria-labelledby': labelId }}
/>
</ListItemIcon>
<ListItemText id={labelId} primary={value.name} />
</ListItemButton>
</ListItem>
)
})}
</List>
</Box> </Box>
)}
{realm.isCommunity && (
<Box sx={{ mt: 3 }}>
<Box display="flex" sx={{ opacity: 0.75 }}>
<PublicIcon />
<Typography sx={{ ml: 1 }} variant="body2">
A community realm, you can join it as you wish.
</Typography>
</Box>
</Box>
)}
<Collapse in={!!error} sx={{ width: '100%' }}>
<Alert sx={{ mt: 3 }} icon={<ErrorIcon fontSize="inherit" />} severity="error">
{error}
</Alert>
</Collapse>
{joined ? (
<Alert severity="info" sx={{ mt: 2.5 }}>
Joined, check it out in the app
</Alert>
) : ( ) : (
<Button fullWidth variant="contained" disabled={loading} sx={{ mt: 3 }} onClick={joinRealm}> <>
Join {publicChannels.length > 0 && (
</Button> <Box sx={{ mt: 3 }}>
<Typography fontSize={14} mx={1} sx={{ opacity: 0.75, mb: 0.5, textAlign: 'center' }}>
Public channels in this realm you can join
</Typography>
<List sx={{ width: '100%', p: 0, borderRadius: '8px', bgcolor: 'rgba(255, 255, 255, .2)' }}>
{publicChannels.map((value) => {
const labelId = `checkbox-list-label-${value}`
return (
<ListItem key={value.id} disablePadding>
<ListItemButton
sx={{ borderRadius: '8px' }}
onClick={() => handleCheckChannel(value.alias)}
dense
>
<ListItemIcon>
<Checkbox
edge="start"
checked={checkedChannels.includes(value.alias)}
tabIndex={-1}
disableRipple
inputProps={{ 'aria-labelledby': labelId }}
/>
</ListItemIcon>
<ListItemText id={labelId} primary={value.name} />
</ListItemButton>
</ListItem>
)
})}
</List>
</Box>
)}
{realm.isCommunity && (
<Box sx={{ mt: 3 }}>
<Box display="flex" sx={{ opacity: 0.75 }}>
<PublicIcon />
<Typography sx={{ ml: 1 }} variant="body2">
A community realm, you can join it as you wish.
</Typography>
</Box>
</Box>
)}
<Collapse in={!!error} sx={{ width: '100%' }}>
<Alert sx={{ mt: 3 }} icon={<ErrorIcon fontSize="inherit" />} severity="error">
{error}
</Alert>
</Collapse>
{joined ? (
<Alert severity="info" sx={{ mt: 2.5 }}>
Joined, check it out in the app
</Alert>
) : (
<Button fullWidth variant="contained" disabled={loading} sx={{ mt: 3 }} onClick={joinRealm}>
Join
</Button>
)}
</>
)} )}
</CardContent> </CardContent>
</Card> </Card>