import { useEffect } from 'react'
/**
* 修復 iOS 鍵盤收起后頁面不恢復的問題
*
* 問題:iOS Safari 在鍵盤收起后,visualViewport.pageTop 不會自動歸零,
* 導致頁面視覺上仍然被推上去
*
* 解決方案:
* 1. 監聽 visualViewport.resize 事件
* 2. 檢測鍵盤彈起/收起(viewport 高度變化超過 100px)
* 3. 鍵盤彈起時:滾動到頂部消除空白
* 4. 鍵盤收起時:使用 scrollTo(0,1) -> scrollTo(0,0) 技巧強制 Safari 重新計算 viewport
*/
export const useIOSKeyboardFix = () => {
useEffect(() => {
if (typeof window === 'undefined' || !window.visualViewport) return
let previousHeight = window.visualViewport.height
const handleViewportResize = () => {
const currentHeight = window.visualViewport!.height
const heightDiff = currentHeight - previousHeight
// 鍵盤彈起:高度減少超過 100px,滾動到頂部消除空白
if (heightDiff < -100) {
setTimeout(() => {
window.scrollTo(0, 0)
document.documentElement.scrollTop = 0
document.body.scrollTop = 0
}, 500)
}
// 鍵盤收起:高度增加超過 100px,重置 viewport 位置
else if (heightDiff > 100) {
requestAnimationFrame(() => {
const viewportOffsetTop = window.visualViewport?.pageTop || 0
if (viewportOffsetTop !== 0) {
// 使用經典的 iOS scrollTo(0,1) -> scrollTo(0,0) 技巧強制 Safari 重新計算 viewport
window.scrollTo(0, 1)
requestAnimationFrame(() => {
window.scrollTo(0, 0)
document.documentElement.scrollTop = 0
document.body.scrollTop = 0
})
} else {
// viewport 正常,直接重置
window.scrollTo(0, 0)
document.documentElement.scrollTop = 0
document.body.scrollTop = 0
}
})
}
previousHeight = currentHeight
}
window.visualViewport.addEventListener('resize', handleViewportResize)
return () => {
window.visualViewport?.removeEventListener('resize', handleViewportResize)
}
}, [])
}