"use strict"; var Chatroom = React.createClass({ getInitialState() { return { autoScroll: true }; }, componentDidMount() { let self = this; this.scrollListener = _.debounce((event) => { self.temporarilyDisableAutoScroll(event); }, 300, { leading: false, trailing: true }); let node = React.findDOMNode(this.refs.messageContainer); node.addEventListener('scroll', this.scrollListener); this.scrollToBottom(); }, componentWillUnmount() { node.removeEventListener('scroll', this.scrollListener); clearTimeout(this.disableScrollTimer); }, loadMoreMessages() { var earliestMessage = this.props.messages[0]; if (earliestMessage === undefined) return; socket.emit("message:refresh", { before: earliestMessage.createdAt }); }, sendMessage(message) { socket.emit("newMessage", {message: message}); }, clearAutoScrollTimeout() { if (this.disableScrollTimer) clearTimeout(this.disableScrollTimer); }, temporarilyDisableAutoScroll(event) { let self = this; let node = event.target; if (node) { if (node.scrollHeight - node.scrollTop === node.clientHeight) { this.setState({ autoScroll: true }); this.clearAutoScrollTimeout(); } if (node.scrollHeight - node.scrollTop - node.clientHeight < 50) return; } this.setState({ autoScroll: false }); this.clearAutoScrollTimeout(); this.disableScrollTimer = setTimeout(() => { self.setState({ autoScroll: true }) }, 10000); }, componentDidUpdate() { this.scrollToBottom(); }, scrollToBottom() { if (!this.state.autoScroll) return; let node = React.findDOMNode(this.refs.messageContainer); node.scrollTop = node.scrollHeight; }, render() { let messages = this.props.messages.map(message => { if (message) { return } }); return (
Gather Chat
); } }); var imgurRegex = /^(https?:\/\/i\.imgur\.com\/\S*\.(jpg|png))$/i; var ChatMessage = React.createClass({ mixins: [ ReactAutolink, ReactEmoji ], getInitialState() { return { createdAt: "" } }, updateCreatedAt() { let self = this; if (this.props.message.createdAt) { self.setState({ createdAt: $.timeago(self.props.message.createdAt) }) } }, componentWillMount() { this.updateCreatedAt(); }, componentDidMount() { this.interval = setInterval(this.updateCreatedAt, 60000); }, componentWillUnmount: function () { clearInterval(this.interval); }, messageContent: function () { let self = this; let message = self.props.message.content if (message.match(imgurRegex)) { return (
); } return self.autolink(message, { target: "_blank", rel: "nofollow" }).map((elem) => { if (_.isString(elem)) { return self.emojify(elem); } else { return elem; } }); }, render() { let deleteButton; let user = this.props.user; if (user && user.admin) { deleteButton = ; } return (
  • User Avatar
    {this.props.message.author.username} {deleteButton} {this.state.createdAt}

    {this.messageContent()}

  • ); } }); var DeleteMessageButton = React.createClass({ handleClick (e) { e.preventDefault(); socket.emit("message:delete", { id: this.props.messageId }); }, render() { return ( ); } }) var MessageBar = React.createClass({ sendMessage(content) { socket.emit("message:new", { content: content }); }, getInitialState() { return { statusMessage: null }; }, checkInputLength() { const input = React.findDOMNode(this.refs.content).value; const currentStatusMessage = this.state.statusMessage; if (input.length > 256) { return this.setState({ statusMessage: "Maximum of 256 characters will be saved" }) } if (currentStatusMessage !== null) { this.setState({ statusMessage: null }); } }, handleInputChange() { // Noop, later assigned as debounced method in componentWillMount }, handleSubmit(e) { e.preventDefault(); let content = React.findDOMNode(this.refs.content).value.trim(); if (!content) return; React.findDOMNode(this.refs.content).value = ''; this.sendMessage(content); return; }, componentWillMount() { this.handleInputChange = _.debounce(this.checkInputLength, { leading: false, trailing: true }); }, render() { let statusMessage; if (this.state.statusMessage !== null) { statusMessage =
    {this.state.statusMessage}
    ; } return (
    {statusMessage}
    ); } });