From 711842916d4e7f5b8af89b02c2dee1536a92d389 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Fri, 5 May 2023 17:53:16 +0800 Subject: [PATCH] New experiment: auto refresh --- src/components/timeline.jsx | 61 +++++++++++++++++++++++----------- src/pages/notifications.jsx | 41 ++++++++++++++++++++++- src/pages/settings.jsx | 12 +++++++ src/utils/states.js | 4 +++ src/utils/useInterval.js | 11 +++--- src/utils/usePageVisibility.js | 5 ++- 6 files changed, 105 insertions(+), 29 deletions(-) diff --git a/src/components/timeline.jsx b/src/components/timeline.jsx index e7607257..500db726 100644 --- a/src/components/timeline.jsx +++ b/src/components/timeline.jsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'preact/hooks'; +import { useCallback, useEffect, useRef, useState } from 'preact/hooks'; import { useHotkeys } from 'react-hotkeys-hook'; import { InView } from 'react-intersection-observer'; import { useDebouncedCallback } from 'use-debounce'; @@ -35,6 +35,7 @@ function Timeline({ allowFilters, refresh, }) { + const snapStates = useSnapshot(states); const [items, setItems] = useState([]); const [uiState, setUIState] = useState('default'); const [showMore, setShowMore] = useState(false); @@ -203,41 +204,51 @@ function Timeline({ } }, [nearReachEnd, showMore]); + const isHovering = useRef(false); + const loadOrCheckUpdates = useCallback( + async ({ disableHoverCheck = false } = {}) => { + console.log('✨ Load or check updates', snapStates.settings.autoRefresh); + if ( + snapStates.settings.autoRefresh && + scrollableRef.current.scrollTop === 0 && + (disableHoverCheck || !isHovering.current) && + !inBackground() + ) { + console.log('✨ Load updates', snapStates.settings.autoRefresh); + loadItems(true); + } else { + console.log('✨ Check updates', snapStates.settings.autoRefresh); + const hasUpdate = await checkForUpdates(); + if (hasUpdate) { + console.log('✨ Has new updates', id); + setShowNew(true); + } + } + }, + [id, loadItems, checkForUpdates, snapStates.settings.autoRefresh], + ); + const lastHiddenTime = useRef(); usePageVisibility( (visible) => { if (visible) { const timeDiff = Date.now() - lastHiddenTime.current; if (!lastHiddenTime.current || timeDiff > 1000 * 60) { - (async () => { - console.log('✨ Check updates'); - const hasUpdate = await checkForUpdates(); - if (hasUpdate) { - console.log('✨ Has new updates', id); - setShowNew(true); - } - })(); + loadOrCheckUpdates({ + disableHoverCheck: true, + }); } } else { lastHiddenTime.current = Date.now(); } setVisible(visible); }, - [checkForUpdates], + [checkForUpdates, loadOrCheckUpdates, snapStates.settings.autoRefresh], ); // checkForUpdates interval useInterval( - () => { - (async () => { - console.log('✨ Check updates'); - const hasUpdate = await checkForUpdates(); - if (hasUpdate) { - console.log('✨ Has new updates', id); - setShowNew(true); - } - })(); - }, + loadOrCheckUpdates, visible && !showNew ? checkForUpdatesInterval : null, ); @@ -254,6 +265,12 @@ function Timeline({ oRef.current = node; }} tabIndex="-1" + onPointerEnter={(e) => { + isHovering.current = true; + }} + onPointerLeave={() => { + isHovering.current = false; + }} >
*'); +} + export default Timeline; diff --git a/src/pages/notifications.jsx b/src/pages/notifications.jsx index d1a983b4..469b2f60 100644 --- a/src/pages/notifications.jsx +++ b/src/pages/notifications.jsx @@ -1,7 +1,7 @@ import './notifications.css'; import { memo } from 'preact/compat'; -import { useEffect, useRef, useState } from 'preact/hooks'; +import { useCallback, useEffect, useRef, useState } from 'preact/hooks'; import { useSnapshot } from 'valtio'; import Icon from '../components/icon'; @@ -95,6 +95,33 @@ function Notifications() { } }, [nearReachEnd, showMore]); + const isHovering = useRef(false); + const loadUpdates = useCallback(() => { + console.log('✨ Load updates', { + autoRefresh: snapStates.settings.autoRefresh, + scrollTop: scrollableRef.current?.scrollTop === 0, + isHovering: isHovering.current, + inBackground: inBackground(), + notificationsShowNew: snapStates.notificationsShowNew, + uiState, + }); + if ( + snapStates.settings.autoRefresh && + scrollableRef.current?.scrollTop === 0 && + !isHovering.current && + !inBackground() && + snapStates.notificationsShowNew && + uiState !== 'loading' + ) { + loadNotifications(true); + } + }, [ + snapStates.notificationsShowNew, + snapStates.settings.autoRefresh, + uiState, + ]); + useEffect(loadUpdates, [snapStates.notificationsShowNew]); + const todayDate = new Date(); const yesterdayDate = new Date(todayDate - 24 * 60 * 60 * 1000); let currentDay = new Date(); @@ -110,6 +137,14 @@ function Notifications() { class="deck-container" ref={scrollableRef} tabIndex="-1" + onPointerEnter={() => { + console.log('👆 Pointer enter'); + isHovering.current = true; + }} + onPointerLeave={() => { + console.log('👇 Pointer leave'); + isHovering.current = false; + }} >
*'); +} + export default memo(Notifications); diff --git a/src/pages/settings.jsx b/src/pages/settings.jsx index 2b09b0e6..9dbad5da 100644 --- a/src/pages/settings.jsx +++ b/src/pages/settings.jsx @@ -147,6 +147,18 @@ function Settings({ onClose }) {

Experiments

    +
  • + +