From 8a9f1f6ccc415f13263ed5b0dde199644a6084be Mon Sep 17 00:00:00 2001 From: Ewe Tek Min Date: Thu, 18 Jul 2019 23:09:47 +0800 Subject: [PATCH] [MM-14303] Able to copy channel header and purpose (#2923) --- .../channel_info/channel_info_header.js | 127 +++++++++++++----- assets/base/i18n/en.json | 2 + 2 files changed, 99 insertions(+), 30 deletions(-) diff --git a/app/screens/channel_info/channel_info_header.js b/app/screens/channel_info/channel_info_header.js index fad941d7a..f5ae75dd1 100644 --- a/app/screens/channel_info/channel_info_header.js +++ b/app/screens/channel_info/channel_info_header.js @@ -4,15 +4,20 @@ import React from 'react'; import PropTypes from 'prop-types'; import { - Text, - View, + Clipboard, Platform, + Text, + TouchableHighlight, + View, } from 'react-native'; +import {intlShape} from 'react-intl'; import ChannelIcon from 'app/components/channel_icon'; import FormattedDate from 'app/components/formatted_date'; import FormattedText from 'app/components/formatted_text'; import Markdown from 'app/components/markdown'; +import mattermostManaged from 'app/mattermost_managed'; +import BottomSheet from 'app/utils/bottom_sheet'; import {getMarkdownTextStyles, getMarkdownBlockStyles} from 'app/utils/markdown'; import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme'; @@ -33,6 +38,51 @@ export default class ChannelInfoHeader extends React.PureComponent { isGroupConstrained: PropTypes.bool, }; + static contextTypes = { + intl: intlShape.isRequired, + }; + + handleLongPress = (text, actionText) => { + const {formatMessage} = this.context.intl; + + const config = mattermostManaged.getCachedConfig(); + + if (config?.copyAndPasteProtection !== 'true') { + const cancelText = formatMessage({id: 'mobile.post.cancel', defaultMessage: 'Cancel'}); + + BottomSheet.showBottomSheetWithOptions({ + options: [actionText, cancelText], + cancelButtonIndex: 1, + }, (value) => { + if (value === 0) { + this.handleCopy(text); + } + }); + } + }; + + handleCopy = (text) => { + Clipboard.setString(text); + } + + handleHeaderLongPress = () => { + const {formatMessage} = this.context.intl; + const {header} = this.props; + this.handleLongPress( + header, + formatMessage({id: 'mobile.channel_info.copy_header', defaultMessage: 'Copy Header'}) + ); + } + + handlePurposeLongPress = () => { + const {formatMessage} = this.context.intl; + const {purpose} = this.props; + this.handleLongPress( + purpose, + formatMessage({id: 'mobile.channel_info.copy_purpose', defaultMessage: 'Copy Purpose'}) + ); + } + render() { const { createAt, @@ -59,7 +109,7 @@ export default class ChannelInfoHeader extends React.PureComponent { return ( - + {purpose.length > 0 && - - + + + + + + } {header.length > 0 && - - + + + + + + } {isGroupConstrained && - + } {creator && - + { container: { backgroundColor: theme.centerChannelBg, marginBottom: 40, - padding: 15, + paddingVertical: 15, borderBottomWidth: 1, borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1), }, @@ -180,5 +244,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => { section: { marginTop: 15, }, + row: { + paddingHorizontal: 15, + }, }; }); diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index 7b742f628..e2074abd0 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -159,6 +159,8 @@ "mobile.channel_info.alertTitleDeleteChannel": "Archive {term}", "mobile.channel_info.alertTitleLeaveChannel": "Leave {term}", "mobile.channel_info.alertYes": "Yes", + "mobile.channel_info.copy_header": "Copy Header", + "mobile.channel_info.copy_purpose": "Copy Purpose", "mobile.channel_info.delete_failed": "We couldn't archive the channel {displayName}. Please check your connection and try again.", "mobile.channel_info.edit": "Edit Channel", "mobile.channel_info.privateChannel": "Private Channel",