diff options
-rw-r--r-- | api/command_expand_collapse.go | 77 | ||||
-rw-r--r-- | api/command_expand_collapse_test.go | 47 | ||||
-rw-r--r-- | i18n/en.json | 20 | ||||
-rw-r--r-- | model/preference.go | 3 | ||||
-rw-r--r-- | webapp/components/post_view/components/post.jsx | 6 | ||||
-rw-r--r-- | webapp/components/post_view/components/post_body.jsx | 10 | ||||
-rw-r--r-- | webapp/components/post_view/components/post_body_additional_content.jsx | 46 | ||||
-rw-r--r-- | webapp/components/post_view/components/post_list.jsx | 4 | ||||
-rw-r--r-- | webapp/components/post_view/post_view_controller.jsx | 21 | ||||
-rw-r--r-- | webapp/components/user_settings/user_settings_advanced.jsx | 7 | ||||
-rw-r--r-- | webapp/components/user_settings/user_settings_display.jsx | 137 | ||||
-rw-r--r-- | webapp/i18n/en.json | 4 | ||||
-rw-r--r-- | webapp/stores/preference_store.jsx | 6 | ||||
-rw-r--r-- | webapp/utils/constants.jsx | 8 |
14 files changed, 353 insertions, 43 deletions
diff --git a/api/command_expand_collapse.go b/api/command_expand_collapse.go new file mode 100644 index 000000000..6015e8bc1 --- /dev/null +++ b/api/command_expand_collapse.go @@ -0,0 +1,77 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package api + +import ( + "github.com/mattermost/platform/model" +) + +type ExpandProvider struct { +} + +type CollapseProvider struct { +} + +const ( + CMD_EXPAND = "expand" + CMD_COLLAPSE = "collapse" +) + +func init() { + RegisterCommandProvider(&ExpandProvider{}) + RegisterCommandProvider(&CollapseProvider{}) +} + +func (me *ExpandProvider) GetTrigger() string { + return CMD_EXPAND +} + +func (me *CollapseProvider) GetTrigger() string { + return CMD_COLLAPSE +} + +func (me *ExpandProvider) GetCommand(c *Context) *model.Command { + return &model.Command{ + Trigger: CMD_EXPAND, + AutoComplete: true, + AutoCompleteDesc: c.T("api.command_expand.desc"), + DisplayName: c.T("api.command_expand.name"), + } +} + +func (me *CollapseProvider) GetCommand(c *Context) *model.Command { + return &model.Command{ + Trigger: CMD_COLLAPSE, + AutoComplete: true, + AutoCompleteDesc: c.T("api.command_collapse.desc"), + DisplayName: c.T("api.command_collapse.name"), + } +} + +func (me *ExpandProvider) DoCommand(c *Context, channelId string, message string) *model.CommandResponse { + return setCollapsePreference(c, "false") +} + +func (me *CollapseProvider) DoCommand(c *Context, channelId string, message string) *model.CommandResponse { + return setCollapsePreference(c, "true") +} + +func setCollapsePreference(c *Context, value string) *model.CommandResponse { + pref := model.Preference{ + UserId: c.Session.UserId, + Category: model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, + Name: model.PREFERENCE_NAME_COLLAPSE_SETTING, + Value: value, + } + + if result := <-Srv.Store.Preference().Save(&model.Preferences{pref}); result.Err != nil { + return &model.CommandResponse{Text: c.T("api.command_expand_collapse.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} + } + + socketMessage := model.NewMessage("", "", c.Session.UserId, model.ACTION_PREFERENCE_CHANGED) + socketMessage.Add("preference", pref.ToJson()) + go Publish(socketMessage) + + return &model.CommandResponse{} +} diff --git a/api/command_expand_collapse_test.go b/api/command_expand_collapse_test.go new file mode 100644 index 000000000..2303b2fed --- /dev/null +++ b/api/command_expand_collapse_test.go @@ -0,0 +1,47 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package api + +import ( + "testing" + "time" + + "github.com/mattermost/platform/model" +) + +func TestExpandCommand(t *testing.T) { + th := Setup().InitBasic() + Client := th.BasicClient + channel := th.BasicChannel + + r1 := Client.Must(Client.Command(channel.Id, "/expand", false)).Data.(*model.CommandResponse) + if r1 == nil { + t.Fatal("Command failed to execute") + } + + time.Sleep(100 * time.Millisecond) + + p1 := Client.Must(Client.GetPreference(model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, model.PREFERENCE_NAME_COLLAPSE_SETTING)).Data.(*model.Preference) + if p1.Value != "false" { + t.Fatal("preference not updated correctly") + } +} + +func TestCollapseCommand(t *testing.T) { + th := Setup().InitBasic() + Client := th.BasicClient + channel := th.BasicChannel + + r1 := Client.Must(Client.Command(channel.Id, "/collapse", false)).Data.(*model.CommandResponse) + if r1 == nil { + t.Fatal("Command failed to execute") + } + + time.Sleep(100 * time.Millisecond) + + p1 := Client.Must(Client.GetPreference(model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, model.PREFERENCE_NAME_COLLAPSE_SETTING)).Data.(*model.Preference) + if p1.Value != "true" { + t.Fatal("preference not updated correctly") + } +} diff --git a/i18n/en.json b/i18n/en.json index 4894c9665..d340a770a 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -400,6 +400,26 @@ "translation": "echo" }, { + "id": "api.command_collapse.desc", + "translation": "Turn on auto-collapsing of image previews" + }, + { + "id": "api.command_collapse.name", + "translation": "collapse" + }, + { + "id": "api.command_expand.desc", + "translation": "Turn off auto-collapsing of image previews" + }, + { + "id": "api.command_expand_collapse.fail.app_error", + "translation": "An error occured while expanding previews" + }, + { + "id": "api.command_expand.name", + "translation": "expand" + }, + { "id": "api.command_join.desc", "translation": "Join the open channel" }, diff --git a/model/preference.go b/model/preference.go index b2ec93105..22858e043 100644 --- a/model/preference.go +++ b/model/preference.go @@ -14,6 +14,9 @@ const ( PREFERENCE_CATEGORY_TUTORIAL_STEPS = "tutorial_step" PREFERENCE_CATEGORY_ADVANCED_SETTINGS = "advanced_settings" + PREFERENCE_CATEGORY_DISPLAY_SETTINGS = "display_settings" + PREFERENCE_NAME_COLLAPSE_SETTING = "collapse_previews" + PREFERENCE_CATEGORY_LAST = "last" PREFERENCE_NAME_LAST_CHANNEL = "channel" ) 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} /> </div> </div> @@ -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( - <a - className={`post__embed-visibility ${prependToggle ? 'pull-left' : ''}`} - data-expanded={this.state.embedVisible} - aria-label='Toggle Embed Visibility' - onClick={this.toggleEmbedVisibility} - /> - ); - 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( + <a + className={`post__embed-visibility ${prependToggle ? 'pull-left' : ''}`} + data-expanded={this.state.embedVisible} + aria-label='Toggle Embed Visibility' + onClick={this.toggleEmbedVisibility} + /> + ); + + 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 ( - <FormattedMessage - id='user.settings.advance.embed_toggle' - defaultMessage='Show toggle for all embed previews' - /> - ); 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 = [ + <div key='userDisplayCollapseOptions'> + <div className='radio'> + <label> + <input + type='radio' + name='collapseFormat' + checked={collapseFormat[0]} + onChange={this.handleCollapseRadio.bind(this, 'true')} + /> + <FormattedMessage + id='user.settings.display.collapseOn' + defaultMessage='On' + /> + </label> + <br/> + </div> + <div className='radio'> + <label> + <input + type='radio' + name='collapseFormat' + checked={collapseFormat[1]} + onChange={this.handleCollapseRadio.bind(this, 'false')} + /> + <FormattedMessage + id='user.settings.display.collapseOff' + defaultMessage='Off' + /> + </label> + <br/> + </div> + <div> + <br/> + <FormattedMessage + id='user.settings.display.collapseDesc' + defaultMessage='Toggle whether to automatically collapse all image previews.' + /> + </div> + </div> + ]; + + return ( + <SettingItemMax + title={ + <FormattedMessage + id='user.settings.display.collapseDisplay' + defaultMessage='Auto Collapse Previews' + /> + } + inputs={inputs} + submit={this.handleSubmit} + server_error={this.state.serverError} + updateSection={handleUpdateCollapseSection} + /> + ); + } + + let describe; + if (this.state.collapseDisplay === 'true') { + describe = ( + <FormattedMessage + id='user.settings.display.collapseOn' + defaultMessage='On' + /> + ); + } else { + describe = ( + <FormattedMessage + id='user.settings.display.collapseOff' + defaultMessage='Off' + /> + ); + } + + const handleUpdateCollapseSection = () => { + this.props.updateSection('collapse'); + }; + + return ( + <SettingItemMin + title={ + <FormattedMessage + id='user.settings.display.collapseDisplay' + defaultMessage='Auto Collapse Previews' + /> + } + 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 { <div className='divider-dark'/> {nameFormatSection} <div className='divider-dark'/> + {collapseSection} + <div className='divider-dark'/> {messageDisplaySection} <div className='divider-dark'/> {channelDisplayModeSection} diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index 7416d1671..0657b3f8c 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -1290,6 +1290,10 @@ "user.settings.developer.register": "Register New Application", "user.settings.developer.thirdParty": "Open to register a new third-party application", "user.settings.developer.title": "Developer Settings", + "user.settings.display.collapseOn": "On", + "user.settings.display.collapseOff": "Off", + "user.settings.display.collapseDesc": "Toggle whether to automatically collapse all image previews.", + "user.settings.display.collapseDisplay": "Auto Collapse Previews", "user.settings.display.channelDisplayTitle": "Channel Display Mode", "user.settings.display.channeldisplaymode": "Select the width of the center channel.", "user.settings.display.clockDisplay": "Clock Display", diff --git a/webapp/stores/preference_store.jsx b/webapp/stores/preference_store.jsx index d84f2ded9..13e0a94f6 100644 --- a/webapp/stores/preference_store.jsx +++ b/webapp/stores/preference_store.jsx @@ -82,8 +82,8 @@ class PreferenceStoreClass extends EventEmitter { this.preferences.clear(); } - emitChange() { - this.emit(CHANGE_EVENT); + emitChange(category) { + this.emit(CHANGE_EVENT, category); } addChangeListener(callback) { @@ -101,7 +101,7 @@ class PreferenceStoreClass extends EventEmitter { case ActionTypes.RECEIVED_PREFERENCE: { const preference = action.preference; this.setPreference(preference.category, preference.name, preference.value); - this.emitChange(); + this.emitChange(preference.category); break; } case ActionTypes.RECEIVED_PREFERENCES: diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx index 216131eae..3a6098713 100644 --- a/webapp/utils/constants.jsx +++ b/webapp/utils/constants.jsx @@ -547,7 +547,9 @@ export default { MESSAGE_DISPLAY: 'message_display', MESSAGE_DISPLAY_CLEAN: 'clean', MESSAGE_DISPLAY_COMPACT: 'compact', - MESSAGE_DISPLAY_DEFAULT: 'clean' + MESSAGE_DISPLAY_DEFAULT: 'clean', + COLLAPSE_DISPLAY: 'collapse_previews', + COLLAPSE_DISPLAY_DEFAULT: 'false' }, TutorialSteps: { INTRO_SCREENS: 0, @@ -728,10 +730,6 @@ export default { EMBED_PREVIEW: { label: 'embed_preview', description: 'Show preview snippet of links below message' - }, - EMBED_TOGGLE: { - label: 'embed_toggle', - description: 'Show toggle for all embed previews' } }, OVERLAY_TIME_DELAY: 400, |