diff --git a/src/app.jsx b/src/app.jsx index 8e4001aa..391e2e45 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -41,6 +41,7 @@ import Public from './pages/public'; import Search from './pages/search'; import Settings from './pages/settings'; import Status from './pages/status'; +import Trending from './pages/trending'; import Welcome from './pages/welcome'; import { api, @@ -238,6 +239,7 @@ function App() { } /> } /> + } /> } /> {/* } /> */} diff --git a/src/components/icon.jsx b/src/components/icon.jsx index afc6e906..0d37deb6 100644 --- a/src/components/icon.jsx +++ b/src/components/icon.jsx @@ -75,6 +75,7 @@ const ICONS = { refresh: 'mingcute:refresh-2-line', emoji2: 'mingcute:emoji-2-line', filter: 'mingcute:filter-2-line', + chart: 'mingcute:chart-line-line', }; const modules = import.meta.glob('/node_modules/@iconify-icons/mingcute/*.js'); diff --git a/src/components/menu.jsx b/src/components/menu.jsx index 7e36ca83..363e5219 100644 --- a/src/components/menu.jsx +++ b/src/components/menu.jsx @@ -137,6 +137,9 @@ function NavMenu(props) { Federated + + Trending + {authenticated && ( <> diff --git a/src/pages/trending.jsx b/src/pages/trending.jsx new file mode 100644 index 00000000..c92a7e11 --- /dev/null +++ b/src/pages/trending.jsx @@ -0,0 +1,127 @@ +import { Menu, MenuItem } from '@szhsin/react-menu'; +import { useRef } from 'preact/hooks'; +import { useNavigate, useParams } from 'react-router-dom'; +import { useSnapshot } from 'valtio'; + +import Icon from '../components/icon'; +import Timeline from '../components/timeline'; +import { api } from '../utils/api'; +import { filteredItems } from '../utils/filters'; +import states from '../utils/states'; +import { saveStatus } from '../utils/states'; +import useTitle from '../utils/useTitle'; + +const LIMIT = 20; + +function Trending(props) { + const snapStates = useSnapshot(states); + const params = 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 trendIterator = useRef(); + async function fetchTrend(firstLoad) { + if (firstLoad || !trendIterator.current) { + trendIterator.current = masto.v1.trends.listStatuses({ + limit: LIMIT, + }); + } + 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; + } + + async function checkForUpdates() { + try { + const results = await masto.v1.trends + .listStatuses({ + limit: 1, + since_id: latestItem.current, + }) + .next(); + let { value } = results; + value = filteredItems(value, 'public'); + if (value?.length) { + return true; + } + return false; + } catch (e) { + return false; + } + } + + return ( +