mirror of
https://github.com/WSA-Installer/wsa-website.git
synced 2026-07-29 11:24:39 -07:00
- Fix VideoAdPlayer CSS conflict and YouTube API race condition - Replace padding-bottom with aspect-video on homepage - Add real AdSense slot IDs to all ad placements (4266907782 banner, 2044808434 in-article, 5341055619 PIP) - AdFrame uses adSenseSlot from config instead of logical slot name - AdFrame shows network name badge and 3 dot indicators for rotation - Add InArticleAd component injecting ads every 4 paragraphs in blog posts - Navigation ad: remove skip button, 5s countdown before Continue clickable - Navigation ad: show on every page navigation (no counter) - Navigation ad: square 400x400 ad area using PIP slot 5341055619
74 lines
2.0 KiB
TypeScript
74 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect, useCallback, useRef } from "react";
|
|
import { usePathname } from "next/navigation";
|
|
import NavigationAdOverlay from "./NavigationAdOverlay";
|
|
import { useNavigationAdConfig } from "@/hooks/useRuntimeConfig";
|
|
|
|
export default function NavigationAdController() {
|
|
const pathname = usePathname();
|
|
const navAd = useNavigationAdConfig();
|
|
const [showAd, setShowAd] = useState(false);
|
|
const [pendingPath, setPendingPath] = useState<string | null>(null);
|
|
const lastPathRef = useRef(pathname);
|
|
const isFirstMount = useRef(true);
|
|
|
|
useEffect(() => {
|
|
if (isFirstMount.current) {
|
|
isFirstMount.current = false;
|
|
lastPathRef.current = pathname;
|
|
return;
|
|
}
|
|
}, [pathname]);
|
|
|
|
useEffect(() => {
|
|
if (!navAd.enabled) return;
|
|
|
|
const handler = (url: string) => {
|
|
if (url === lastPathRef.current) return;
|
|
if (url.startsWith("#") || url.startsWith("javascript:")) return;
|
|
|
|
setPendingPath(url);
|
|
setShowAd(true);
|
|
return false;
|
|
};
|
|
|
|
const originalPush = window.history.pushState;
|
|
const originalReplace = window.history.replaceState;
|
|
|
|
window.history.pushState = function (...args) {
|
|
const result = originalPush.apply(this, args);
|
|
if (args[2] && typeof args[2] === "string") {
|
|
handler(args[2]);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
window.history.replaceState = function (...args) {
|
|
return originalReplace.apply(this, args);
|
|
};
|
|
|
|
return () => {
|
|
window.history.pushState = originalPush;
|
|
window.history.replaceState = originalReplace;
|
|
};
|
|
}, [navAd.enabled]);
|
|
|
|
const handleAccept = useCallback(() => {
|
|
setShowAd(false);
|
|
if (pendingPath) {
|
|
lastPathRef.current = pendingPath;
|
|
window.history.pushState({}, "", pendingPath);
|
|
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
setPendingPath(null);
|
|
}
|
|
}, [pendingPath]);
|
|
|
|
return (
|
|
<NavigationAdOverlay
|
|
visible={showAd}
|
|
onAccept={handleAccept}
|
|
/>
|
|
);
|
|
}
|