summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2016-06-06 13:41:54 -0400
committerCorey Hulen <corey@hulen.com>2016-06-06 10:41:54 -0700
commit1e245f19c7884e293698fe2e8cd7f46d4dac54c9 (patch)
treeacdedf465346c9ad8b416c3e4604a9979e829aea
parent629b49a119cf58451a80e4667a6f876bea00e6aa (diff)
downloadchat-1e245f19c7884e293698fe2e8cd7f46d4dac54c9.tar.gz
chat-1e245f19c7884e293698fe2e8cd7f46d4dac54c9.tar.bz2
chat-1e245f19c7884e293698fe2e8cd7f46d4dac54c9.zip
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
-rw-r--r--api/command_expand_collapse.go77
-rw-r--r--api/command_expand_collapse_test.go47
-rw-r--r--i18n/en.json20
-rw-r--r--model/preference.go3
-rw-r--r--webapp/components/post_view/components/post.jsx6
-rw-r--r--webapp/components/post_view/components/post_body.jsx10
-rw-r--r--webapp/components/post_view/components/post_body_additional_content.jsx46
-rw-r--r--webapp/components/post_view/components/post_list.jsx4
-rw-r--r--webapp/components/post_view/post_view_controller.jsx21
-rw-r--r--webapp/components/user_settings/user_settings_advanced.jsx7
-rw-r--r--webapp/components/user_settings/user_settings_display.jsx137
-rw-r--r--webapp/i18n/en.json4
-rw-r--r--webapp/stores/preference_store.jsx6
-rw-r--r--webapp/utils/constants.jsx8
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,