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
38 lines
1.1 KiB
TypeScript
38 lines
1.1 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect } from "react";
|
|
|
|
export default function SecretLayer() {
|
|
const [message, setMessage] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
// In a real app, this would fetch from a database or listen to a WebSocket
|
|
const savedMessage = localStorage.getItem("shadow_broadcast");
|
|
if (savedMessage) {
|
|
setMessage(savedMessage);
|
|
}
|
|
|
|
// Listen for storage changes (if admin updates in another tab)
|
|
const handleStorage = () => {
|
|
setMessage(localStorage.getItem("shadow_broadcast"));
|
|
};
|
|
window.addEventListener("storage", handleStorage);
|
|
return () => window.removeEventListener("storage", handleStorage);
|
|
}, []);
|
|
|
|
if (!message) return null;
|
|
|
|
return (
|
|
<div className="fixed bottom-0 left-0 w-full bg-red-600 text-white py-2 px-4 text-center font-mono text-xs z-[9999] animate-pulse">
|
|
<span className="font-bold uppercase mr-4">[ADMIN BROADCAST]:</span>
|
|
{message}
|
|
<button
|
|
onClick={() => setMessage(null)}
|
|
className="ml-4 underline opacity-50 hover:opacity-100"
|
|
>
|
|
DISMISS
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|