diff --git a/src/components/background-service.jsx b/src/components/background-service.jsx index 927a174..e7d7dcf 100644 --- a/src/components/background-service.jsx +++ b/src/components/background-service.jsx @@ -1,5 +1,6 @@ import { memo } from 'preact/compat'; import { useEffect, useRef, useState } from 'preact/hooks'; +import { useDebouncedCallback } from 'use-debounce'; import { api } from '../utils/api'; import states, { saveStatus } from '../utils/states'; @@ -11,55 +12,62 @@ export default memo(function BackgroundService({ isLoggedIn }) { // - WebSocket to receive notifications when page is visible const [visible, setVisible] = useState(true); usePageVisibility(setVisible); - useEffect(() => { - let sub; - if (isLoggedIn && visible) { - const { masto, streaming, instance } = api(); - (async () => { - // 1. Get the latest notification - if (states.notificationsLast) { - const notificationsIterator = masto.v1.notifications.list({ - limit: 1, - since_id: states.notificationsLast.id, - }); - const { value: notifications } = await notificationsIterator.next(); - if (notifications?.length) { - let lastReadId; - try { - const markers = await masto.v1.markers.fetch({ - timeline: 'notifications', - }); - lastReadId = markers?.notifications?.lastReadId; - } catch (e) {} - if (lastReadId) { - states.notificationsShowNew = notifications[0].id !== lastReadId; - } else { - states.notificationsShowNew = true; - } - } - } - - // 2. Start streaming - if (streaming) { - sub = streaming.user.notification.subscribe(); - console.log('🎏 Streaming notification', sub); - for await (const entry of sub) { - if (!sub) break; - console.log('🔔🔔 Notification entry', entry); - if (entry.event === 'notification') { - console.log('🔔🔔 Notification', entry); - saveStatus(entry.payload, instance, { - skipThreading: true, - }); - } + const subRef = useRef(); + const debouncedStartNotifications = useDebouncedCallback(() => { + const { masto, streaming, instance } = api(); + (async () => { + // 1. Get the latest notification + if (states.notificationsLast) { + const notificationsIterator = masto.v1.notifications.list({ + limit: 1, + since_id: states.notificationsLast.id, + }); + const { value: notifications } = await notificationsIterator.next(); + if (notifications?.length) { + let lastReadId; + try { + const markers = await masto.v1.markers.fetch({ + timeline: 'notifications', + }); + lastReadId = markers?.notifications?.lastReadId; + } catch (e) {} + if (lastReadId) { + states.notificationsShowNew = notifications[0].id !== lastReadId; + } else { states.notificationsShowNew = true; } } - })(); + } + + // 2. Start streaming + if (streaming) { + let sub = (subRef.current = streaming.user.notification.subscribe()); + console.log('🎏 Streaming notification', sub); + for await (const entry of sub) { + if (!sub) break; + console.log('🔔🔔 Notification entry', entry); + if (entry.event === 'notification') { + console.log('🔔🔔 Notification', entry); + saveStatus(entry.payload, instance, { + skipThreading: true, + }); + } + states.notificationsShowNew = true; + } + } + })(); + }, 3000); + useEffect(() => { + // let sub; + if (isLoggedIn && visible) { + debouncedStartNotifications(); } return () => { - sub?.unsubscribe?.(); - sub = null; + // sub?.unsubscribe?.(); + // sub = null; + debouncedStartNotifications?.cancel?.(); + subRef.current?.unsubscribe?.(); + subRef.current = null; }; }, [visible, isLoggedIn]); diff --git a/src/components/timeline.jsx b/src/components/timeline.jsx index 2fe7c0d..a687ab4 100644 --- a/src/components/timeline.jsx +++ b/src/components/timeline.jsx @@ -238,6 +238,10 @@ function Timeline({ }, [id, loadItems, checkForUpdates, snapStates.settings.autoRefresh], ); + const debouncedLoadOrCheckUpdates = useDebouncedCallback( + loadOrCheckUpdates, + 3000, + ); const lastHiddenTime = useRef(); usePageVisibility( @@ -245,12 +249,14 @@ function Timeline({ if (visible) { const timeDiff = Date.now() - lastHiddenTime.current; if (!lastHiddenTime.current || timeDiff > 1000 * 60) { - loadOrCheckUpdates({ + // 1 minute + debouncedLoadOrCheckUpdates({ disableIdleCheck: true, }); } } else { lastHiddenTime.current = Date.now(); + debouncedLoadOrCheckUpdates.cancel(); } setVisible(visible); },