Files
popa-launcher/src/renderer/components/Notifier.tsx
2025-12-28 14:32:39 +05:00

156 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
Alert,
Box,
Snackbar,
Button,
Stack,
Typography,
Paper,
} from '@mui/material';
import { useEffect, useState } from 'react';
import { styled, alpha, keyframes } from '@mui/material/styles';
export const GRADIENT =
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)';
const glowPulse = keyframes`
0% { opacity: .6 }
50% { opacity: 1 }
100% { opacity: .6 }
`;
export const GlassCard = styled(Paper)(() => ({
position: 'relative',
overflow: 'hidden',
borderRadius: 18,
background: 'rgba(0,0,0,0.45)',
border: '1px solid rgba(255,255,255,0.12)',
backdropFilter: 'blur(14px)',
boxShadow: '0 16px 40px rgba(0,0,0,0.45)',
}));
export const Glow = styled('div')(() => ({
position: 'absolute',
inset: -2,
background:
'radial-gradient(400px 120px at 10% 0%, rgba(242,113,33,0.25), transparent 60%),' +
'radial-gradient(400px 120px at 90% 0%, rgba(233,64,205,0.25), transparent 60%)',
pointerEvents: 'none',
animation: `${glowPulse} 5s ease-in-out infinite`,
}));
export const GradientButton = styled(Button)(() => ({
background: GRADIENT,
borderRadius: 999,
textTransform: 'none',
fontWeight: 700,
'&:hover': {
background: GRADIENT,
filter: 'brightness(1.08)',
},
}));
export const SoftButton = styled(Button)(() => ({
borderRadius: 999,
textTransform: 'none',
color: '#fff',
border: '1px solid rgba(255,255,255,0.14)',
background: 'rgba(255,255,255,0.06)',
'&:hover': { background: 'rgba(255,255,255,0.1)' },
}));
type Severity = 'error' | 'warning' | 'info' | 'success';
const severityColor: Record<Severity, string> = {
info: '#4fc3f7',
success: '#4caf50',
warning: '#ff9800',
error: '#f44336',
};
export const Notifier = () => {
const [open, setOpen] = useState(false);
const [message, setMessage] = useState('');
const [severity, setSeverity] = useState<Severity>('info');
const [hasUpdateAvailable, setHasUpdateAvailable] = useState(false);
useEffect(() => {
// Слушаем событие о наличии обновления
window.electron.ipcRenderer.on('update-available', () => {
setMessage('Доступно новое обновление');
setSeverity('info');
setHasUpdateAvailable(true);
setOpen(true);
});
return () => {
// Отписываемся от события при размонтировании
window.electron.ipcRenderer.removeAllListeners('update-available');
};
}, []);
useEffect(() => {
if (process.env.NODE_ENV === 'development') {
setMessage('Доступно новое обновление (dev preview)');
setSeverity('info');
setHasUpdateAvailable(true);
setOpen(true);
}
}, []);
const handleClose = () => {
setOpen(false);
};
const handleUpdate = () => {
window.electron.ipcRenderer.invoke('install-update');
setOpen(false);
};
return (
<Snackbar
open={open}
onClose={handleClose}
autoHideDuration={hasUpdateAvailable ? null : 5000}
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
>
<GlassCard sx={{ minWidth: 340 }}>
<Glow />
<Box
sx={{
p: 2,
position: 'relative',
gap: 1,
display: 'flex',
flexDirection: 'column',
}}
>
<Typography
sx={{
color: 'rgba(255,255,255,0.82)',
fontSize: 13.5,
lineHeight: 1.35,
pr: hasUpdateAvailable ? 1 : 0,
}}
>
{message}
</Typography>
{hasUpdateAvailable && (
<Stack direction="row" spacing={1} justifyContent="center" gap={1}>
<SoftButton size="small" onClick={handleUpdate}>
Обновить
</SoftButton>
<SoftButton size="small" onClick={handleClose}>
Позже
</SoftButton>
</Stack>
)}
</Box>
</GlassCard>
</Snackbar>
);
};