import './notifications.css'; import { Link } from 'preact-router/match'; import { useEffect, useRef, useState } from 'preact/hooks'; import { useSnapshot } from 'valtio'; import Icon from '../components/icon'; import Loader from '../components/loader'; import NameText from '../components/name-text'; import Status from '../components/status'; import states from '../utils/states'; import useTitle from '../utils/useTitle'; /* Notification types ================== mention = Someone mentioned you in their status status = Someone you enabled notifications for has posted a status reblog = Someone boosted one of your statuses follow = Someone followed you follow_request = Someone requested to follow you favourite = Someone favourited one of your statuses poll = A poll you have voted in or created has ended update = A status you interacted with has been edited admin.sign_up = Someone signed up (optionally sent to admins) admin.report = A new report has been filed */ const contentText = { mention: 'mentioned you in their status.', status: 'posted a status.', reblog: 'boosted your status.', follow: 'followed you.', follow_request: 'requested to follow you.', favourite: 'favourited your status.', poll: 'A poll you have voted in or created has ended.', update: 'A status you interacted with has been edited.', }; const LIMIT = 20; function Notification({ notification }) { const { id, type, status, account } = notification; // status = Attached when type of the notification is favourite, reblog, status, mention, poll, or update const actualStatusID = status?.reblog?.id || status?.id; return ( <>

{!/poll|update/i.test(type) && ( <> {' '} )} {contentText[type]}

{status && ( )}
); } function NotificationsList({ notifications, emptyCopy }) { if (!notifications.length && emptyCopy) { return

{emptyCopy}

; } return ( ); } export default () => { useTitle('Notifications'); const snapStates = useSnapshot(states); const [uiState, setUIState] = useState('default'); const [showMore, setShowMore] = useState(false); const notificationsIterator = useRef( masto.notifications.getIterator({ limit: LIMIT, }), ).current; async function fetchNotifications(firstLoad) { const allNotifications = await notificationsIterator.next( firstLoad ? { limit: LIMIT, } : undefined, ); if (allNotifications.value <= 0) { return { done: true }; } const notificationsValues = allNotifications.value.map((notification) => { if (notification.status) { states.statuses.set(notification.status.id, notification.status); } return notification; }); if (firstLoad) { states.notifications = notificationsValues; } else { states.notifications.push(...notificationsValues); } states.notificationsLastFetchTime = Date.now(); console.log(allNotifications); return allNotifications; } const loadNotifications = (firstLoad) => { setUIState('loading'); (async () => { try { const { done } = await fetchNotifications(firstLoad); setShowMore(!done); setUIState('default'); } catch (e) { setUIState('error'); } })(); }; useEffect(() => { loadNotifications(true); }, []); const scrollableRef = useRef(); // Group notifications by today, yesterday, and older const groupedNotifications = snapStates.notifications.reduce( (acc, notification) => { const date = new Date(notification.createdAt); const today = new Date(); const yesterday = new Date(); yesterday.setDate(today.getDate() - 1); if ( date.getDate() === today.getDate() && date.getMonth() === today.getMonth() && date.getFullYear() === today.getFullYear() ) { acc.today.push(notification); } else if ( date.getDate() === yesterday.getDate() && date.getMonth() === yesterday.getMonth() && date.getFullYear() === yesterday.getFullYear() ) { acc.yesterday.push(notification); } else { acc.older.push(notification); } return acc; }, { today: [], yesterday: [], older: [] }, ); console.log(groupedNotifications); return (

Notifications

{snapStates.notificationsNew.length > 0 && ( )}
{snapStates.notifications.length ? ( <>

Today

{groupedNotifications.yesterday.length > 0 && ( <>

Yesterday

)} {groupedNotifications.older.length > 0 && ( <>

Older

)} {showMore && ( )} ) : ( <> {uiState === 'loading' && ( <>

Today

    {Array.from({ length: 5 }).map((_, i) => (
  • ███████████ ████

  • ))}
)} {uiState === 'error' && (

Error loading notifications

)} )}
); };