Skip to content

Commit

Permalink
fix: Improve inViewport detection of replies (#14829)
Browse files Browse the repository at this point in the history
  • Loading branch information
atomrc committed Mar 14, 2023
1 parent cdc6d82 commit e9f5a6c
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 21 deletions.
1 change: 0 additions & 1 deletion src/script/components/utils/InViewport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ const InViewport: React.FC<InViewportParams & React.HTMLProps<HTMLDivElement>> =
inViewport = isInViewport;
triggerCallbackIfVisible();
},
element.parentElement || undefined,
requireFullyInView,
allowBiggerThanViewport,
);
Expand Down
6 changes: 3 additions & 3 deletions src/script/util/DOM/overlayedObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface OverlayElement {
* Keeps track of elements that are overlayed by other elements (thus not visible on screen).
*/
const overlayedElements = new Map<HTMLElement, OverlayElement>();
let overlayCheckerInterval: number = undefined;
let overlayCheckerInterval: number | undefined = undefined;

function checkOverlayedElements() {
overlayedElements.forEach(({onVisible, onChange}, element) => {
Expand All @@ -35,7 +35,7 @@ function checkOverlayedElements() {
return onChange(isVisible);
}
if (isVisible) {
onVisible();
onVisible?.();
removeElement(element);
}
});
Expand All @@ -54,7 +54,7 @@ const isOverlayed = (domElement: HTMLElement): boolean => {
const middlePointX = (box.right + box.left) / 2;
const middlePointY = (box.bottom + box.top) / 2;
const elementAtPoint = document.elementFromPoint(middlePointX, middlePointY);
return elementAtPoint && domElement !== elementAtPoint && !domElement.contains(elementAtPoint);
return !!elementAtPoint && domElement !== elementAtPoint && !domElement.contains(elementAtPoint);
};

const onElementVisible = (element: HTMLElement, onVisible: () => void) => {
Expand Down
23 changes: 6 additions & 17 deletions src/script/util/DOM/viewportObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,9 @@ const observedElements = new Map();
const tolerance = 0.8;

const onIntersect: IntersectionObserverCallback = entries => {
entries.forEach(({intersectionRatio, intersectionRect, isIntersecting, target: element, rootBounds}) => {
const {onVisible, onChange, requireFullyInView, container, allowBiggerThanViewport} =
observedElements.get(element) || {};
const isFullyInView = () => {
if (container) {
const minHeight = Math.min(container.clientHeight, element.clientHeight) * tolerance;
return intersectionRect.height >= minHeight;
}
return intersectionRatio >= tolerance;
};
entries.forEach(({intersectionRatio, isIntersecting, target: element, rootBounds}) => {
const {onVisible, onChange, requireFullyInView, allowBiggerThanViewport} = observedElements.get(element) || {};
const isFullyInView = intersectionRatio >= tolerance;

const isBiggerThanRoot = () => {
return (
Expand All @@ -40,7 +33,7 @@ const onIntersect: IntersectionObserverCallback = entries => {
);
};

const isVisible = isIntersecting && (!requireFullyInView || isFullyInView() || isBiggerThanRoot());
const isVisible = isIntersecting && (!requireFullyInView || isFullyInView || isBiggerThanRoot());

if (onChange) {
onChange(isVisible);
Expand All @@ -64,16 +57,14 @@ const observer = new IntersectionObserver(onIntersect, options);
* @param onVisible the callback to call when the element appears
* @param requireFullyInView should the element be fully in view
* @param allowBiggerThanViewport should fire when element is bigger than viewport
* @param container the element containing the element
*/
const onElementInViewport = (
element: HTMLElement,
onVisible: Function,
requireFullyInView?: boolean,
allowBiggerThanViewport?: boolean,
container?: HTMLElement,
): void => {
observedElements.set(element, {allowBiggerThanViewport, container, onVisible, requireFullyInView});
observedElements.set(element, {allowBiggerThanViewport, onVisible, requireFullyInView});
return observer.observe(element);
};

Expand All @@ -84,17 +75,15 @@ const onElementInViewport = (
* @param onChange the callback to call when the element intersects or not
* @param requireFullyInView should the element be fully in view
* @param allowBiggerThanViewport should fire when element is bigger than viewport
* @param container the element containing the element
*/
const trackElement = (
element: HTMLElement,
onChange: Function,
container?: HTMLElement,
requireFullyInView = false,
allowBiggerThanViewport = false,
): void => {
if (element) {
observedElements.set(element, {allowBiggerThanViewport, container, onChange, requireFullyInView});
observedElements.set(element, {allowBiggerThanViewport, onChange, requireFullyInView});
return observer.observe(element);
}
};
Expand Down

0 comments on commit e9f5a6c

Please sign in to comment.