Files
jiang13-forum/frontend/src/utils/zoomGuard.ts
freefire 2392768868 feat(ssr): 真 SSR 收尾——干净 hydration 与浏览器原生滚动恢复
- 修复 onRenderClient 引入 serverClient 导致浏览器 process is not defined:
  抽出双端安全的 ssr/feedSeed.ts 作为唯一数据播种入口,serverClient 加 SSR 守卫
- 修复 React 19 Fizz Suspense Outlining:Suspense 边界从布局 Outlet 下移到
  各懒加载路由,SSR 输出不再出现 <!--$?--> / $RB / template 探针标记
- 修复窄屏 React #418 hydration 致命错误:useMediaQuery 首帧恒 false,
  useLayoutEffect 绘制前同步真实值;主题改 cookie 存储供 SSR 直出,
  head 内联防闪烁/缩放脚本移除(缩放锁改为客户端 zoomGuard 模块)
- 清理假 SSR 残留:删除 StaticFeedList 镜像组件、SSR 图标生成脚本、
  探针与死代码;列表接口裁剪正文,仅下发 excerpt/first_image
- Feed 与帖子详情改为窗口滚动(app-shell--doc-scroll):删除虚拟列表、
  自研滚动快照与全局滚轮 hack;F5/前进后退滚动位置全部交给浏览器原生
  历史恢复,HTML 响应头 no-cache 配合;锚点/楼层用 scrollIntoView +
  scroll-margin-top 适配 sticky 顶栏
2026-09-09 20:53:28 +08:00

34 lines
1.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 手机/平板双指与手势缩放锁(头像裁剪、图片灯箱区域放行 pinch)。
*
* 只监听用户手势事件,而手势必然发生在页面加载与客户端 bundle 执行之后,
* 因此无需像主题脚本那样内联在 <head> 中,在客户端入口安装即可。
*/
export function installZoomGuard(): void {
if (typeof document === 'undefined') return;
const inZoomAllowArea = (target: EventTarget | null): boolean =>
!!target
&& target instanceof Element
&& typeof target.closest === 'function'
&& !!target.closest('.avatar-crop-stage, .image-lightbox');
const blockGesture = (e: Event) => {
if (inZoomAllowArea(e.target)) return;
if (e.cancelable) e.preventDefault();
};
const blockMultiTouch = (e: TouchEvent) => {
if (e.touches && e.touches.length > 1) {
if (inZoomAllowArea(e.target)) return;
if (e.cancelable) e.preventDefault();
}
};
document.addEventListener('gesturestart', blockGesture, { passive: false });
document.addEventListener('gesturechange', blockGesture, { passive: false });
document.addEventListener('gestureend', blockGesture, { passive: false });
document.addEventListener('touchstart', blockMultiTouch, { passive: false });
document.addEventListener('touchmove', blockMultiTouch, { passive: false });
}