- Replace fake-site footer with dark-web launch CTA; fix HubChatter inside AppProviders (client crash) - Add /launch, DEPLOY.md, onions:list|status|health, list-onion-urls, install-systemd, onion-status - start.sh CYBERLUX_PREPARE_ONLY; copy pass on satellite pages; Navbar launch link - README: operator cheat sheet, phone Tor note, systemd via install-systemd.sh Made-with: Cursor
105 lines
3.5 KiB
TypeScript
105 lines
3.5 KiB
TypeScript
"use client";
|
||
|
||
import Link from "next/link";
|
||
import { useState, useEffect, useRef } from "react";
|
||
|
||
export default function DDoSProtection({ onComplete }: { onComplete: () => void }) {
|
||
const [progress, setProgress] = useState(0);
|
||
const [status, setStatus] = useState("Checking your browser…");
|
||
/** Client-only — avoids SSR/client HTML mismatch from Math.random() in JSX. */
|
||
const [rayId, setRayId] = useState("");
|
||
const doneRef = useRef(false);
|
||
const onCompleteRef = useRef(onComplete);
|
||
onCompleteRef.current = onComplete;
|
||
|
||
useEffect(() => {
|
||
setRayId(Math.random().toString(36).substring(2, 10).toUpperCase());
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
const interval = setInterval(() => {
|
||
setProgress((prev) => {
|
||
if (prev >= 100) {
|
||
return 100;
|
||
}
|
||
const next = prev + Math.random() * 15;
|
||
if (next >= 100) {
|
||
if (!doneRef.current) {
|
||
doneRef.current = true;
|
||
clearInterval(interval);
|
||
setTimeout(() => onCompleteRef.current(), 500);
|
||
}
|
||
return 100;
|
||
}
|
||
return next;
|
||
});
|
||
}, 400);
|
||
|
||
const statusUpdates = [
|
||
"Checking your browser…",
|
||
"Verifying client challenge…",
|
||
"Analyzing request signature…",
|
||
"Negotiating TLS + Tor circuit…",
|
||
"Establishing encrypted tunnel…",
|
||
"Access granted.",
|
||
];
|
||
|
||
let statusIndex = 0;
|
||
const statusInterval = setInterval(() => {
|
||
if (statusIndex < statusUpdates.length - 1) {
|
||
statusIndex++;
|
||
setStatus(statusUpdates[statusIndex]);
|
||
} else {
|
||
clearInterval(statusInterval);
|
||
}
|
||
}, 800);
|
||
|
||
return () => {
|
||
clearInterval(interval);
|
||
clearInterval(statusInterval);
|
||
};
|
||
}, []);
|
||
|
||
return (
|
||
<div
|
||
className="fixed inset-0 z-[10000] flex flex-col items-center justify-center bg-black p-8 font-mono text-[#00ff41]"
|
||
style={{ backgroundColor: "#000000", color: "#00ff41" }}
|
||
>
|
||
<div
|
||
className="w-full max-w-md border-2 border-[#00ff41]/20 bg-[#050505] p-12 shadow-[0_0_50px_rgba(0,255,65,0.1)]"
|
||
style={{ backgroundColor: "#050505", borderColor: "rgba(0,255,65,0.2)" }}
|
||
>
|
||
<div className="text-4xl mb-8 animate-pulse">🛡️</div>
|
||
<h1 className="text-2xl font-bold mb-2 uppercase tracking-tighter">DDoS Protection</h1>
|
||
<p className="text-xs opacity-60 mb-8 leading-relaxed">
|
||
Origin shield active — wait while we validate your session. Automated requests are throttled at the edge.
|
||
</p>
|
||
|
||
<div className="w-full h-2 bg-[#00ff41]/10 mb-4 overflow-hidden">
|
||
<div
|
||
className="h-full bg-[#00ff41] transition-all duration-300 ease-out"
|
||
style={{ width: `${progress}%` }}
|
||
/>
|
||
</div>
|
||
|
||
<div className="flex justify-between text-[10px] uppercase tracking-widest">
|
||
<span>{status}</span>
|
||
<span>{Math.floor(progress)}%</span>
|
||
</div>
|
||
|
||
<div className="mt-12 text-[8px] opacity-20 leading-relaxed">
|
||
Ray ID: {rayId || "—"}
|
||
<br />
|
||
Performance & Security by ShadowGuard™
|
||
</div>
|
||
</div>
|
||
<p className="pointer-events-none fixed bottom-6 left-0 right-0 px-4 text-center text-sm font-mono uppercase tracking-[0.2em] text-neon-cyan/80 sm:text-base">
|
||
Tor-ready ingress · verify circuit ·{" "}
|
||
<Link href="/launch" className="pointer-events-auto text-neon-purple underline hover:text-neon-cyan">
|
||
/launch
|
||
</Link>
|
||
</p>
|
||
</div>
|
||
);
|
||
}
|