Moved to next js ssr (with fixes)
This commit is contained in:
@@ -1,14 +1,248 @@
|
||||
'use client';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Box, LinearProgress } from '@mui/material';
|
||||
import React, { useEffect } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
Grid,
|
||||
Card,
|
||||
CardContent,
|
||||
CardActions,
|
||||
Chip,
|
||||
Button,
|
||||
useTheme,
|
||||
Link,
|
||||
} from '@mui/material';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { IMod } from '@/src/types/Imod';
|
||||
|
||||
const ModsPageLegacy = dynamic(() => import('@/src/legacy-pages/ModsPage'));
|
||||
const ModCard = styled(Card)(({ theme }) => ({
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
background: theme.palette.mode === 'dark'
|
||||
? 'linear-gradient(145deg, #1a1a2e 0%, #16213e 100%)'
|
||||
: 'linear-gradient(145deg, #ffffff 0%, #f5f5f5 100%)',
|
||||
border: `1px solid ${theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'}`,
|
||||
borderRadius: '16px',
|
||||
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
'&::before': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: '3px',
|
||||
background: theme.palette.mode === 'dark'
|
||||
? 'linear-gradient(90deg, #dee2e6 0%, #cccccc 100%)'
|
||||
: 'linear-gradient(90deg, #000000 0%, #333333 100%)',
|
||||
transform: 'scaleX(0)',
|
||||
transition: 'transform 0.3s ease',
|
||||
},
|
||||
'&:hover': {
|
||||
boxShadow: theme.palette.mode === 'dark' ? '0 20px 40px rgba(255, 255, 255, 0.1)' : '0 20px 40px rgba(0, 0, 0, 0.2)',
|
||||
borderColor: theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.3)' : 'rgba(0, 0, 0, 0.3)',
|
||||
'&::before': {
|
||||
transform: 'scaleX(1)',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
const VersionLink = styled(Link)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: theme.spacing(1.5, 2),
|
||||
marginBottom: theme.spacing(1),
|
||||
background: theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.05)' : 'rgba(0, 0, 0, 0.05)',
|
||||
borderRadius: '10px',
|
||||
textDecoration: 'none',
|
||||
color: 'inherit',
|
||||
transition: 'all 0.2s ease',
|
||||
border: `1px solid ${theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'}`,
|
||||
'&:hover': {
|
||||
background: theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)',
|
||||
borderColor: theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.3)' : 'rgba(0, 0, 0, 0.3)',
|
||||
},
|
||||
}));
|
||||
|
||||
const ModTitle = styled(Typography)(({ theme }) => ({
|
||||
fontWeight: 700,
|
||||
mb: 1,
|
||||
background: theme.palette.mode === 'dark'
|
||||
? 'linear-gradient(135deg, #dee2e6 0%, #e0e0e0 100%)'
|
||||
: 'none',
|
||||
WebkitBackgroundClip: theme.palette.mode === 'dark' ? 'text' : 'initial',
|
||||
WebkitTextFillColor: theme.palette.mode === 'dark' ? '#dee2e6' : 'initial',
|
||||
color: theme.palette.mode === 'dark' ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)',
|
||||
}));
|
||||
|
||||
const VersionsChip = styled(Chip)(({ theme }) => ({
|
||||
backgroundColor: theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.15)' : 'rgba(0, 0, 0, 0.1)',
|
||||
color: theme.palette.mode === 'dark' ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)',
|
||||
fontWeight: 600,
|
||||
}));
|
||||
|
||||
const VersionText = styled(Typography)(({ theme }) => ({
|
||||
fontWeight: 600,
|
||||
color: theme.palette.text.secondary,
|
||||
}));
|
||||
|
||||
const VersionArrow = styled(Typography)(({ theme }) => ({
|
||||
color: theme.palette.text.secondary,
|
||||
}));
|
||||
|
||||
const BetaVersionsLabel = styled(Typography)(({ theme }) => ({
|
||||
color: 'rgba(255, 193, 7, 0.9)',
|
||||
fontWeight: 600,
|
||||
mb: 1,
|
||||
}));
|
||||
|
||||
interface ModsPageClientProps {
|
||||
initialMods: IMod[];
|
||||
}
|
||||
|
||||
export default function ModsPageClient({ initialMods }: ModsPageClientProps) {
|
||||
return <ModsPageLegacy initialMods={initialMods} />;
|
||||
const theme = useTheme();
|
||||
|
||||
// Очистка кэша сайта при заходе на главную страницу (один раз за сессию)
|
||||
useEffect(() => {
|
||||
if (!sessionStorage.getItem('cache_cleared')) {
|
||||
sessionStorage.setItem('cache_cleared', '1');
|
||||
(async () => {
|
||||
try {
|
||||
if ('caches' in window) {
|
||||
const names = await caches.keys();
|
||||
await Promise.all(names.map(name => caches.delete(name)));
|
||||
}
|
||||
if ('serviceWorker' in navigator) {
|
||||
const regs = await navigator.serviceWorker.getRegistrations();
|
||||
await Promise.all(regs.map(r => r.unregister()));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Cache clear failed:', e);
|
||||
}
|
||||
})();
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Sort all mods by order, then group by name
|
||||
const sortedMods = [...initialMods].sort((a, b) => a.order - b.order);
|
||||
|
||||
const mapWithModVersions = new Map<string, IMod[]>();
|
||||
sortedMods.forEach(mod => {
|
||||
const versionList = mapWithModVersions.get(mod.name);
|
||||
if (versionList == null) {
|
||||
mapWithModVersions.set(mod.name, [mod]);
|
||||
} else {
|
||||
versionList.push(mod);
|
||||
}
|
||||
});
|
||||
|
||||
const getLatestVersion = (modName: string) => {
|
||||
const sameMods = mapWithModVersions.get(modName) ?? [];
|
||||
// The latest version is the one with the maximum id
|
||||
const latest = sameMods.reduce((max, mod) => mod.id > max.id ? mod : max, sameMods[0]);
|
||||
const betaMods = sameMods.filter(m => m.isBeta);
|
||||
return {
|
||||
latest,
|
||||
allVersions: sameMods,
|
||||
hasBeta: betaMods.length > 0,
|
||||
betaVersion: betaMods[0],
|
||||
};
|
||||
};
|
||||
|
||||
function ModCardComponent(modName: string) {
|
||||
const sameMods = mapWithModVersions.get(modName) ?? [];
|
||||
const { latest, hasBeta, betaVersion } = getLatestVersion(modName);
|
||||
|
||||
return (
|
||||
<ModCard>
|
||||
<CardContent sx={{ flexGrow: 1, p: 3 }}>
|
||||
<Box sx={{ mb: 2 }}>
|
||||
<ModTitle variant="h5">
|
||||
{modName}
|
||||
</ModTitle>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: 'flex', gap: 1, mb: 2 }}>
|
||||
<VersionsChip
|
||||
label={`${sameMods.length} versions`}
|
||||
size="small"
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{sameMods.filter(m => !m.isBeta).map(mod => (
|
||||
<VersionLink key={mod.id} href={"/mod/" + mod.id}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%' }}>
|
||||
<VersionText variant="body2">
|
||||
Version {mod.version}
|
||||
</VersionText>
|
||||
<VersionArrow variant="caption">
|
||||
→
|
||||
</VersionArrow>
|
||||
</Box>
|
||||
</VersionLink>
|
||||
))}
|
||||
|
||||
{hasBeta && (
|
||||
<Box sx={{ mt: 2 }}>
|
||||
<BetaVersionsLabel variant="subtitle2">
|
||||
Beta versions:
|
||||
</BetaVersionsLabel>
|
||||
{betaVersion && (
|
||||
<VersionLink href={"/mod/" + betaVersion.id}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%' }}>
|
||||
<Typography variant="body2" sx={{ fontWeight: 600 }}>
|
||||
Version {betaVersion.version} (Beta)
|
||||
</Typography>
|
||||
<VersionArrow variant="caption">
|
||||
→
|
||||
</VersionArrow>
|
||||
</Box>
|
||||
</VersionLink>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</CardContent>
|
||||
|
||||
<CardActions sx={{ px: 3, pb: 3 }}>
|
||||
<Button
|
||||
size="medium"
|
||||
variant="outlined"
|
||||
href={"/mod/" + latest?.id}
|
||||
sx={{
|
||||
width: '100%',
|
||||
color: theme.palette.mode === 'dark' ? '#FFD700' : '#1976d2',
|
||||
borderColor: theme.palette.mode === 'dark' ? 'rgba(255, 215, 0, 0.5)' : 'rgba(25, 118, 210, 0.5)',
|
||||
fontWeight: 600,
|
||||
borderRadius: '10px',
|
||||
textTransform: 'none',
|
||||
fontSize: '1rem',
|
||||
py: 1.5,
|
||||
'&:hover': {
|
||||
borderColor: theme.palette.mode === 'dark' ? '#FFD700' : '#1976d2',
|
||||
backgroundColor: theme.palette.mode === 'dark' ? 'rgba(255, 215, 0, 0.1)' : 'rgba(25, 118, 210, 0.1)',
|
||||
boxShadow: theme.palette.mode === 'dark' ? '0 8px 20px rgba(255, 215, 0, 0.2)' : '0 8px 20px rgba(25, 118, 210, 0.2)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
Open latest {latest?.version ?? ''}
|
||||
</Button>
|
||||
</CardActions>
|
||||
</ModCard>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Grid container spacing={3}>
|
||||
{[...new Set(sortedMods.map(m => m.name))].map((modName) => (
|
||||
<Grid item xs={12} sm={6} md={4}>
|
||||
{ModCardComponent(modName)}
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user