From 1e245f19c7884e293698fe2e8cd7f46d4dac54c9 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Mon, 6 Jun 2016 13:41:54 -0400 Subject: PLT-3114 Moved preview collapse out of pre-release features (#3206) * Added user setting to auto collapse image previews * Added slash commands for collapsing/expanding image previews * Added translation strings for collapse setting * Add default props for preview collapse setting --- webapp/components/post_view/components/post.jsx | 6 + .../components/post_view/components/post_body.jsx | 10 +- .../components/post_body_additional_content.jsx | 46 ++++--- .../components/post_view/components/post_list.jsx | 4 +- .../components/post_view/post_view_controller.jsx | 21 +++- .../user_settings/user_settings_advanced.jsx | 7 -- .../user_settings/user_settings_display.jsx | 137 ++++++++++++++++++++- 7 files changed, 196 insertions(+), 35 deletions(-) (limited to 'webapp/components') diff --git a/webapp/components/post_view/components/post.jsx b/webapp/components/post_view/components/post.jsx index 2ed062c74..d30216180 100644 --- a/webapp/components/post_view/components/post.jsx +++ b/webapp/components/post_view/components/post.jsx @@ -72,6 +72,10 @@ export default class Post extends React.Component { return true; } + if (nextProps.previewCollapsed !== this.props.previewCollapsed) { + return true; + } + if (!Utils.areObjectsEqual(nextProps.user, this.props.user)) { return true; } @@ -190,6 +194,7 @@ export default class Post extends React.Component { parentPost={parentPost} handleCommentClick={this.handleCommentClick} compactDisplay={this.props.compactDisplay} + previewCollapsed={this.props.previewCollapsed} /> @@ -213,5 +218,6 @@ Post.propTypes = { currentUser: React.PropTypes.object.isRequired, center: React.PropTypes.bool, compactDisplay: React.PropTypes.bool, + previewCollapsed: React.PropTypes.string, commentCount: React.PropTypes.number }; diff --git a/webapp/components/post_view/components/post_body.jsx b/webapp/components/post_view/components/post_body.jsx index eba62ad77..2a2be75a9 100644 --- a/webapp/components/post_view/components/post_body.jsx +++ b/webapp/components/post_view/components/post_body.jsx @@ -25,7 +25,11 @@ export default class PostBody extends React.Component { return true; } - if (!Utils.areObjectsEqual(nextProps.compactDisplay, this.props.compactDisplay)) { + if (nextProps.compactDisplay !== this.props.compactDisplay) { + return true; + } + + if (nextProps.previewCollapsed !== this.props.previewCollapsed) { return true; } @@ -172,6 +176,7 @@ export default class PostBody extends React.Component { post={this.props.post} message={messageWrapper} compactDisplay={this.props.compactDisplay} + previewCollapsed={this.props.previewCollapsed} /> ); } @@ -193,5 +198,6 @@ PostBody.propTypes = { parentPost: React.PropTypes.object, retryPost: React.PropTypes.func.isRequired, handleCommentClick: React.PropTypes.func.isRequired, - compactDisplay: React.PropTypes.bool + compactDisplay: React.PropTypes.bool, + previewCollapsed: React.PropTypes.string }; diff --git a/webapp/components/post_view/components/post_body_additional_content.jsx b/webapp/components/post_view/components/post_body_additional_content.jsx index bd29da962..6757f3b2a 100644 --- a/webapp/components/post_view/components/post_body_additional_content.jsx +++ b/webapp/components/post_view/components/post_body_additional_content.jsx @@ -22,10 +22,14 @@ export default class PostBodyAdditionalContent extends React.Component { this.toggleEmbedVisibility = this.toggleEmbedVisibility.bind(this); this.state = { - embedVisible: true + embedVisible: props.previewCollapsed.startsWith('false') }; } + componentWillReceiveProps(nextProps) { + this.setState({embedVisible: nextProps.previewCollapsed.startsWith('false')}); + } + shouldComponentUpdate(nextProps, nextState) { if (!Utils.areObjectsEqual(nextProps.post, this.props.post)) { return true; @@ -118,25 +122,23 @@ export default class PostBodyAdditionalContent extends React.Component { if (generateEmbed) { let messageWithToggle = []; - if (Utils.isFeatureEnabled(Constants.PRE_RELEASE_FEATURES.EMBED_TOGGLE)) { - // if message has only one line and starts with a link place toggle in this only line - // else - place it in new line between message and embed - const prependToggle = (/^\s*https?:\/\/.*$/).test(this.props.post.message); - messageWithToggle.push( - - ); - if (prependToggle) { - messageWithToggle.push(this.props.message); - } else { - messageWithToggle.unshift(this.props.message); - } - } else { + + // if message has only one line and starts with a link place toggle in this only line + // else - place it in new line between message and embed + const prependToggle = (/^\s*https?:\/\/.*$/).test(this.props.post.message); + messageWithToggle.push( + + ); + + if (prependToggle) { messageWithToggle.push(this.props.message); + } else { + messageWithToggle.unshift(this.props.message); } return ( @@ -156,8 +158,12 @@ export default class PostBodyAdditionalContent extends React.Component { } } +PostBodyAdditionalContent.defaultProps = { + previewCollapsed: 'false' +}; PostBodyAdditionalContent.propTypes = { post: React.PropTypes.object.isRequired, + message: React.PropTypes.element.isRequired, compactDisplay: React.PropTypes.bool, - message: React.PropTypes.element.isRequired + previewCollapsed: React.PropTypes.string }; diff --git a/webapp/components/post_view/components/post_list.jsx b/webapp/components/post_view/components/post_list.jsx index 288609cd9..28be93544 100644 --- a/webapp/components/post_view/components/post_list.jsx +++ b/webapp/components/post_view/components/post_list.jsx @@ -260,6 +260,7 @@ export default class PostList extends React.Component { center={this.props.displayPostsInCenter} commentCount={commentCount} compactDisplay={this.props.compactDisplay} + previewCollapsed={this.props.previewsCollapsed} /> ); @@ -520,5 +521,6 @@ PostList.propTypes = { postsToHighlight: React.PropTypes.object, displayNameType: React.PropTypes.string, displayPostsInCenter: React.PropTypes.bool, - compactDisplay: React.PropTypes.bool + compactDisplay: React.PropTypes.bool, + previewsCollapsed: React.PropTypes.string }; diff --git a/webapp/components/post_view/post_view_controller.jsx b/webapp/components/post_view/post_view_controller.jsx index d2866d8eb..e5a14af36 100644 --- a/webapp/components/post_view/post_view_controller.jsx +++ b/webapp/components/post_view/post_view_controller.jsx @@ -51,7 +51,8 @@ export default class PostViewController extends React.Component { scrollType: ScrollTypes.NEW_MESSAGE, displayNameType: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, 'name_format', 'false'), displayPostsInCenter: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT) === Preferences.CHANNEL_DISPLAY_MODE_CENTERED, - compactDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT) === Preferences.MESSAGE_DISPLAY_COMPACT + compactDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT) === Preferences.MESSAGE_DISPLAY_COMPACT, + previewsCollapsed: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.COLLAPSE_DISPLAY, 'false') }; } @@ -67,11 +68,19 @@ export default class PostViewController extends React.Component { } } - onPreferenceChange() { + onPreferenceChange(category) { + // Bit of a hack to force render when this setting is updated + // regardless of change + let previewSuffix = ''; + if (category === Preferences.CATEGORY_DISPLAY_SETTINGS) { + previewSuffix = '_' + Utils.generateId(); + } + this.setState({ displayNameType: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, 'name_format', 'false'), displayPostsInCenter: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT) === Preferences.CHANNEL_DISPLAY_MODE_CENTERED, - compactDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT) === Preferences.MESSAGE_DISPLAY_COMPACT + compactDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT) === Preferences.MESSAGE_DISPLAY_COMPACT, + previewsCollapsed: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.COLLAPSE_DISPLAY, 'false') + previewSuffix }); } @@ -132,6 +141,7 @@ export default class PostViewController extends React.Component { displayNameType: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, 'name_format', 'false'), displayPostsInCenter: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT) === Preferences.CHANNEL_DISPLAY_MODE_CENTERED, compactDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT) === Preferences.MESSAGE_DISPLAY_COMPACT, + previewsCollapsed: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.COLLAPSE_DISPLAY, 'false'), scrollType: ScrollTypes.NEW_MESSAGE }); } @@ -183,6 +193,10 @@ export default class PostViewController extends React.Component { return true; } + if (nextState.previewsCollapsed !== this.state.previewsCollapsed) { + return true; + } + if (nextState.lastViewed !== this.state.lastViewed) { return true; } @@ -241,6 +255,7 @@ export default class PostViewController extends React.Component { displayNameType={this.state.displayNameType} displayPostsInCenter={this.state.displayPostsInCenter} compactDisplay={this.state.compactDisplay} + previewsCollapsed={this.state.previewsCollapsed} lastViewed={this.state.lastViewed} /> ); diff --git a/webapp/components/user_settings/user_settings_advanced.jsx b/webapp/components/user_settings/user_settings_advanced.jsx index f1a72aa0f..35ab77256 100644 --- a/webapp/components/user_settings/user_settings_advanced.jsx +++ b/webapp/components/user_settings/user_settings_advanced.jsx @@ -234,13 +234,6 @@ export default class AdvancedSettingsDisplay extends React.Component { defaultMessage='Show preview snippet of links below message' /> ); - case 'EMBED_TOGGLE': - return ( - - ); default: return null; } diff --git a/webapp/components/user_settings/user_settings_display.jsx b/webapp/components/user_settings/user_settings_display.jsx index 7036d7389..f7a030e52 100644 --- a/webapp/components/user_settings/user_settings_display.jsx +++ b/webapp/components/user_settings/user_settings_display.jsx @@ -24,7 +24,8 @@ function getDisplayStateFromStores() { nameFormat: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, 'name_format', 'username'), selectedFont: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, 'selected_font', Constants.DEFAULT_FONT), channelDisplayMode: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT), - messageDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT) + messageDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT), + collapseDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.COLLAPSE_DISPLAY, Preferences.COLLAPSE_DISPLAY_DEFAULT) }; } @@ -41,9 +42,11 @@ export default class UserSettingsDisplay extends React.Component { this.updateSection = this.updateSection.bind(this); this.updateState = this.updateState.bind(this); this.deactivate = this.deactivate.bind(this); + this.createCollapseSection = this.createCollapseSection.bind(this); this.state = getDisplayStateFromStores(); } + handleSubmit() { const userId = UserStore.getCurrentId(); @@ -77,8 +80,14 @@ export default class UserSettingsDisplay extends React.Component { name: Preferences.MESSAGE_DISPLAY, value: this.state.messageDisplay }; + const collapseDisplayPreference = { + user_id: userId, + category: Preferences.CATEGORY_DISPLAY_SETTINGS, + name: Preferences.COLLAPSE_DISPLAY, + value: this.state.collapseDisplay + }; - AsyncClient.savePreferences([timePreference, namePreference, fontPreference, channelDisplayModePreference, messageDisplayPreference], + AsyncClient.savePreferences([timePreference, namePreference, fontPreference, channelDisplayModePreference, messageDisplayPreference, collapseDisplayPreference], () => { this.updateSection(''); }, @@ -87,27 +96,38 @@ export default class UserSettingsDisplay extends React.Component { } ); } + handleClockRadio(militaryTime) { this.setState({militaryTime}); } + handleNameRadio(nameFormat) { this.setState({nameFormat}); } + handleChannelDisplayModeRadio(channelDisplayMode) { this.setState({channelDisplayMode}); } + handlemessageDisplayRadio(messageDisplay) { this.setState({messageDisplay}); } + handleFont(selectedFont) { Utils.applyFont(selectedFont); this.setState({selectedFont}); } + + handleCollapseRadio(collapseDisplay) { + this.setState({collapseDisplay}); + } + updateSection(section) { $('.settings-modal .modal-body').scrollTop(0).perfectScrollbar('update'); this.updateState(); this.props.updateSection(section); } + updateState() { const newState = getDisplayStateFromStores(); if (!Utils.areObjectsEqual(newState, this.state)) { @@ -115,9 +135,118 @@ export default class UserSettingsDisplay extends React.Component { this.setState(newState); } } + deactivate() { this.updateState(); } + + createCollapseSection() { + if (this.props.activeSection === 'collapse') { + const collapseFormat = [false, false]; + if (this.state.collapseDisplay === 'true') { + collapseFormat[0] = true; + } else { + collapseFormat[1] = true; + } + + const handleUpdateCollapseSection = (e) => { + this.updateSection(''); + e.preventDefault(); + }; + + const inputs = [ +
+
+ +
+
+
+ +
+
+
+
+ +
+
+ ]; + + return ( + + } + inputs={inputs} + submit={this.handleSubmit} + server_error={this.state.serverError} + updateSection={handleUpdateCollapseSection} + /> + ); + } + + let describe; + if (this.state.collapseDisplay === 'true') { + describe = ( + + ); + } else { + describe = ( + + ); + } + + const handleUpdateCollapseSection = () => { + this.props.updateSection('collapse'); + }; + + return ( + + } + describe={describe} + updateSection={handleUpdateCollapseSection} + /> + ); + } + render() { const serverError = this.state.serverError || null; let clockSection; @@ -127,6 +256,8 @@ export default class UserSettingsDisplay extends React.Component { let languagesSection; let messageDisplaySection; + const collapseSection = this.createCollapseSection(); + if (this.props.activeSection === 'clock') { const clockFormat = [false, false]; if (this.state.militaryTime === 'true') { @@ -729,6 +860,8 @@ export default class UserSettingsDisplay extends React.Component {
{nameFormatSection}
+ {collapseSection} +
{messageDisplaySection}
{channelDisplayModeSection} -- cgit v1.2.3-1-g7c22