this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fallback to polling if streaming fails

+57 -32
+57 -32
src/components/background-service.jsx
··· 13 13 // - WebSocket to receive notifications when page is visible 14 14 const [visible, setVisible] = useState(true); 15 15 usePageVisibility(setVisible); 16 + const checkLatestNotification = async (masto, instance, skipCheckMarkers) => { 17 + if (states.notificationsLast) { 18 + const notificationsIterator = masto.v1.notifications.list({ 19 + limit: 1, 20 + sinceId: states.notificationsLast.id, 21 + }); 22 + const { value: notifications } = await notificationsIterator.next(); 23 + if (notifications?.length) { 24 + if (skipCheckMarkers) { 25 + states.notificationsShowNew = true; 26 + } else { 27 + let lastReadId; 28 + try { 29 + const markers = await masto.v1.markers.fetch({ 30 + timeline: 'notifications', 31 + }); 32 + lastReadId = markers?.notifications?.lastReadId; 33 + } catch (e) {} 34 + if (lastReadId) { 35 + states.notificationsShowNew = notifications[0].id !== lastReadId; 36 + } else { 37 + states.notificationsShowNew = true; 38 + } 39 + } 40 + } 41 + } 42 + }; 43 + 16 44 useEffect(() => { 17 45 let sub; 46 + let pollNotifications; 18 47 if (isLoggedIn && visible) { 19 48 const { masto, streaming, instance } = api(); 20 49 (async () => { 21 50 // 1. Get the latest notification 22 - if (states.notificationsLast) { 23 - const notificationsIterator = masto.v1.notifications.list({ 24 - limit: 1, 25 - since_id: states.notificationsLast.id, 26 - }); 27 - const { value: notifications } = await notificationsIterator.next(); 28 - if (notifications?.length) { 29 - let lastReadId; 30 - try { 31 - const markers = await masto.v1.markers.fetch({ 32 - timeline: 'notifications', 33 - }); 34 - lastReadId = markers?.notifications?.lastReadId; 35 - } catch (e) {} 36 - if (lastReadId) { 37 - states.notificationsShowNew = notifications[0].id !== lastReadId; 38 - } else { 51 + await checkLatestNotification(masto, instance); 52 + 53 + let hasStreaming = false; 54 + // 2. Start streaming 55 + if (streaming) { 56 + try { 57 + hasStreaming = true; 58 + sub = streaming.user.notification.subscribe(); 59 + console.log('๐ŸŽ Streaming notification', sub); 60 + for await (const entry of sub) { 61 + if (!sub) break; 62 + console.log('๐Ÿ””๐Ÿ”” Notification entry', entry); 63 + if (entry.event === 'notification') { 64 + console.log('๐Ÿ””๐Ÿ”” Notification', entry); 65 + saveStatus(entry.payload, instance, { 66 + skipThreading: true, 67 + }); 68 + } 39 69 states.notificationsShowNew = true; 40 70 } 71 + } catch (e) { 72 + hasStreaming = false; 73 + console.error(e); 41 74 } 42 75 } 43 76 44 - // 2. Start streaming 45 - if (streaming) { 46 - sub = streaming.user.notification.subscribe(); 47 - console.log('๐ŸŽ Streaming notification', sub); 48 - for await (const entry of sub) { 49 - if (!sub) break; 50 - console.log('๐Ÿ””๐Ÿ”” Notification entry', entry); 51 - if (entry.event === 'notification') { 52 - console.log('๐Ÿ””๐Ÿ”” Notification', entry); 53 - saveStatus(entry.payload, instance, { 54 - skipThreading: true, 55 - }); 56 - } 57 - states.notificationsShowNew = true; 58 - } 77 + if (!hasStreaming) { 78 + console.log('๐ŸŽ Streaming failed, fallback to polling'); 79 + // Fallback to polling every minute 80 + pollNotifications = setInterval(() => { 81 + checkLatestNotification(masto, instance, true); 82 + }, 1000 * 60); 59 83 } 60 84 })(); 61 85 } 62 86 return () => { 63 87 sub?.unsubscribe?.(); 64 88 sub = null; 89 + clearInterval(pollNotifications); 65 90 }; 66 91 }, [visible, isLoggedIn]); 67 92