{title}
)}{description}
)}import './trending.css'; import { MenuItem } from '@szhsin/react-menu'; import { getBlurHashAverageColor } from 'fast-blurhash'; import { useMemo, useRef, useState } from 'preact/hooks'; import { useNavigate, useParams } from 'react-router-dom'; import { useSnapshot } from 'valtio'; import Icon from '../components/icon'; import Link from '../components/link'; import Menu2 from '../components/menu2'; import RelativeTime from '../components/relative-time'; import Timeline from '../components/timeline'; import { api } from '../utils/api'; import { oklab2rgb, rgb2oklab } from '../utils/color-utils'; import { filteredItems } from '../utils/filters'; import pmem from '../utils/pmem'; import shortenNumber from '../utils/shorten-number'; import states from '../utils/states'; import { saveStatus } from '../utils/states'; import useTitle from '../utils/useTitle'; const LIMIT = 20; const fetchLinks = pmem( (masto) => { return masto.v1.trends.links.list().next(); }, { // News last much longer maxAge: 10 * 60 * 1000, // 10 minutes }, ); function Trending({ columnMode, ...props }) { const snapStates = useSnapshot(states); const params = columnMode ? {} : useParams(); const { masto, instance } = api({ instance: props?.instance || params.instance, }); const title = `Trending (${instance})`; useTitle(title, `/:instance?/trending`); // const navigate = useNavigate(); const latestItem = useRef(); const [hashtags, setHashtags] = useState([]); const [links, setLinks] = useState([]); const trendIterator = useRef(); async function fetchTrend(firstLoad) { if (firstLoad || !trendIterator.current) { trendIterator.current = masto.v1.trends.statuses.list({ limit: LIMIT, }); // Get hashtags try { const iterator = masto.v1.trends.tags.list(); const { value: tags } = await iterator.next(); console.log('tags', tags); if (tags?.length) { setHashtags(tags); } } catch (e) { console.error(e); } // Get links try { const { value } = await fetchLinks(masto); // 4 types available: link, photo, video, rich // Only want links for now const links = value?.filter?.((link) => link.type === 'link'); console.log('links', links); if (links?.length) { setLinks(links); } } catch (e) { console.error(e); } } const results = await trendIterator.current.next(); let { value } = results; if (value?.length) { if (firstLoad) { latestItem.current = value[0].id; } value = filteredItems(value, 'public'); // Might not work here value.forEach((item) => { saveStatus(item, instance); }); } return { ...results, value, }; } async function checkForUpdates() { try { const results = await masto.v1.trends.statuses .list({ limit: 1, // NOT SUPPORTED // since_id: latestItem.current, }) .next(); let { value } = results; value = filteredItems(value, 'public'); if (value?.length && value[0].id !== latestItem.current) { latestItem.current = value[0].id; return true; } return false; } catch (e) { return false; } } const TimelineStart = useMemo(() => { return ( <> {!!hashtags.length && (
)} {!!links.length && ( )} > ); }, [hashtags, links]); return (