Chat List: Fix overscroll for desktop and iOS Safari
This commit is contained in:
parent
493e62b5c2
commit
5b40d53771
@ -1998,9 +1998,6 @@ export interface ActionPayloads {
|
|||||||
reason: ApiReportReason;
|
reason: ApiReportReason;
|
||||||
description: string;
|
description: string;
|
||||||
} & WithTabId;
|
} & WithTabId;
|
||||||
toggleAllStoriesHidden: {
|
|
||||||
isHidden: boolean;
|
|
||||||
};
|
|
||||||
openStoryPrivacyEditor: WithTabId | undefined;
|
openStoryPrivacyEditor: WithTabId | undefined;
|
||||||
closeStoryPrivacyEditor: WithTabId | undefined;
|
closeStoryPrivacyEditor: WithTabId | undefined;
|
||||||
editStoryPrivacy: {
|
editStoryPrivacy: {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useRef } from '../../lib/teact/teact';
|
import React, { useEffect, useRef } from '../../lib/teact/teact';
|
||||||
import { forceMutation, requestMutation } from '../../lib/fasterdom/fasterdom';
|
import { forceMutation, requestMutation } from '../../lib/fasterdom/fasterdom';
|
||||||
|
|
||||||
|
import { IS_IOS, IS_SAFARI } from '../../util/windowEnvironment';
|
||||||
import { stopScrollInertia } from '../../util/resetScroll';
|
import { stopScrollInertia } from '../../util/resetScroll';
|
||||||
|
|
||||||
import useLastCallback from '../useLastCallback';
|
import useLastCallback from '../useLastCallback';
|
||||||
@ -8,6 +9,7 @@ import useDebouncedCallback from '../useDebouncedCallback';
|
|||||||
|
|
||||||
const MOUSE_WHEEL_DEBOUNCE = 250;
|
const MOUSE_WHEEL_DEBOUNCE = 250;
|
||||||
const TRIGGER_HEIGHT = 1;
|
const TRIGGER_HEIGHT = 1;
|
||||||
|
const INERTIA_THRESHOLD = 100;
|
||||||
|
|
||||||
export default function useTopOverscroll(
|
export default function useTopOverscroll(
|
||||||
containerRef: React.RefObject<HTMLDivElement>,
|
containerRef: React.RefObject<HTMLDivElement>,
|
||||||
@ -17,10 +19,12 @@ export default function useTopOverscroll(
|
|||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const overscrollTriggerRef = useRef<HTMLDivElement>(null);
|
const overscrollTriggerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const isTriggerJustEnabled = useRef<boolean>(false);
|
const isTriggerJustEnabled = useRef(false);
|
||||||
const lastScrollTopRef = useRef<number>(0);
|
const lastScrollTopRef = useRef(0);
|
||||||
const isTriggerEnabledRef = useRef<boolean>(false);
|
const isTriggerEnabledRef = useRef(false);
|
||||||
const lastIsOnTopRef = useRef<boolean>(true);
|
const lastIsOnTopRef = useRef(true);
|
||||||
|
const lastScrollAtRef = useRef(0);
|
||||||
|
const isReturningOverscrollRef = useRef(false);
|
||||||
|
|
||||||
const enableOverscrollTrigger = useLastCallback((noScrollInertiaStop = false) => {
|
const enableOverscrollTrigger = useLastCallback((noScrollInertiaStop = false) => {
|
||||||
if (isTriggerEnabledRef.current) return;
|
if (isTriggerEnabledRef.current) return;
|
||||||
@ -29,7 +33,7 @@ export default function useTopOverscroll(
|
|||||||
overscrollTriggerRef.current.style.display = 'block';
|
overscrollTriggerRef.current.style.display = 'block';
|
||||||
containerRef.current.scrollTop = TRIGGER_HEIGHT;
|
containerRef.current.scrollTop = TRIGGER_HEIGHT;
|
||||||
|
|
||||||
if (!noScrollInertiaStop) {
|
if (!IS_SAFARI && !noScrollInertiaStop) {
|
||||||
stopScrollInertia(containerRef.current);
|
stopScrollInertia(containerRef.current);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +53,7 @@ export default function useTopOverscroll(
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleScroll = useLastCallback(() => {
|
const handleScroll = useLastCallback(() => {
|
||||||
if (!containerRef.current || !overscrollTriggerRef.current) return;
|
if (!containerRef.current) return;
|
||||||
|
|
||||||
if (isTriggerJustEnabled.current) {
|
if (isTriggerJustEnabled.current) {
|
||||||
isTriggerJustEnabled.current = false;
|
isTriggerJustEnabled.current = false;
|
||||||
@ -61,22 +65,31 @@ export default function useTopOverscroll(
|
|||||||
const isMovingDown = newScrollTop > lastScrollTopRef.current;
|
const isMovingDown = newScrollTop > lastScrollTopRef.current;
|
||||||
const isMovingUp = newScrollTop < lastScrollTopRef.current;
|
const isMovingUp = newScrollTop < lastScrollTopRef.current;
|
||||||
const isOnTop = newScrollTop === 0;
|
const isOnTop = newScrollTop === 0;
|
||||||
|
const lastEventDelay = Date.now() - lastScrollAtRef.current;
|
||||||
|
|
||||||
if (isMovingUp && isOnTop && !isTriggerEnabledRef.current) {
|
if (overscrollTriggerRef.current) {
|
||||||
forceMutation(enableOverscrollTrigger, [containerRef.current, overscrollTriggerRef.current]);
|
if (isOnTop && !isTriggerEnabledRef.current) {
|
||||||
return;
|
forceMutation(enableOverscrollTrigger, [containerRef.current, overscrollTriggerRef.current]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
forceMutation(disableOverscrollTrigger, overscrollTriggerRef.current);
|
||||||
}
|
}
|
||||||
|
|
||||||
forceMutation(disableOverscrollTrigger, overscrollTriggerRef.current);
|
if (
|
||||||
|
isMovingUp && (
|
||||||
if (isMovingUp && lastIsOnTopRef.current) {
|
(lastIsOnTopRef.current && lastEventDelay > INERTIA_THRESHOLD)
|
||||||
|
|| (newScrollTop < 0 && isReturningOverscrollRef.current) // Overscroll repeated by the user
|
||||||
|
)) {
|
||||||
onOverscroll?.();
|
onOverscroll?.();
|
||||||
} else if (isMovingDown) {
|
} else if (isMovingDown && newScrollTop > 0) {
|
||||||
onReset?.();
|
onReset?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
lastScrollTopRef.current = newScrollTop;
|
lastScrollTopRef.current = newScrollTop;
|
||||||
lastIsOnTopRef.current = isOnTop;
|
lastIsOnTopRef.current = isOnTop;
|
||||||
|
lastScrollAtRef.current = Date.now();
|
||||||
|
isReturningOverscrollRef.current = isMovingDown && newScrollTop < 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle non-scrollable container
|
// Handle non-scrollable container
|
||||||
@ -113,7 +126,7 @@ export default function useTopOverscroll(
|
|||||||
};
|
};
|
||||||
}, [containerRef, handleWheel]);
|
}, [containerRef, handleWheel]);
|
||||||
|
|
||||||
return (
|
return !IS_IOS ? (
|
||||||
<div ref={overscrollTriggerRef} className="overscroll-trigger" key="overscroll-trigger" />
|
<div ref={overscrollTriggerRef} className="overscroll-trigger" key="overscroll-trigger" />
|
||||||
);
|
) : undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user