import React from 'react'; import { Link } from 'react-router-dom'; import { HashLink } from 'react-router-hash-link'; import { Helmet } from 'react-helmet'; import moment from 'moment'; import localForage from 'localforage'; import { infoLine, ToggleDot } from './utils.js'; class Article extends React.Component { constructor(props) { super(props); const id = this.props.match.params.id; const cache = this.props.cache; if (id in cache) console.log('cache hit'); this.state = { story: cache[id] || false, error: false, collapsed: [], expanded: [], }; } componentDidMount() { const id = this.props.match.params.id; localForage.getItem(id) .then( (value) => { this.setState({ story: value }); } ); fetch('/api/' + id) .then(res => res.json()) .then( (result) => { this.setState({ story: result.story }, () => { const hash = window.location.hash.substring(1); if (hash) { document.getElementById(hash).scrollIntoView(); } }); localForage.setItem(id, result.story); }, (error) => { this.setState({ error: true }); } ); } collapseComment(cid) { this.setState(prevState => ({ ...prevState, collapsed: [...prevState.collapsed, cid], expanded: prevState.expanded.filter(x => x !== cid), })); } expandComment(cid) { this.setState(prevState => ({ ...prevState, collapsed: prevState.collapsed.filter(x => x !== cid), expanded: [...prevState.expanded, cid], })); } countComments(c) { return c.comments.reduce((sum, x) => sum + this.countComments(x), 1); } displayComment(story, c, level) { const cid = c.author + c.date; const collapsed = this.state.collapsed.includes(cid); const expanded = this.state.expanded.includes(cid); const hidden = collapsed || (level == 4 && !expanded); const hasChildren = c.comments.length !== 0; return (

{c.author === story.author ? '[OP]' : ''} {c.author || '[Deleted]'} {' '} | {moment.unix(c.date).fromNow()} {hasChildren && ( hidden ? this.expandComment(cid)}>+ : this.collapseComment(cid)}>– )}

{hidden && hasChildren ?
this.expandComment(cid)}>[show {this.countComments(c) - 1} more]
: c.comments.map(i => this.displayComment(story, i, level + 1)) }
); } render() { const id = this.props.match.params.id; const story = this.state.story; const error = this.state.error; return (
{error &&

Connection error?

} {story ?
{story.title} - QotNews Comments

{story.title}

View article
{infoLine(story)}
{story.comments.map(c => this.displayComment(story, c, 0))}
:

loading...

}
); } } export default Article;