Harden onion boot flow and deepen site surfaces
Add persistent onion key backup and restore, improve startup resilience, and flesh out the major site verticals with richer navigation, search coverage, and operator documentation. Made-with: Cursor
This commit is contained in:
100
components/DDoSProtection.tsx
Normal file
100
components/DDoSProtection.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
"use client";
|
||||
|
||||
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-2xl font-black text-red-500 sm:text-3xl md:text-4xl">
|
||||
This site is fake
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user