Add VPN detection: show blocker when not on home IP
Check public IP via api.ipify.org on mount and display "Выключи VPN" fullscreen message if it doesn't match the expected home IP. Gracefully falls through on fetch errors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -159,3 +159,13 @@ h2 {
|
|||||||
.actions button.danger:hover {
|
.actions button.danger:hover {
|
||||||
background: #e74c3c;
|
background: #e74c3c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vpn-block {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
font-size: 2rem;
|
||||||
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|||||||
@@ -190,6 +190,16 @@ function parseHash(): { view: "list" | "project"; projectId: number | null } {
|
|||||||
function App() {
|
function App() {
|
||||||
const [view, setView] = useState<"list" | "project">(parseHash().view);
|
const [view, setView] = useState<"list" | "project">(parseHash().view);
|
||||||
const [projectId, setProjectId] = useState<number | null>(parseHash().projectId);
|
const [projectId, setProjectId] = useState<number | null>(parseHash().projectId);
|
||||||
|
const [vpnCheck, setVpnCheck] = useState<"loading" | "ok" | "vpn">("loading");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch("https://api.ipify.org?format=json")
|
||||||
|
.then((r) => r.json())
|
||||||
|
.then((data: { ip: string }) => {
|
||||||
|
setVpnCheck(data.ip === "95.165.73.140" ? "ok" : "vpn");
|
||||||
|
})
|
||||||
|
.catch(() => setVpnCheck("ok"));
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onHashChange = () => {
|
const onHashChange = () => {
|
||||||
@@ -209,6 +219,11 @@ function App() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (vpnCheck === "loading") return null;
|
||||||
|
if (vpnCheck === "vpn") {
|
||||||
|
return <div className="vpn-block">Выключи VPN</div>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="app">
|
<div className="app">
|
||||||
{view === "list" ? (
|
{view === "list" ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user