Experiment making idle detection global

Hooks are nice but it makes component re-render unnecessarily

Also, idle detection doesn't need to be per-component.
This commit is contained in:
Lim Chee Aun 2023-10-21 12:26:28 +08:00
parent 5a616633c6
commit 749d6880b8
3 changed files with 47 additions and 14 deletions

View file

@ -1,5 +1,6 @@
import './app.css'; import './app.css';
import debounce from 'just-debounce-it';
import { import {
useEffect, useEffect,
useLayoutEffect, useLayoutEffect,
@ -68,6 +69,45 @@ setTimeout(() => {
} }
}, 5000); }, 5000);
(() => {
window.__IDLE__ = false;
const nonIdleEvents = [
'mousemove',
'mousedown',
'resize',
'keydown',
'touchstart',
'pointerdown',
'pointermove',
'wheel',
];
const IDLE_TIME = 5_000; // 5 seconds
const setIdle = debounce(() => {
window.__IDLE__ = true;
}, IDLE_TIME);
const onNonIdle = () => {
window.__IDLE__ = false;
setIdle();
};
nonIdleEvents.forEach((event) => {
window.addEventListener(event, onNonIdle, {
passive: true,
capture: true,
});
});
// document.addEventListener(
// 'visibilitychange',
// () => {
// if (document.visibilityState === 'visible') {
// onNonIdle();
// }
// },
// {
// passive: true,
// },
// );
})();
function App() { function App() {
const snapStates = useSnapshot(states); const snapStates = useSnapshot(states);
const [isLoggedIn, setIsLoggedIn] = useState(false); const [isLoggedIn, setIsLoggedIn] = useState(false);

View file

@ -1,4 +1,3 @@
import { useIdle } from '@uidotdev/usehooks';
import { useCallback, useEffect, useRef, useState } from 'preact/hooks'; import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { InView } from 'react-intersection-observer'; import { InView } from 'react-intersection-observer';
@ -211,21 +210,19 @@ function Timeline({
} }
}, [nearReachEnd, showMore]); }, [nearReachEnd, showMore]);
const idle = useIdle(5000);
console.debug('🧘‍♀️ IDLE', idle);
const loadOrCheckUpdates = useCallback( const loadOrCheckUpdates = useCallback(
async ({ disableHoverCheck = false } = {}) => { async ({ disableIdleCheck = false } = {}) => {
console.log('✨ Load or check updates', { console.log('✨ Load or check updates', {
autoRefresh: snapStates.settings.autoRefresh, autoRefresh: snapStates.settings.autoRefresh,
scrollTop: scrollableRef.current.scrollTop, scrollTop: scrollableRef.current.scrollTop,
disableHoverCheck, disableIdleCheck,
idle, idle: window.__IDLE__,
inBackground: inBackground(), inBackground: inBackground(),
}); });
if ( if (
snapStates.settings.autoRefresh && snapStates.settings.autoRefresh &&
scrollableRef.current.scrollTop === 0 && scrollableRef.current.scrollTop === 0 &&
(disableHoverCheck || idle) && (disableIdleCheck || window.__IDLE__) &&
!inBackground() !inBackground()
) { ) {
console.log('✨ Load updates', snapStates.settings.autoRefresh); console.log('✨ Load updates', snapStates.settings.autoRefresh);
@ -239,7 +236,7 @@ function Timeline({
} }
} }
}, },
[id, idle, loadItems, checkForUpdates, snapStates.settings.autoRefresh], [id, loadItems, checkForUpdates, snapStates.settings.autoRefresh],
); );
const lastHiddenTime = useRef(); const lastHiddenTime = useRef();
@ -249,7 +246,7 @@ function Timeline({
const timeDiff = Date.now() - lastHiddenTime.current; const timeDiff = Date.now() - lastHiddenTime.current;
if (!lastHiddenTime.current || timeDiff > 1000 * 60) { if (!lastHiddenTime.current || timeDiff > 1000 * 60) {
loadOrCheckUpdates({ loadOrCheckUpdates({
disableHoverCheck: true, disableIdleCheck: true,
}); });
} }
} else { } else {

View file

@ -1,6 +1,5 @@
import './notifications.css'; import './notifications.css';
import { useIdle } from '@uidotdev/usehooks';
import { memo } from 'preact/compat'; import { memo } from 'preact/compat';
import { useCallback, useEffect, useRef, useState } from 'preact/hooks'; import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
import { useSearchParams } from 'react-router-dom'; import { useSearchParams } from 'react-router-dom';
@ -172,8 +171,6 @@ function Notifications({ columnMode }) {
} }
}, [nearReachEnd, showMore]); }, [nearReachEnd, showMore]);
const idle = useIdle(5000);
console.debug('🧘‍♀️ IDLE', idle);
const loadUpdates = useCallback(() => { const loadUpdates = useCallback(() => {
console.log('✨ Load updates', { console.log('✨ Load updates', {
autoRefresh: snapStates.settings.autoRefresh, autoRefresh: snapStates.settings.autoRefresh,
@ -185,7 +182,7 @@ function Notifications({ columnMode }) {
if ( if (
snapStates.settings.autoRefresh && snapStates.settings.autoRefresh &&
scrollableRef.current?.scrollTop === 0 && scrollableRef.current?.scrollTop === 0 &&
idle && window.__IDLE__ &&
!inBackground() && !inBackground() &&
snapStates.notificationsShowNew && snapStates.notificationsShowNew &&
uiState !== 'loading' uiState !== 'loading'
@ -193,7 +190,6 @@ function Notifications({ columnMode }) {
loadNotifications(true); loadNotifications(true);
} }
}, [ }, [
idle,
snapStates.notificationsShowNew, snapStates.notificationsShowNew,
snapStates.settings.autoRefresh, snapStates.settings.autoRefresh,
uiState, uiState,