diff --git a/src/app.jsx b/src/app.jsx index 5bf428d..44ef3d8 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -28,178 +28,7 @@ const { VITE_CLIENT_NAME: CLIENT_NAME } = import.meta.env; window.__STATES__ = states; -async function startStream() { - const stream = await masto.v1.stream.streamUser(); - console.log('STREAM START', { stream }); - stream.on('update', (status) => { - console.log('UPDATE', status); - - const inHomeNew = states.homeNew.find((s) => s.id === status.id); - const inHome = states.home.find((s) => s.id === status.id); - if (!inHomeNew && !inHome) { - states.homeNew.unshift({ - id: status.id, - reblog: status.reblog?.id, - reply: !!status.inReplyToAccountId, - }); - } - - states.statuses.set(status.id, status); - if (status.reblog) { - states.statuses.set(status.reblog.id, status.reblog); - } - }); - stream.on('status.update', (status) => { - console.log('STATUS.UPDATE', status); - states.statuses.set(status.id, status); - if (status.reblog) { - states.statuses.set(status.reblog.id, status.reblog); - } - }); - stream.on('delete', (statusID) => { - console.log('DELETE', statusID); - // states.statuses.delete(statusID); - const s = states.statuses.get(statusID); - if (s) s._deleted = true; - }); - stream.on('notification', (notification) => { - console.log('NOTIFICATION', notification); - - 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, - ); - } - } - }); - - stream.ws.onclose = () => { - console.log('STREAM CLOSED!'); - - requestAnimationFrame(() => { - startStream(); - }); - }; - - return { - stream, - stopStream: () => { - stream.ws.close(); - }, - }; -} - -function startVisibility() { - const handleVisibilityChange = () => { - if (document.visibilityState === '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 firstStatusID = states.home[0]?.id; - const firstNotificationID = states.notifications[0]?.id; - const fetchHome = masto.v1.timelines.listHome({ - limit: 1, - ...(firstStatusID && { sinceId: firstStatusID }), - }); - const fetchNotifications = masto.v1.notifications.list({ - limit: 1, - ...(firstNotificationID && { sinceId: firstNotificationID }), - }); - - const newStatuses = await fetchHome; - if ( - newStatuses.length && - newStatuses[0].id !== states.home[0].id - ) { - states.homeNew = newStatuses.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.length) { - const notification = newNotifications[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() { +function App() { const snapStates = useSnapshot(states); const [isLoggedIn, setIsLoggedIn] = useState(false); const [uiState, setUIState] = useState('loading'); @@ -458,3 +287,176 @@ export function App() { ); } + +async function startStream() { + const stream = await masto.v1.stream.streamUser(); + console.log('STREAM START', { stream }); + stream.on('update', (status) => { + console.log('UPDATE', status); + + const inHomeNew = states.homeNew.find((s) => s.id === status.id); + const inHome = states.home.find((s) => s.id === status.id); + if (!inHomeNew && !inHome) { + states.homeNew.unshift({ + id: status.id, + reblog: status.reblog?.id, + reply: !!status.inReplyToAccountId, + }); + } + + states.statuses.set(status.id, status); + if (status.reblog) { + states.statuses.set(status.reblog.id, status.reblog); + } + }); + stream.on('status.update', (status) => { + console.log('STATUS.UPDATE', status); + states.statuses.set(status.id, status); + if (status.reblog) { + states.statuses.set(status.reblog.id, status.reblog); + } + }); + stream.on('delete', (statusID) => { + console.log('DELETE', statusID); + // states.statuses.delete(statusID); + const s = states.statuses.get(statusID); + if (s) s._deleted = true; + }); + stream.on('notification', (notification) => { + console.log('NOTIFICATION', notification); + + 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, + ); + } + } + }); + + stream.ws.onclose = () => { + console.log('STREAM CLOSED!'); + + requestAnimationFrame(() => { + startStream(); + }); + }; + + return { + stream, + stopStream: () => { + stream.ws.close(); + }, + }; +} + +function startVisibility() { + const handleVisibilityChange = () => { + if (document.visibilityState === '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 firstStatusID = states.home[0]?.id; + const firstNotificationID = states.notifications[0]?.id; + const fetchHome = masto.v1.timelines.listHome({ + limit: 1, + ...(firstStatusID && { sinceId: firstStatusID }), + }); + const fetchNotifications = masto.v1.notifications.list({ + limit: 1, + ...(firstNotificationID && { sinceId: firstNotificationID }), + }); + + const newStatuses = await fetchHome; + if ( + newStatuses.length && + newStatuses[0].id !== states.home[0].id + ) { + states.homeNew = newStatuses.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.length) { + const notification = newNotifications[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 { App };