import React, { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import qs from 'qs'; import moment from 'moment'; import Message from './Message'; import Spinner from './Spinner'; import UserInfo from './UserInfo'; import { getMessages } from '../api'; /** * @typedef {Object} Query * @property {string} baseUrl * @property {Object=} search * @property {string} pageParam */ /** * @typedef {Object} PageProps * @property {import('history').History} history * @property {import('history').Location} location * @property {import('react-router').match} match * @property {string} search * @property {import('../api').SecureUser} visitor * @property {import('../api').Message[]} msgs */ /** * @param {PageProps} props */ export function Discover(props) { let search = qs.parse(props.location.search.substring(1)); const query = { baseUrl: '/api/messages', search: search, pageParam: search.search ? 'page' : 'before_mid' }; return (); } /** * @param {PageProps} props */ export function Discussions(props) { const query = { baseUrl: '/api/messages/discussions', pageParam: 'to' }; return (); } /** * @param {PageProps} props */ export function Blog(props) { const { user } = props.match.params; let search = qs.parse(props.location.search.substring(1)); search.uname = user; const query = { baseUrl: '/api/messages', search: search, pageParam: search.search ? 'page' : 'before_mid' }; return ( <>
); } /** * @param {PageProps} props */ export function Tag(props) { const { tag } = props.match.params; const query = { baseUrl: '/api/messages', search: { tag: tag }, pageParam: 'before_mid' }; return (); } /** * @param {PageProps} props */ export function Home(props) { const query = { baseUrl: '/api/home', pageParam: 'before_mid' }; return (); } /** * @param {{ authRequired?: boolean, visitor: import('../api').SecureUser, history: import('history').History, location: import('history').Location, msgs: import('../api').Message[], query: Query }} props */ function Feed(props) { const [msgs, setMsgs] = useState([]); const [loading, setLoading] = useState(true); const [nextpage, setNextpage] = useState(null); const [error, setError] = useState(false); useEffect(() => { let loadMessages = (hash = '', filter = '') => { document.body.scrollTop = 0; document.documentElement.scrollTop = 0; setMsgs([]); setLoading(true); const filterParams = qs.parse(filter); let params = Object.assign({}, filterParams || {}, props.query.search || {}); let url = props.query.baseUrl; if (hash) { params.hash = hash; } if (!params.hash && props.authRequired) { props.history.push('/'); } getMessages(url, params) .then(response => { const { data } = response; const { pageParam } = props.query; const lastMessage = data.slice(-1)[0] || {}; const nextpage = getPageParam(pageParam, lastMessage, filterParams); setMsgs(data); setLoading(false); setNextpage(nextpage); }).catch(ex => { setError(true); }); }; loadMessages(props.visitor.hash, props.location.search.substring(1)); }, [props]); let getPageParam = (pageParam, lastMessage, filterParams) => { const pageValue = pageParam === 'before_mid' ? lastMessage.mid : pageParam === 'page' ? (Number(filterParams.page) || 0) + 1 : moment.utc(lastMessage.updated).valueOf(); let newFilter = { ...filterParams }; newFilter[pageParam] = pageValue; return `?${qs.stringify(newFilter)}`; }; const { tag } = qs.parse(location.search.substring(1)) || {}; const nodes = ( <> { tag && (

← All posts with tag {tag}

) } { msgs.map(msg => ) } { msgs.length >= 20 && (

Next →

) } ); return msgs.length > 0 ? (
{nodes}
) : error ?
error
: loading ?
:
No more messages
; }