Switch nav toggle to tap-only and harden image protection
Replace scroll-direction nav reappear with a one-shot scroll-down hide plus tap-on-image toggle. Distinguish tap from scroll on touch via touchstart/touchmove tracking so swipes don't re-show the nav. Discourage casual image saving with contextmenu prevent, draggable=false, select-none, and -webkit-touch-callout:none. Add 10.8.0.2 to allowedDevOrigins for VPN dev access. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
57255e2624
commit
c099673f6b
@ -42,7 +42,7 @@ export function PageReader({
|
||||
const [showUI, setShowUI] = useState(true);
|
||||
const [showDrawer, setShowDrawer] = useState(false);
|
||||
const [pages, setPages] = useState<PageData[]>([]);
|
||||
const lastScrollY = useRef(0);
|
||||
const hiddenByScrollRef = useRef(false);
|
||||
const offsetRef = useRef(0);
|
||||
const doneRef = useRef(false);
|
||||
const loadingRef = useRef(false);
|
||||
@ -127,17 +127,31 @@ export function PageReader({
|
||||
[]
|
||||
);
|
||||
|
||||
// Distinguish tap from scroll on touch devices
|
||||
const touchMovedRef = useRef(false);
|
||||
|
||||
const onTouchStart = useCallback(() => {
|
||||
touchMovedRef.current = false;
|
||||
}, []);
|
||||
|
||||
const onTouchMove = useCallback(() => {
|
||||
touchMovedRef.current = true;
|
||||
}, []);
|
||||
|
||||
const onTap = useCallback(() => {
|
||||
if (touchMovedRef.current) return;
|
||||
setShowUI((v) => !v);
|
||||
}, []);
|
||||
|
||||
// Hide nav on first scroll down; after that, only tap toggles
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
const currentY = window.scrollY;
|
||||
if (currentY > lastScrollY.current && currentY > 50) {
|
||||
if (!hiddenByScrollRef.current && window.scrollY > 50) {
|
||||
hiddenByScrollRef.current = true;
|
||||
setShowUI(false);
|
||||
} else if (currentY < lastScrollY.current) {
|
||||
setShowUI(true);
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
}
|
||||
lastScrollY.current = currentY;
|
||||
};
|
||||
|
||||
window.addEventListener("scroll", handleScroll, { passive: true });
|
||||
return () => window.removeEventListener("scroll", handleScroll);
|
||||
}, []);
|
||||
@ -178,8 +192,11 @@ export function PageReader({
|
||||
|
||||
{/* Pages - vertical scroll (webtoon style, best for mobile) */}
|
||||
<div
|
||||
className="max-w-4xl mx-auto leading-[0]"
|
||||
onClick={() => setShowUI(!showUI)}
|
||||
className="max-w-4xl mx-auto leading-[0] select-none"
|
||||
onClick={onTap}
|
||||
onTouchStart={onTouchStart}
|
||||
onTouchMove={onTouchMove}
|
||||
onContextMenu={(e) => e.preventDefault()}
|
||||
>
|
||||
{pages.map((page, i) => (
|
||||
<div
|
||||
@ -191,7 +208,8 @@ export function PageReader({
|
||||
<img
|
||||
src={page.imageUrl}
|
||||
alt={`Page ${page.number}`}
|
||||
className="w-full h-auto block align-bottom -mb-px"
|
||||
className="w-full h-auto block align-bottom -mb-px [-webkit-touch-callout:none]"
|
||||
draggable={false}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
allowedDevOrigins: ["10.8.0.2"],
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user