64 lines
1.5 KiB
TypeScript
64 lines
1.5 KiB
TypeScript
export function usePullToRefresh(onRefresh: () => Promise<void> | void) {
|
|
const isPulling = ref(false)
|
|
const pullDistance = ref(0)
|
|
const isRefreshing = ref(false)
|
|
|
|
const threshold = 80
|
|
let startY = 0
|
|
let currentY = 0
|
|
|
|
const onTouchStart = (e: TouchEvent) => {
|
|
if (window.scrollY === 0) {
|
|
startY = e.touches[0].clientY
|
|
isPulling.value = true
|
|
}
|
|
}
|
|
|
|
const onTouchMove = (e: TouchEvent) => {
|
|
if (!isPulling.value || isRefreshing.value) return
|
|
|
|
currentY = e.touches[0].clientY
|
|
const diff = currentY - startY
|
|
|
|
if (diff > 0 && window.scrollY === 0) {
|
|
pullDistance.value = Math.min(diff * 0.5, threshold * 1.5)
|
|
if (diff > 10) {
|
|
e.preventDefault()
|
|
}
|
|
}
|
|
}
|
|
|
|
const onTouchEnd = async () => {
|
|
if (!isPulling.value) return
|
|
|
|
if (pullDistance.value >= threshold && !isRefreshing.value) {
|
|
isRefreshing.value = true
|
|
await onRefresh()
|
|
isRefreshing.value = false
|
|
}
|
|
|
|
isPulling.value = false
|
|
pullDistance.value = 0
|
|
startY = 0
|
|
}
|
|
|
|
onMounted(() => {
|
|
document.addEventListener('touchstart', onTouchStart, { passive: true })
|
|
document.addEventListener('touchmove', onTouchMove, { passive: false })
|
|
document.addEventListener('touchend', onTouchEnd)
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
document.removeEventListener('touchstart', onTouchStart)
|
|
document.removeEventListener('touchmove', onTouchMove)
|
|
document.removeEventListener('touchend', onTouchEnd)
|
|
})
|
|
|
|
return {
|
|
isPulling,
|
|
pullDistance,
|
|
isRefreshing,
|
|
threshold
|
|
}
|
|
}
|