From 15fc2b76f95bc3c83ce3f5ee0a8142cde5fa6b0b Mon Sep 17 00:00:00 2001 From: Haelwenn Monnier Date: Thu, 27 Sep 2018 15:04:33 +0000 Subject: [PATCH] Show "read more" link on overly long in-stream statuses (#8205) Show "read more" link on overly long in-stream statuses --- app/javascript/mastodon/components/status.js | 2 +- .../mastodon/components/status_content.js | 40 +++++++++++++++++-- .../styles/mastodon/components.scss | 22 ++++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 6c595c712..90c689a75 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -285,7 +285,7 @@ class Status extends ImmutablePureComponent { - + {media} diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js index 81013747e..f221474f3 100644 --- a/app/javascript/mastodon/components/status_content.js +++ b/app/javascript/mastodon/components/status_content.js @@ -6,6 +6,8 @@ import { FormattedMessage } from 'react-intl'; import Permalink from './permalink'; import classnames from 'classnames'; +const MAX_HEIGHT = 322; // 20px * 16 (+ 2px padding at the top) + export default class StatusContent extends React.PureComponent { static contextTypes = { @@ -17,10 +19,12 @@ export default class StatusContent extends React.PureComponent { expanded: PropTypes.bool, onExpandedToggle: PropTypes.func, onClick: PropTypes.func, + collapsable: PropTypes.bool, }; state = { hidden: true, + collapsed: null, // `collapsed: null` indicates that an element doesn't need collapsing, while `true` or `false` indicates that it does (and is/isn't). }; _updateStatusLinks () { @@ -53,6 +57,16 @@ export default class StatusContent extends React.PureComponent { link.setAttribute('target', '_blank'); link.setAttribute('rel', 'noopener'); } + + if ( + this.props.collapsable + && this.props.onClick + && this.state.collapsed === null + && node.clientHeight > MAX_HEIGHT + && this.props.status.get('spoiler_text').length === 0 + ) { + this.setState({ collapsed: true }); + } } componentDidMount () { @@ -113,6 +127,11 @@ export default class StatusContent extends React.PureComponent { } } + handleCollapsedClick = (e) => { + e.preventDefault(); + this.setState({ collapsed: !this.state.collapsed }); + } + setRef = (c) => { this.node = c; } @@ -132,12 +151,19 @@ export default class StatusContent extends React.PureComponent { const classNames = classnames('status__content', { 'status__content--with-action': this.props.onClick && this.context.router, 'status__content--with-spoiler': status.get('spoiler_text').length > 0, + 'status__content--collapsed': this.state.collapsed === true, }); if (isRtl(status.get('search_index'))) { directionStyle.direction = 'rtl'; } + const readMoreButton = ( + + ); + if (status.get('spoiler_text').length > 0) { let mentionsPlaceholder = ''; @@ -167,17 +193,23 @@ export default class StatusContent extends React.PureComponent { ); } else if (this.props.onClick) { - return ( + const output = [
- ); + />, + ]; + + if (this.state.collapsed) { + output.push(readMoreButton); + } + + return output; } else { return (