diff --git a/app/components/message_attachments/message_attachment.js b/app/components/message_attachments/message_attachment.js
index d057df232..2ccd9f1a0 100644
--- a/app/components/message_attachments/message_attachment.js
+++ b/app/components/message_attachments/message_attachment.js
@@ -13,9 +13,10 @@ import {
View,
} from 'react-native';
-import FormattedText from 'app/components/formatted_text';
import Markdown from 'app/components/markdown';
import ProgressiveImage from 'app/components/progressive_image';
+import ShowMoreButton from 'app/components/show_more_button';
+
import CustomPropTypes from 'app/constants/custom_prop_types';
import ImageCacheManager from 'app/utils/image_cache_manager';
import {previewImageAtIndex, calculateDimensions} from 'app/utils/images';
@@ -103,10 +104,10 @@ export default class MessageAttachment extends PureComponent {
const {height} = event.nativeEvent.layout;
const {height: deviceHeight} = Dimensions.get('window');
- if (height >= (deviceHeight * 1.2)) {
+ if (height >= (deviceHeight * 0.6)) {
this.setState({
isLongText: true,
- maxHeight: (deviceHeight * 0.6),
+ maxHeight: (deviceHeight * 0.4),
});
}
};
@@ -385,23 +386,6 @@ export default class MessageAttachment extends PureComponent {
let text;
if (attachment.text) {
- let moreLessLocale = {id: 'post_attachment.collapse', defaultMessage: 'Show less...'};
- if (collapsed) {
- moreLessLocale = {id: 'post_attachment.more', defaultMessage: 'Show more...'};
- }
-
- let moreLess;
- if (isLongText) {
- moreLess = (
-
- );
- }
-
text = (
- {moreLess}
+ {isLongText &&
+
+ }
);
}
@@ -523,11 +512,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
height: 45,
width: 45,
},
- moreLess: {
- color: theme.linkColor,
- fontSize: 12,
- marginTop: 5,
- },
headingContainer: {
alignSelf: 'stretch',
flexDirection: 'row',
diff --git a/app/components/post_body/post_body.js b/app/components/post_body/post_body.js
index f5ef0166b..5208c955e 100644
--- a/app/components/post_body/post_body.js
+++ b/app/components/post_body/post_body.js
@@ -6,14 +6,12 @@ import PropTypes from 'prop-types';
import {
Dimensions,
Platform,
- Text,
TouchableHighlight,
TouchableOpacity,
View,
} from 'react-native';
import {intlShape} from 'react-intl';
import Icon from 'react-native-vector-icons/Ionicons';
-import LinearGradient from 'react-native-linear-gradient';
import {Posts} from 'mattermost-redux/constants';
@@ -21,6 +19,7 @@ import CombinedSystemMessage from 'app/components/combined_system_message';
import FormattedText from 'app/components/formatted_text';
import Markdown from 'app/components/markdown';
import OptionsContext from 'app/components/options_context';
+import ShowMoreButton from 'app/components/show_more_button';
import {emptyFunction} from 'app/utils/general';
import {getMarkdownTextStyles, getMarkdownBlockStyles} from 'app/utils/markdown';
@@ -336,64 +335,12 @@ export default class PostBody extends PureComponent {
);
};
- renderShowMoreOption = (style) => {
- const {highlight, theme} = this.props;
- const {isLongPost} = this.state;
-
- if (!isLongPost) {
- return null;
- }
-
- const gradientColors = [];
- if (highlight) {
- gradientColors.push(
- changeOpacity(theme.mentionHighlightBg, 0),
- changeOpacity(theme.mentionHighlightBg, 0.15),
- changeOpacity(theme.mentionHighlightBg, 0.5),
- );
- } else {
- gradientColors.push(
- changeOpacity(theme.centerChannelBg, 0),
- changeOpacity(theme.centerChannelBg, 0.75),
- theme.centerChannelBg,
- );
- }
-
- return (
-
-
-
-
-
-
-
- {'+'}
-
-
-
-
-
-
-
- );
- };
-
render() {
const {formatMessage} = this.context.intl;
const {
hasBeenDeleted,
hasBeenEdited,
+ highlight,
isFailed,
isPending,
isPostAddChannelMember,
@@ -496,7 +443,12 @@ export default class PostBody extends PureComponent {
>
{messageComponent}
- {this.renderShowMoreOption(style)}
+ {isLongPost &&
+
+ }
{this.renderPostAdditionalContent(blockStyles, messageStyle, textStyles)}
{this.renderFileAttachments()}
@@ -562,56 +514,5 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
systemMessage: {
opacity: 0.6,
},
- showMoreGradient: {
- flex: 1,
- height: 50,
- position: 'absolute',
- top: -50,
- width: '100%',
- },
- showMoreContainer: {
- alignItems: 'center',
- justifyContent: 'center',
- flex: 1,
- flexDirection: 'row',
- position: 'relative',
- top: -7.5,
- },
- showMoreDividerLeft: {
- backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
- flex: 1,
- height: 1,
- marginRight: 10,
- },
- showMoreDividerRight: {
- backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
- flex: 1,
- height: 1,
- marginLeft: 10,
- },
- showMoreButtonContainer: {
- backgroundColor: theme.centerChannelBg,
- borderColor: changeOpacity(theme.centerChannelColor, 0.2),
- borderRadius: 4,
- borderWidth: 1,
- height: 37,
- paddingHorizontal: 10,
- },
- showMoreButton: {
- alignItems: 'center',
- flex: 1,
- flexDirection: 'row',
- },
- showMorePlusSign: {
- color: theme.linkColor,
- fontSize: 16,
- fontWeight: '600',
- marginRight: 8,
- },
- showMoreText: {
- color: theme.linkColor,
- fontSize: 13,
- fontWeight: '600',
- },
};
});
diff --git a/app/components/show_more_button/__snapshots__/show_more_button.test.js.snap b/app/components/show_more_button/__snapshots__/show_more_button.test.js.snap
new file mode 100644
index 000000000..283dae457
--- /dev/null
+++ b/app/components/show_more_button/__snapshots__/show_more_button.test.js.snap
@@ -0,0 +1,893 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ShowMoreButton should match, button snapshot 1`] = `
+
+
+ +
+
+
+
+`;
+
+exports[`ShowMoreButton should match, button snapshot 2`] = `
+
+
+ -
+
+
+
+`;
+
+exports[`ShowMoreButton should match, full snapshot 1`] = `
+ShallowWrapper {
+ "length": 1,
+ Symbol(enzyme.__root__): [Circular],
+ Symbol(enzyme.__unrendered__): ,
+ Symbol(enzyme.__renderer__): Object {
+ "batchedUpdates": [Function],
+ "getNode": [Function],
+ "render": [Function],
+ "simulateEvent": [Function],
+ "unmount": [Function],
+ },
+ Symbol(enzyme.__node__): Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+
+
+
+ +
+
+
+
+
+
+ ,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "colors": Array [
+ "rgba(47,62,78,0)",
+ "rgba(47,62,78,0.75)",
+ "#2f3e4e",
+ ],
+ "locations": Array [
+ 0,
+ 0.7,
+ 1,
+ ],
+ "style": Object {
+ "flex": 1,
+ "height": 50,
+ "position": "absolute",
+ "top": -50,
+ "width": "100%",
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+
+ +
+
+
+
+ ,
+ ,
+ ],
+ "style": Object {
+ "alignItems": "center",
+ "flex": 1,
+ "flexDirection": "row",
+ "justifyContent": "center",
+ "position": "relative",
+ "top": 10,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "rgba(221,221,221,0.2)",
+ "flex": 1,
+ "height": 1,
+ "marginRight": 10,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "activeOpacity": 0.2,
+ "children":
+
+ +
+
+
+ ,
+ "onPress": [MockFunction],
+ "style": Object {
+ "backgroundColor": "#2f3e4e",
+ "borderColor": "rgba(221,221,221,0.2)",
+ "borderRadius": 4,
+ "borderWidth": 1,
+ "height": 37,
+ "paddingHorizontal": 10,
+ },
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+
+ +
+ ,
+ ,
+ ],
+ "style": Object {
+ "alignItems": "center",
+ "flex": 1,
+ "flexDirection": "row",
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "accessible": true,
+ "allowFontScaling": true,
+ "children": "+",
+ "ellipsizeMode": "tail",
+ "style": Object {
+ "color": undefined,
+ "fontSize": 16,
+ "fontWeight": "600",
+ "marginRight": 8,
+ },
+ },
+ "ref": null,
+ "rendered": "+",
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "defaultMessage": "Show More",
+ "id": "post_info.message.show_more",
+ "style": Object {
+ "color": undefined,
+ "fontSize": 13,
+ "fontWeight": "600",
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "rgba(221,221,221,0.2)",
+ "flex": 1,
+ "height": 1,
+ "marginLeft": 10,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ Symbol(enzyme.__nodes__): Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+
+
+
+ +
+
+
+
+
+
+ ,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "colors": Array [
+ "rgba(47,62,78,0)",
+ "rgba(47,62,78,0.75)",
+ "#2f3e4e",
+ ],
+ "locations": Array [
+ 0,
+ 0.7,
+ 1,
+ ],
+ "style": Object {
+ "flex": 1,
+ "height": 50,
+ "position": "absolute",
+ "top": -50,
+ "width": "100%",
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+
+ +
+
+
+
+ ,
+ ,
+ ],
+ "style": Object {
+ "alignItems": "center",
+ "flex": 1,
+ "flexDirection": "row",
+ "justifyContent": "center",
+ "position": "relative",
+ "top": 10,
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "rgba(221,221,221,0.2)",
+ "flex": 1,
+ "height": 1,
+ "marginRight": 10,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "activeOpacity": 0.2,
+ "children":
+
+ +
+
+
+ ,
+ "onPress": [MockFunction],
+ "style": Object {
+ "backgroundColor": "#2f3e4e",
+ "borderColor": "rgba(221,221,221,0.2)",
+ "borderRadius": 4,
+ "borderWidth": 1,
+ "height": 37,
+ "paddingHorizontal": 10,
+ },
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+
+ +
+ ,
+ ,
+ ],
+ "style": Object {
+ "alignItems": "center",
+ "flex": 1,
+ "flexDirection": "row",
+ },
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "accessible": true,
+ "allowFontScaling": true,
+ "children": "+",
+ "ellipsizeMode": "tail",
+ "style": Object {
+ "color": undefined,
+ "fontSize": 16,
+ "fontWeight": "600",
+ "marginRight": 8,
+ },
+ },
+ "ref": null,
+ "rendered": "+",
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "defaultMessage": "Show More",
+ "id": "post_info.message.show_more",
+ "style": Object {
+ "color": undefined,
+ "fontSize": 13,
+ "fontWeight": "600",
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "rgba(221,221,221,0.2)",
+ "flex": 1,
+ "height": 1,
+ "marginLeft": 10,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ Symbol(enzyme.__options__): Object {
+ "adapter": ReactSixteenAdapter {
+ "options": Object {
+ "enableComponentDidUpdateOnSetState": true,
+ },
+ },
+ },
+}
+`;
diff --git a/app/components/show_more_button/index.js b/app/components/show_more_button/index.js
new file mode 100644
index 000000000..0002f53a2
--- /dev/null
+++ b/app/components/show_more_button/index.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {connect} from 'react-redux';
+
+import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
+
+import ShowMoreButton from './show_more_button';
+
+function mapStateToProps(state) {
+ return {
+ theme: getTheme(state),
+ };
+}
+
+export default connect(mapStateToProps)(ShowMoreButton);
diff --git a/app/components/show_more_button/show_more_button.js b/app/components/show_more_button/show_more_button.js
new file mode 100644
index 000000000..48e783378
--- /dev/null
+++ b/app/components/show_more_button/show_more_button.js
@@ -0,0 +1,142 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React, {PureComponent} from 'react';
+import PropTypes from 'prop-types';
+import {Text, TouchableOpacity, View} from 'react-native';
+import LinearGradient from 'react-native-linear-gradient';
+
+import FormattedText from 'app/components/formatted_text';
+
+import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
+
+export default class ShowMoreButton extends PureComponent {
+ static propTypes = {
+ highlight: PropTypes.bool,
+ onPress: PropTypes.func.isRequired,
+ showMore: PropTypes.bool.isRequired,
+ theme: PropTypes.object.isRequired,
+ };
+
+ static defaultProps = {
+ showMore: true,
+ };
+
+ renderButton(showMore, style) {
+ let sign = '+';
+ let textId = 'post_info.message.show_more';
+ let textMessage = 'Show More';
+ if (!showMore) {
+ sign = '-';
+ textId = 'post_info.message.show_less';
+ textMessage = 'Show Less';
+ }
+
+ return (
+
+ {sign}
+
+
+ );
+ }
+
+ render() {
+ const {highlight, showMore, theme} = this.props;
+ const style = getStyleSheet(theme, showMore);
+
+ let gradientColors = [
+ changeOpacity(theme.centerChannelBg, 0),
+ changeOpacity(theme.centerChannelBg, 0.75),
+ theme.centerChannelBg,
+ ];
+ if (highlight) {
+ gradientColors = [
+ changeOpacity(theme.mentionHighlightBg, 0),
+ changeOpacity(theme.mentionHighlightBg, 0.15),
+ changeOpacity(theme.mentionHighlightBg, 0.5),
+ ];
+ }
+
+ return (
+
+ {showMore &&
+
+ }
+
+
+
+ {this.renderButton(showMore, style)}
+
+
+
+
+ );
+ }
+}
+
+const getStyleSheet = makeStyleSheetFromTheme((theme, showMore) => {
+ return {
+ gradient: {
+ flex: 1,
+ height: 50,
+ position: 'absolute',
+ top: -50,
+ width: '100%',
+ },
+ container: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ flex: 1,
+ flexDirection: 'row',
+ position: 'relative',
+ top: showMore ? -7.5 : 10,
+ },
+ dividerLeft: {
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
+ flex: 1,
+ height: 1,
+ marginRight: 10,
+ },
+ buttonContainer: {
+ backgroundColor: theme.centerChannelBg,
+ borderColor: changeOpacity(theme.centerChannelColor, 0.2),
+ borderRadius: 4,
+ borderWidth: 1,
+ height: 37,
+ paddingHorizontal: 10,
+ },
+ button: {
+ alignItems: 'center',
+ flex: 1,
+ flexDirection: 'row',
+ },
+ sign: {
+ color: theme.linkColor,
+ fontSize: 16,
+ fontWeight: '600',
+ marginRight: 8,
+ },
+ text: {
+ color: theme.linkColor,
+ fontSize: 13,
+ fontWeight: '600',
+ },
+ dividerRight: {
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.2),
+ flex: 1,
+ height: 1,
+ marginLeft: 10,
+ },
+ };
+});
diff --git a/app/components/show_more_button/show_more_button.test.js b/app/components/show_more_button/show_more_button.test.js
new file mode 100644
index 000000000..7c63aa8cd
--- /dev/null
+++ b/app/components/show_more_button/show_more_button.test.js
@@ -0,0 +1,64 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {TouchableOpacity} from 'react-native';
+import {configure, shallow} from 'enzyme';
+import Adapter from 'enzyme-adapter-react-16';
+configure({adapter: new Adapter()});
+
+import LinearGradient from 'react-native-linear-gradient';
+
+import ShowMoreButton from './show_more_button';
+
+describe('ShowMoreButton', () => {
+ const baseProps = {
+ highlight: false,
+ onPress: jest.fn(),
+ showMore: true,
+ theme: {
+ centerChannelBg: '#2f3e4e',
+ centerChannelColor: '#dddddd',
+ },
+ };
+
+ test('should match, full snapshot', () => {
+ const wrapper = shallow(
+
+ );
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('should match, button snapshot', () => {
+ const wrapper = shallow(
+
+ );
+
+ expect(wrapper.instance().renderButton(true, {button: {}, sign: {}, text: {}})).toMatchSnapshot();
+ expect(wrapper.instance().renderButton(false, {button: {}, sign: {}, text: {}})).toMatchSnapshot();
+ });
+
+ test('should LinearGradient exists', () => {
+ const wrapper = shallow(
+
+ );
+
+ expect(wrapper.find(LinearGradient).exists()).toBe(true);
+ wrapper.setProps({showMore: false});
+ expect(wrapper.find(LinearGradient).exists()).toBe(false);
+ });
+
+ test('should call props.onPress on press of TouchableOpacity', () => {
+ const onPress = jest.fn();
+ const wrapper = shallow(
+
+ );
+
+ wrapper.find(TouchableOpacity).props().onPress();
+ expect(onPress).toHaveBeenCalledTimes(1);
+ });
+});