/** @jsx h */ import { h, Component } from 'preact'; import api from 'common/api'; import { BASE_URL, NODE_ID, COMMENT_NODE_CLASSNAME_PREFIX, DEFAULT_SORT, LS_SORT_KEY, MAX_SHOWN_ROOT_COMMENTS, } from 'common/constants'; import { siteId, url, maxShownComments } from 'common/settings'; import store from 'common/store'; import AuthPanel from 'components/auth-panel'; import BlockedUsers from 'components/blocked-users'; import Comment from 'components/comment'; import Input from 'components/input'; import Preloader from 'components/preloader'; import Thread from 'components/thread'; const IS_MOBILE = /Android|webOS|iPhone|iPad|iPod|Opera Mini|Windows Phone/i.test(navigator.userAgent); export default class Root extends Component { constructor(props) { super(props); let sort; try { sort = localStorage.getItem(LS_SORT_KEY) || DEFAULT_SORT; } catch (e) { sort = DEFAULT_SORT; } this.state = { isLoaded: false, isCommentsListLoading: false, user: {}, sort, commentsShown: maxShownComments || MAX_SHOWN_ROOT_COMMENTS, }; this.addComment = this.addComment.bind(this); this.replaceComment = this.replaceComment.bind(this); this.onSignIn = this.onSignIn.bind(this); this.onSignOut = this.onSignOut.bind(this); this.onBlockedUsersShow = this.onBlockedUsersShow.bind(this); this.onBlockedUsersHide = this.onBlockedUsersHide.bind(this); this.onCommentsDisable = this.onCommentsDisable.bind(this); this.onCommentsEnable = this.onCommentsEnable.bind(this); this.onSortChange = this.onSortChange.bind(this); this.onUnblockSomeone = this.onUnblockSomeone.bind(this); this.checkUrlHash = this.checkUrlHash.bind(this); this.showMore = this.showMore.bind(this); } componentWillMount() { store.onUpdate('comments', comments => this.setState({ comments })); store.onUpdate('info', info => this.setState({ info })); } componentDidMount() { const { sort } = this.state; api.getConfig().then(config => { store.set('config', config); this.setState({ config }); }); Promise.all([ api .getUser() .then(data => store.set('user', data)) .catch(() => store.set('user', {})), api .getPostComments({ sort, url }) .then(({ comments = [], info = {} } = {}) => { store.set('comments', comments); store.set('info', info); }) .catch(() => store.set('comments', [])), ]).finally(() => { this.setState({ isLoaded: true, user: store.get('user'), }); setTimeout(this.checkUrlHash); window.addEventListener('hashchange', this.checkUrlHash); }); } checkUrlHash(e) { const hash = e ? `#${e.newURL.split('#')[1]}` : window.location.hash; if (hash.indexOf(`#${COMMENT_NODE_CLASSNAME_PREFIX}`) === 0) { if (e) e.preventDefault(); const comment = document.querySelector(hash); if (comment) { setTimeout(() => { window.parent.postMessage(JSON.stringify({ scrollTo: comment.getBoundingClientRect().top }), '*'); }, 500); } } } onSignOut() { api.logOut().then(() => { store.set('user', {}); this.setState({ user: {} }); }); } onSignIn(provider) { const newWindow = window.open( `${BASE_URL}/auth/${provider}/login?from=${encodeURIComponent( location.origin + location.pathname + '?selfClose' )}&site=${siteId}` ); let secondsPass = 0; const checkMsDelay = 300; const checkInterval = setInterval(() => { let shouldProceed; secondsPass += checkMsDelay; try { shouldProceed = newWindow.closed || secondsPass > 30000; } catch (e) {} if (shouldProceed) { clearInterval(checkInterval); api .getUser() .then(user => { store.set('user', user); this.setState({ user }); }) .catch(() => {}); // TODO: we need to handle it and write error to user } }, checkMsDelay); } onBlockedUsersShow() { api.getBlocked().then(bannedUsers => { this.setState({ bannedUsers, isBlockedVisible: true }); }); } onCommentsEnable() { api.enableComments(siteId, url).then(() => { const info = store.get('info'); info.read_only = false; this.setState({ info }); }); } onCommentsDisable() { api.disableComments(siteId, url).then(() => { const info = store.get('info'); info.read_only = true; this.setState({ info }); }); } onBlockedUsersHide() { const { wasSomeoneUnblocked, sort } = this.state; // if someone was unblocked let's reload comments if (wasSomeoneUnblocked) { api.getPostComments({ sort, url }).then(({ comments, info } = {}) => { store.set('comments', comments); store.set('info', info); }); } this.setState({ isBlockedVisible: false, wasSomeoneUnblocked: false, }); } onSortChange(sort) { if (sort === this.state.sort) return; this.setState({ sort, isCommentsListLoading: true }); try { localStorage.setItem(LS_SORT_KEY, sort); } catch (e) { // can't save; ignore it } api .getPostComments({ sort, url }) .then(({ comments, info } = {}) => { store.set('comments', comments); store.set('info', info); }) .finally(() => { this.setState({ isCommentsListLoading: false }); }); } onUnblockSomeone() { this.setState({ wasSomeoneUnblocked: true }); } addComment(comment) { store.addComment(comment); } replaceComment(comment) { store.replaceComment(comment); } showMore() { this.setState({ commentsShown: this.state.commentsShown + MAX_SHOWN_ROOT_COMMENTS, }); } render( props, { config = {}, comments = [], info = {}, user, sort, isLoaded, isBlockedVisible, isCommentsListLoading, bannedUsers, commentsShown, } ) { if (!isLoaded) { return (
Powered by{' '} Remark42