diff --git a/src/app.jsx b/src/app.jsx index e86df9bc..cf65ec63 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -103,6 +103,99 @@ async function startStream() { }; } +function startVisibility() { + const handleVisibilityChange = () => { + if (document.hidden) { + const timestamp = Date.now(); + store.session.set('lastHidden', timestamp); + } else { + const timestamp = Date.now(); + const lastHidden = store.session.get('lastHidden'); + const diff = timestamp - lastHidden; + const diffMins = Math.round(diff / 1000 / 60); + if (diffMins > 1) { + console.log('visible', { lastHidden, diffMins }); + setTimeout(() => { + // Buffer for WS reconnect + (async () => { + try { + const fetchHome = masto.timelines.fetchHome({ + limit: 2, + // Need 2 because "new posts" only appear when there are 2 or more + }); + const fetchNotifications = masto.notifications + .iterate({ + limit: 1, + }) + .next(); + + const newStatuses = await fetchHome; + if ( + newStatuses.value.length && + newStatuses.value[0].id !== states.home[0].id + ) { + states.homeNew = newStatuses.value.map((status) => { + states.statuses.set(status.id, status); + if (status.reblog) { + states.statuses.set(status.reblog.id, status.reblog); + } + return { + id: status.id, + reblog: status.reblog?.id, + reply: !!status.inReplyToAccountId, + }; + }); + } + + const newNotifications = await fetchNotifications; + if (newNotifications.value.length) { + const notification = newNotifications.value[0]; + const inNotificationsNew = states.notificationsNew.find( + (n) => n.id === notification.id, + ); + const inNotifications = states.notifications.find( + (n) => n.id === notification.id, + ); + if (!inNotificationsNew && !inNotifications) { + states.notificationsNew.unshift(notification); + } + + if ( + notification.status && + !states.statuses.has(notification.status.id) + ) { + states.statuses.set( + notification.status.id, + notification.status, + ); + if ( + notification.status.reblog && + !states.statuses.has(notification.status.reblog.id) + ) { + states.statuses.set( + notification.status.reblog.id, + notification.status.reblog, + ); + } + } + } + } catch (e) { + // Silently fail + console.error(e); + } + })(); + }, 100); + } + } + }; + document.addEventListener('visibilitychange', handleVisibilityChange); + return { + stop: () => { + document.removeEventListener('visibilitychange', handleVisibilityChange); + }, + }; +} + export function App() { const snapStates = useSnapshot(states); const [isLoggedIn, setIsLoggedIn] = useState(false); @@ -210,6 +303,7 @@ export function App() { if (isLoggedIn) { requestAnimationFrame(() => { startStream(); + startVisibility(); // Collect instance info (async () => { diff --git a/src/pages/home.jsx b/src/pages/home.jsx index 99a2792e..f19d0598 100644 --- a/src/pages/home.jsx +++ b/src/pages/home.jsx @@ -7,7 +7,6 @@ import Icon from '../components/icon'; import Loader from '../components/loader'; import Status from '../components/status'; import states from '../utils/states'; -import store from '../utils/store'; const LIMIT = 20; @@ -70,56 +69,6 @@ function Home({ hidden }) { loadStatuses(true); }, []); - useEffect(() => { - const handleVisibilityChange = () => { - if (document.hidden) { - const timestamp = Date.now(); - store.session.set('lastHidden', timestamp); - } else { - const timestamp = Date.now(); - const lastHidden = store.session.get('lastHidden'); - const diff = timestamp - lastHidden; - const diffMins = Math.round(diff / 1000 / 60); - if (diffMins > 1) { - console.log('visible', { lastHidden, diffMins }); - setUIState('loading'); - setTimeout(() => { - (async () => { - const newStatuses = await masto.timelines.fetchHome({ - limit: 2, - // Need 2 because "new posts" only appear when there are 2 or more - }); - if ( - newStatuses.value.length && - newStatuses.value[0].id !== states.home[0].id - ) { - states.homeNew = newStatuses.value.map((status) => { - states.statuses.set(status.id, status); - if (status.reblog) { - states.statuses.set(status.reblog.id, status.reblog); - } - return { - id: status.id, - reblog: status.reblog?.id, - reply: !!status.inReplyToAccountId, - }; - }); - } - setUIState('default'); - })(); - // loadStatuses(true); - // states.homeNew = []; - }, 100); - } - } - }; - document.addEventListener('visibilitychange', handleVisibilityChange); - return () => { - document.removeEventListener('visibilitychange', handleVisibilityChange); - setUIState('default'); - }; - }, []); - const scrollableRef = useRef(); return (