diff --git a/composables/useInfiniteScroll.ts b/composables/useInfiniteScroll.ts index d79d0fc..0180852 100644 --- a/composables/useInfiniteScroll.ts +++ b/composables/useInfiniteScroll.ts @@ -1,18 +1,58 @@ // composables/useInfiniteScroll.ts +import { ref, onMounted, onBeforeUnmount } from "vue"; + export default function useInfiniteScroll( - callback: () => void, - elementId: string + callback: () => Promise, + elementId?: string ) { + const route = useRoute(); const isFetching = ref(false); - const infiniteScroll = ref(null); + const infiniteScroll = ref(null); - const handleScroll = () => { - if (isFetching.value) return; - const scrollPosition = - infiniteScroll.value.scrollTop + infiniteScroll.value.clientHeight; - const threshold = infiniteScroll.value.scrollHeight - 100; + // Throttle function to limit scroll event frequency + const throttle = (func: (...args: any[]) => void, limit: number) => { + let lastFunc: ReturnType; + let lastRan: number; + return function (this: any, ...args: any[]) { + const context = this; + if (!lastRan) { + func.apply(context, args); + lastRan = Date.now(); + } else { + clearTimeout(lastFunc); + lastFunc = setTimeout(() => { + if (Date.now() - lastRan >= limit) { + func.apply(context, args); + lastRan = Date.now(); + } + }, limit - (Date.now() - lastRan)); + } + }; + }; - if (scrollPosition >= threshold) { + const checkScrollPosition = () => { + if (isFetching.value || !infiniteScroll.value) return; + + let scrollPosition: number; + let threshold: number; + let clientHeight: number; + let scrollHeight: number; + + if (infiniteScroll.value === window) { + scrollPosition = window.scrollY || window.pageYOffset; + clientHeight = document.documentElement.clientHeight; + scrollHeight = document.documentElement.scrollHeight; + } else { + const el = infiniteScroll.value as HTMLElement; + scrollPosition = el.scrollTop; + clientHeight = el.clientHeight; + scrollHeight = el.scrollHeight; + } + + threshold = scrollHeight - 100; + const currentPosition = scrollPosition + clientHeight; + + if (currentPosition >= threshold) { isFetching.value = true; callback().finally(() => { isFetching.value = false; @@ -20,28 +60,57 @@ export default function useInfiniteScroll( } }; + // Throttled version of scroll handler + const throttledScrollHandler = throttle(checkScrollPosition, 200); + const handleTouchEnd = () => { - // Add a slight delay to ensure scroll position is updated - setTimeout(handleScroll, 100); + setTimeout(throttledScrollHandler, 100); }; onMounted(() => { - const targetElement = document.getElementById(elementId); - infiniteScroll.value = targetElement; + console.info(route.name) + + if (route.name == "hadithaSearch" || route.name == "hadithaLibrary") { + const targetElement = elementId + ? document.getElementById(elementId) + : window; - if (targetElement) { - targetElement.addEventListener("scroll", handleScroll); - targetElement.addEventListener("touchend", handleTouchEnd); + if (!targetElement) { + console.warn( + `Element ${elementId || "window"} not found for infinite scroll` + ); + return; + } + + infiniteScroll.value = targetElement; + + if (targetElement === window) { + window.addEventListener("scroll", throttledScrollHandler); + window.addEventListener("touchend", handleTouchEnd); + } else { + targetElement.addEventListener("scroll", throttledScrollHandler); + targetElement.addEventListener("touchend", handleTouchEnd); + } } }); onBeforeUnmount(() => { - const targetElement = document.getElementById(elementId); - infiniteScroll.value = targetElement; + if (route.name == "hadithaSearch" || route.name == "hadithaLibrary") { + if (!infiniteScroll.value) return; - if (targetElement) { - targetElement.removeEventListener("scroll", handleScroll); - targetElement.removeEventListener("touchend", handleTouchEnd); + if (infiniteScroll.value === window) { + window.removeEventListener("scroll", throttledScrollHandler); + window.removeEventListener("touchend", handleTouchEnd); + } else { + (infiniteScroll.value as HTMLElement).removeEventListener( + "scroll", + throttledScrollHandler + ); + (infiniteScroll.value as HTMLElement).removeEventListener( + "touchend", + handleTouchEnd + ); + } } }); diff --git a/systems/research_ui b/systems/research_ui index c3aa660..e104762 160000 --- a/systems/research_ui +++ b/systems/research_ui @@ -1 +1 @@ -Subproject commit c3aa6605ff449226a04817f0fb29a4b0f77654bc +Subproject commit e1047621e2b74024de94331d7a1f424e83214440 diff --git a/systems/search_ui b/systems/search_ui index 117dc3e..f4dbda3 160000 --- a/systems/search_ui +++ b/systems/search_ui @@ -1 +1 @@ -Subproject commit 117dc3e4faed749ac4dbfbf0a41899fe22282c84 +Subproject commit f4dbda3abbe6ca4b18fe3e2f452a3684ca13c9ad diff --git a/systems/task_ui b/systems/task_ui index dce0b4f..1c5b1d4 160000 --- a/systems/task_ui +++ b/systems/task_ui @@ -1 +1 @@ -Subproject commit dce0b4fe6cf7158ac7cb841564e78de33e23d0a3 +Subproject commit 1c5b1d47a1a07ba1a567e9f11fd60d5408fde883