diff --git a/app/components/message_attachments/__snapshots__/attachment_footer.test.js.snap b/app/components/message_attachments/__snapshots__/attachment_footer.test.js.snap
new file mode 100644
index 0000000000..5dc1bfdb1a
--- /dev/null
+++ b/app/components/message_attachments/__snapshots__/attachment_footer.test.js.snap
@@ -0,0 +1,109 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AttachmentFooter it matches snapshot when both footer and footer_icon are provided 1`] = `
+
+
+
+ This is the footer!
+
+
+`;
+
+exports[`AttachmentFooter it matches snapshot when footer text is provided 1`] = `
+
+
+ This is the footer!
+
+
+`;
+
+exports[`AttachmentFooter it matches snapshot when no footer is provided 1`] = `""`;
+
+exports[`AttachmentFooter it matches snapshot when only the footer icon is provided 1`] = `""`;
+
+exports[`AttachmentFooter it matches snapshot when the footer is longer than the maximum length 1`] = `
+
+
+
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa…
+
+
+`;
diff --git a/app/components/message_attachments/attachment_footer.js b/app/components/message_attachments/attachment_footer.js
new file mode 100644
index 0000000000..51f072514f
--- /dev/null
+++ b/app/components/message_attachments/attachment_footer.js
@@ -0,0 +1,77 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React, {PureComponent} from 'react';
+import {Image, Text, View, Platform} from 'react-native';
+import PropTypes from 'prop-types';
+import truncate from 'lodash/truncate';
+
+import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
+import {MAX_ATTACHMENT_FOOTER_LENGTH} from 'app/constants/attachment';
+
+export default class AttachmentFooter extends PureComponent {
+ static propTypes = {
+ text: PropTypes.string,
+ icon: PropTypes.string,
+ theme: PropTypes.object.isRequired,
+ };
+
+ render() {
+ const {
+ text,
+ icon,
+ theme,
+ } = this.props;
+
+ if (!text) {
+ return null;
+ }
+
+ const style = getStyleSheet(theme);
+
+ return (
+
+ {Boolean(icon) &&
+
+ }
+
+ {truncate(text, {length: MAX_ATTACHMENT_FOOTER_LENGTH, omission: '…'})}
+
+
+ );
+ }
+}
+
+const getStyleSheet = makeStyleSheetFromTheme((theme) => {
+ return {
+ container: {
+ flex: 1,
+ flexDirection: 'row',
+ marginTop: 5,
+ },
+ icon: {
+ height: 12,
+ width: 12,
+ marginRight: 5,
+ ...Platform.select({
+ ios: {
+ marginTop: 1,
+ },
+ android: {
+ marginTop: 2,
+ },
+ }),
+ },
+ text: {
+ color: changeOpacity(theme.centerChannelColor, 0.5),
+ fontSize: 11,
+ },
+ };
+});
diff --git a/app/components/message_attachments/attachment_footer.test.js b/app/components/message_attachments/attachment_footer.test.js
new file mode 100644
index 0000000000..7bf46be1b4
--- /dev/null
+++ b/app/components/message_attachments/attachment_footer.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 {shallow} from 'enzyme';
+
+import {MAX_ATTACHMENT_FOOTER_LENGTH} from 'app/constants/attachment';
+import AttachmentFooter from './attachment_footer';
+
+import Preferences from 'mattermost-redux/constants/preferences';
+
+describe('AttachmentFooter', () => {
+ const baseProps = {
+ text: 'This is the footer!',
+ icon: 'https://images.com/image.png',
+ theme: Preferences.THEMES.default,
+ };
+
+ test('it matches snapshot when no footer is provided', () => {
+ const props = {
+ ...baseProps,
+ text: undefined,
+ icon: undefined,
+ };
+
+ const wrapper = shallow();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('it matches snapshot when footer text is provided', () => {
+ const props = {
+ ...baseProps,
+ icon: undefined,
+ };
+
+ const wrapper = shallow();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('it matches snapshot when only the footer icon is provided', () => {
+ const props = {
+ ...baseProps,
+ text: undefined,
+ };
+
+ const wrapper = shallow();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('it matches snapshot when both footer and footer_icon are provided', () => {
+ const wrapper = shallow();
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('it matches snapshot when the footer is longer than the maximum length', () => {
+ const props = {
+ ...baseProps,
+ text: 'a'.repeat(MAX_ATTACHMENT_FOOTER_LENGTH + 1),
+ };
+
+ const wrapper = shallow();
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/app/components/message_attachments/message_attachment.js b/app/components/message_attachments/message_attachment.js
index 5e544b6c8c..143fc63dc4 100644
--- a/app/components/message_attachments/message_attachment.js
+++ b/app/components/message_attachments/message_attachment.js
@@ -16,6 +16,7 @@ import AttachmentPreText from './attachment_pretext';
import AttachmentText from './attachment_text';
import AttachmentThumbnail from './attachment_thumbnail';
import AttachmentTitle from './attachment_title';
+import AttachmentFooter from './attachment_footer';
const STATUS_COLORS = {
good: '#00c100',
@@ -104,6 +105,11 @@ export default class MessageAttachment extends PureComponent {
textStyles={textStyles}
theme={theme}
/>
+