Files
malenia-frontend/src/components/ClientLinksModal.tsx
2026-08-14 19:49:27 +07:00

112 lines
3.4 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 { useEffect } from 'react';
import { createPortal } from 'react-dom';
interface Client {
name: string;
href: string;
note?: string;
}
interface Platform {
name: string;
clients: Client[];
}
const PLATFORMS: Platform[] = [
{
name: 'iOS',
clients: [
{ name: 'Incy Client', href: 'https://apps.apple.com/us/app/incy/id6756943388', note: 'Приложение может быть недоступно в РФ, смените регион.' },
],
},
{
name: 'Windows',
clients: [
{ name: 'Happ', href: 'https://github.com/Happ-proxy/happ-desktop/releases/latest/download/setup-Happ.x64.exe' },
{
name: 'Throne',
href: 'https://github.com/throneproj/Throne/releases/latest',
note: 'При первом запуске: Настройки -> Подписка -> Разрешить отправку HWID.',
},
],
},
{
name: 'Android',
clients: [
{ name: 'Happ (Google Play)', href: 'https://play.google.com/store/apps/details?id=com.happproxy&pli=1' },
{ name: 'Happ (APK)', href: 'https://github.com/Happ-proxy/happ-android/releases/latest/download/Happ.apk' },
{ name: 'v2raytun', href: 'https://play.google.com/store/apps/details?id=com.v2raytun.android&hl=ru' },
],
},
{
name: 'Linux',
clients: [
{
name: 'Throne',
href: 'https://github.com/throneproj/Throne/releases/latest',
note: 'При первом запуске: Настройки -> Подписка -> Разрешить отправку HWID.',
},
],
},
];
interface ClientLinksModalProps {
open: boolean;
onClose: () => void;
}
export function ClientLinksModal({ open, onClose }: ClientLinksModalProps) {
useEffect(() => {
if (!open) return;
const onKey = (event: KeyboardEvent) => {
if (event.key === 'Escape') onClose();
};
document.addEventListener('keydown', onKey);
document.body.style.overflow = 'hidden';
return () => {
document.removeEventListener('keydown', onKey);
document.body.style.overflow = '';
};
}, [onClose, open]);
if (!open) return null;
return createPortal(
<div
className="modal-veil is-open"
role="dialog"
aria-modal="true"
aria-labelledby="client-links-title"
onClick={(event) => {
if (event.target === event.currentTarget) onClose();
}}
>
<div className="modal client-links-modal" role="document">
<div className="modal-kicker">Подключение устройства</div>
<h3 className="modal-title" id="client-links-title">
Выберите клиент
</h3>
<div className="client-platforms">
{PLATFORMS.map((platform) => (
<section className="client-platform" key={platform.name} aria-label={platform.name}>
<h4>{platform.name}</h4>
{platform.clients.map((client) => (
<div className="client-link" key={client.href}>
<a href={client.href} target="_blank" rel="noreferrer">
{client.name}
</a>
{client.note ? <p>{client.note}</p> : null}
</div>
))}
</section>
))}
</div>
<button type="button" className="btn" onClick={onClose} autoFocus>
Закрыть
</button>
</div>
</div>,
document.body,
);
}