1+ import { Button } from '@material-ui/core' ;
12import IconButton from '@material-ui/core/IconButton' ;
23import { createStyles , Theme , withStyles , WithStyles } from '@material-ui/core/styles' ;
34import Typography from '@material-ui/core/Typography' ;
5+ import { ExpandLess , ExpandMore } from '@material-ui/icons' ;
46import Delete from '@material-ui/icons/Delete' ;
5- import React from 'react' ;
7+ import React , { RefObject } from 'react' ;
68import TimeAgo from 'react-timeago' ;
79import Container from '../common/Container' ;
8- import * as config from '../config' ;
910import { Markdown } from '../common/Markdown' ;
10- import { RenderMode , contentType } from './extras ' ;
11+ import * as config from '../config ' ;
1112import { IMessageExtras } from '../types' ;
13+ import { contentType , RenderMode } from './extras' ;
14+
15+ const PREVIEW_LENGTH = 500 ;
1216
1317const styles = ( theme : Theme ) =>
1418 createStyles ( {
@@ -52,7 +56,12 @@ const styles = (theme: Theme) =>
5256 whiteSpace : 'pre-wrap' ,
5357 } ,
5458 content : {
59+ maxHeight : PREVIEW_LENGTH ,
5560 wordBreak : 'break-all' ,
61+ overflowY : 'hidden' ,
62+ '&.expanded' : {
63+ maxHeight : 'none' ,
64+ } ,
5665 '& p' : {
5766 margin : 0 ,
5867 } ,
@@ -79,6 +88,11 @@ interface IProps {
7988 height : ( height : number ) => void ;
8089}
8190
91+ interface IState {
92+ expanded : boolean ;
93+ isOverflowing : boolean ;
94+ }
95+
8296const priorityColor = ( priority : number ) => {
8397 if ( priority >= 4 && priority <= 7 ) {
8498 return 'rgba(230, 126, 34, 0.7)' ;
@@ -89,14 +103,39 @@ const priorityColor = (priority: number) => {
89103 }
90104} ;
91105
92- class Message extends React . PureComponent < IProps & WithStyles < typeof styles > > {
106+ class Message extends React . PureComponent < IProps & WithStyles < typeof styles > , IState > {
107+ public state = { expanded : false , isOverflowing : false } ;
93108 private node : HTMLDivElement | null = null ;
109+ private previewRef : RefObject < HTMLDivElement > ;
110+
111+ constructor ( props : IProps & WithStyles < typeof styles > ) {
112+ super ( props ) ;
113+ this . previewRef = React . createRef ( ) ;
114+ }
94115
95- public componentDidMount = ( ) =>
116+ public componentDidMount = ( ) => {
117+ if ( this . previewRef . current ) {
118+ this . setState ( {
119+ isOverflowing :
120+ this . previewRef . current . scrollHeight > this . previewRef . current . clientHeight ,
121+ } ) ;
122+ }
123+ this . updateHeightInParent ( ) ;
124+ } ;
125+
126+ public togglePreviewHeight = ( ) => {
127+ this . setState (
128+ ( state ) => ( { expanded : ! state . expanded } ) ,
129+ ( ) => this . updateHeightInParent ( )
130+ ) ;
131+ } ;
132+
133+ private updateHeightInParent = ( ) =>
96134 this . props . height ( this . node ? this . node . getBoundingClientRect ( ) . height : 0 ) ;
97135
98136 private renderContent = ( ) => {
99137 const content = this . props . content ;
138+
100139 switch ( contentType ( this . props . extras ) ) {
101140 case RenderMode . Markdown :
102141 return < Markdown > { content } </ Markdown > ;
@@ -114,6 +153,7 @@ class Message extends React.PureComponent<IProps & WithStyles<typeof styles>> {
114153 < Container
115154 style = { {
116155 display : 'flex' ,
156+ flexWrap : 'wrap' ,
117157 borderLeftColor : priorityColor ( priority ) ,
118158 borderLeftWidth : 6 ,
119159 borderLeftStyle : 'solid' ,
@@ -141,10 +181,28 @@ class Message extends React.PureComponent<IProps & WithStyles<typeof styles>> {
141181 < Delete />
142182 </ IconButton >
143183 </ div >
144- < Typography component = "div" className = { `${ classes . content } content` } >
184+
185+ < Typography
186+ component = "div"
187+ ref = { this . previewRef }
188+ className = { `${ classes . content } content ${
189+ this . state . isOverflowing && this . state . expanded ? 'expanded' : ''
190+ } `} >
145191 { this . renderContent ( ) }
146192 </ Typography >
147193 </ div >
194+ { this . state . isOverflowing && (
195+ < Button
196+ style = { { marginTop : 16 } }
197+ onClick = { ( ) => this . togglePreviewHeight ( ) }
198+ variant = "contained"
199+ color = "primary"
200+ size = "large"
201+ fullWidth = { true }
202+ startIcon = { this . state . expanded ? < ExpandLess /> : < ExpandMore /> } >
203+ { this . state . expanded ? 'Read Less' : 'Read More' }
204+ </ Button >
205+ ) }
148206 </ Container >
149207 </ div >
150208 ) ;
0 commit comments