[MM-61995] Correct copying instructions when long-pressing an email in messages & headers (#8798)

* feat: fixed email copy interface

* feat: changed message when long-pressing an email on mobile in messages & headers

* implemented changes: message decriptors outside component; email/url check and cleanHref outside renderContent function
This commit is contained in:
Vasily Belousov 2025-05-12 22:56:38 -05:00 committed by GitHub
parent c983de91fa
commit 7c3914bd13
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 38 additions and 11 deletions

View file

@ -4,7 +4,7 @@
import {useManagedConfig} from '@mattermost/react-native-emm';
import Clipboard from '@react-native-clipboard/clipboard';
import React, {Children, type ReactElement, useCallback} from 'react';
import {useIntl} from 'react-intl';
import {useIntl, defineMessages} from 'react-intl';
import {Alert, StyleSheet, Text, View} from 'react-native';
import urlParse from 'url-parse';
@ -13,7 +13,7 @@ import {useServerUrl} from '@context/server';
import {useTheme} from '@context/theme';
import {bottomSheet, dismissBottomSheet} from '@screens/navigation';
import {handleDeepLink, matchDeepLink} from '@utils/deep_link';
import {bottomSheetSnapPoint} from '@utils/helpers';
import {bottomSheetSnapPoint, isEmail} from '@utils/helpers';
import {preventDoubleTap} from '@utils/tap';
import {normalizeProtocol, tryOpenURL} from '@utils/url';
@ -25,6 +25,17 @@ type MarkdownLinkProps = {
onLinkLongPress?: (url?: string) => void;
}
const messages = defineMessages({
copyEmail: {
id: 'mobile.markdown.link.copy_email',
defaultMessage: 'Copy Email Address',
},
copyURL: {
id: 'mobile.markdown.link.copy_url',
defaultMessage: 'Copy URL',
},
});
const style = StyleSheet.create({
bottomSheet: {
flex: 1,
@ -113,6 +124,9 @@ const MarkdownLink = ({children, experimentalNormalizeMarkdownLinks, href, siteU
return;
}
const cleanHref = href.replace(/^mailto:/, '');
const isEmailLink = isEmail(cleanHref);
const renderContent = () => {
return (
<View
@ -123,10 +137,10 @@ const MarkdownLink = ({children, experimentalNormalizeMarkdownLinks, href, siteU
leftIcon='content-copy'
onPress={() => {
dismissBottomSheet();
Clipboard.setString(href);
Clipboard.setString(cleanHref);
}}
testID='at_mention.bottom_sheet.copy_url'
text={intl.formatMessage({id: 'mobile.markdown.link.copy_url', defaultMessage: 'Copy URL'})}
text={intl.formatMessage(isEmailLink ? messages.copyEmail : messages.copyURL)}
/>
<SlideUpPanelItem
destructive={true}

View file

@ -5,7 +5,7 @@ import {useManagedConfig} from '@mattermost/react-native-emm';
import Clipboard from '@react-native-clipboard/clipboard';
import moment from 'moment';
import React, {useCallback, useMemo} from 'react';
import {useIntl} from 'react-intl';
import {useIntl, defineMessages} from 'react-intl';
import {Platform, StyleSheet, Text, View} from 'react-native';
import CustomStatusExpiry from '@components/custom_status/custom_status_expiry';
@ -20,7 +20,7 @@ import {SNACK_BAR_TYPE} from '@constants/snack_bar';
import {ANDROID_33, OS_VERSION} from '@constants/versions';
import {useTheme} from '@context/theme';
import {bottomSheet, dismissBottomSheet} from '@screens/navigation';
import {bottomSheetSnapPoint} from '@utils/helpers';
import {bottomSheetSnapPoint, isEmail} from '@utils/helpers';
import {getMarkdownBlockStyles, getMarkdownTextStyles} from '@utils/markdown';
import {showSnackBar} from '@utils/snack_bar';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@ -84,6 +84,17 @@ const style = StyleSheet.create({
const headerTestId = 'channel_info.extra.header';
const messages = defineMessages({
copyEmail: {
id: 'mobile.markdown.link.copy_email',
defaultMessage: 'Copy Email Address',
},
copyURL: {
id: 'mobile.markdown.link.copy_url',
defaultMessage: 'Copy URL',
},
});
const onCopy = async (text: string, isLink?: boolean) => {
Clipboard.setString(text);
await dismissBottomSheet();
@ -114,6 +125,10 @@ const Extra = ({channelId, createdAt, createdBy, customStatus, header, isCustomS
const handleLongPress = useCallback((url?: string) => {
if (managedConfig?.copyAndPasteProtection !== 'true') {
const cleanUrl = url?.replace(/^mailto:/, '') || '';
const isEmailLink = isEmail(cleanUrl);
const renderContent = () => (
<View
testID={`${headerTestId}.bottom_sheet`}
@ -134,13 +149,10 @@ const Extra = ({channelId, createdAt, createdBy, customStatus, header, isCustomS
<SlideUpPanelItem
leftIcon='link-variant'
onPress={() => {
onCopy(url!, true);
onCopy(cleanUrl, true);
}}
testID={`${headerTestId}.bottom_sheet.copy_url`}
text={intl.formatMessage({
id: 'mobile.markdown.link.copy_url',
defaultMessage: 'Copy URL',
})}
text={intl.formatMessage(isEmailLink ? messages.copyEmail : messages.copyURL)}
/>
)}
<SlideUpPanelItem

View file

@ -728,6 +728,7 @@
"mobile.markdown.code.plusMoreLines": "+{count, number} more {count, plural, one {line} other {lines}}",
"mobile.markdown.copy_header": "Copy header text",
"mobile.markdown.image.too_large": "Image exceeds max dimensions of {maxWidth} by {maxHeight}:",
"mobile.markdown.link.copy_email": "Copy Email Address",
"mobile.markdown.link.copy_url": "Copy URL",
"mobile.mention.copy_mention": "Copy Mention",
"mobile.message_length.message": "Your current message is too long. Current character count: {count}/{max}",