copy header text in channel info implemented (#7605)
* copy header text in channel info implemented * changes fixed
This commit is contained in:
parent
1199c3772c
commit
d8d607257f
4 changed files with 139 additions and 24 deletions
|
|
@ -71,6 +71,7 @@ type MarkdownProps = {
|
|||
textStyles?: MarkdownTextStyles;
|
||||
theme: Theme;
|
||||
value?: string;
|
||||
onLinkLongPress?: (url?: string) => void;
|
||||
}
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
|
|
@ -133,7 +134,7 @@ const Markdown = ({
|
|||
enableInlineLatex, enableLatex, maxNodes,
|
||||
imagesMetadata, isEdited, isReplyPost, isSearchResult, layoutHeight, layoutWidth,
|
||||
location, mentionKeys, minimumHashtagLength = 3, onPostPress, postId, searchPatterns,
|
||||
textStyles = {}, theme, value = '', baseParagraphStyle,
|
||||
textStyles = {}, theme, value = '', baseParagraphStyle, onLinkLongPress,
|
||||
}: MarkdownProps) => {
|
||||
const style = getStyleSheet(theme);
|
||||
const managedConfig = useManagedConfig<ManagedConfig>();
|
||||
|
|
@ -402,7 +403,10 @@ const Markdown = ({
|
|||
|
||||
const renderLink = ({children, href}: {children: ReactElement; href: string}) => {
|
||||
return (
|
||||
<MarkdownLink href={href}>
|
||||
<MarkdownLink
|
||||
href={href}
|
||||
onLinkLongPress={onLinkLongPress}
|
||||
>
|
||||
{children}
|
||||
</MarkdownLink>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ type MarkdownLinkProps = {
|
|||
experimentalNormalizeMarkdownLinks: string;
|
||||
href: string;
|
||||
siteURL: string;
|
||||
onLinkLongPress?: (url?: string) => void;
|
||||
}
|
||||
|
||||
const style = StyleSheet.create({
|
||||
|
|
@ -44,7 +45,7 @@ const parseLinkLiteral = (literal: string) => {
|
|||
return parsed.href;
|
||||
};
|
||||
|
||||
const MarkdownLink = ({children, experimentalNormalizeMarkdownLinks, href, siteURL}: MarkdownLinkProps) => {
|
||||
const MarkdownLink = ({children, experimentalNormalizeMarkdownLinks, href, siteURL, onLinkLongPress}: MarkdownLinkProps) => {
|
||||
const intl = useIntl();
|
||||
const {bottom} = useSafeAreaInsets();
|
||||
const managedConfig = useManagedConfig<ManagedConfig>();
|
||||
|
|
@ -109,6 +110,11 @@ const MarkdownLink = ({children, experimentalNormalizeMarkdownLinks, href, siteU
|
|||
|
||||
const handleLongPress = useCallback(() => {
|
||||
if (managedConfig?.copyAndPasteProtection !== 'true') {
|
||||
if (onLinkLongPress) {
|
||||
onLinkLongPress(href);
|
||||
return;
|
||||
}
|
||||
|
||||
const renderContent = () => {
|
||||
return (
|
||||
<View
|
||||
|
|
@ -145,7 +151,7 @@ const MarkdownLink = ({children, experimentalNormalizeMarkdownLinks, href, siteU
|
|||
theme,
|
||||
});
|
||||
}
|
||||
}, [managedConfig, intl, bottom, theme]);
|
||||
}, [managedConfig, intl, bottom, theme, onLinkLongPress]);
|
||||
|
||||
const renderChildren = experimentalNormalizeMarkdownLinks ? parseChildren() : children;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,29 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {useManagedConfig} from '@mattermost/react-native-emm';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import moment from 'moment';
|
||||
import React, {useMemo} from 'react';
|
||||
import {Text, View} from 'react-native';
|
||||
import React, {useCallback, useMemo} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {Platform, StyleSheet, Text, View} from 'react-native';
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
||||
|
||||
import CustomStatusExpiry from '@components/custom_status/custom_status_expiry';
|
||||
import Emoji from '@components/emoji';
|
||||
import FormattedDate from '@components/formatted_date';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import Markdown from '@components/markdown';
|
||||
import SlideUpPanelItem, {ITEM_HEIGHT} from '@components/slide_up_panel_item';
|
||||
import TouchableWithFeedback from '@components/touchable_with_feedback';
|
||||
import {Screens} from '@constants';
|
||||
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 {getMarkdownBlockStyles, getMarkdownTextStyles} from '@utils/markdown';
|
||||
import {showSnackBar} from '@utils/snack_bar';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
||||
|
|
@ -66,8 +77,30 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
|||
},
|
||||
}));
|
||||
|
||||
const style = StyleSheet.create({
|
||||
bottomSheet: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
const headerTestId = 'channel_info.extra.header';
|
||||
|
||||
const onCopy = async (text: string, isLink?: boolean) => {
|
||||
Clipboard.setString(text);
|
||||
await dismissBottomSheet();
|
||||
if ((Platform.OS === OS_VERSION.ANDROID && Number(Platform.Version) < ANDROID_33) || Platform.OS === OS_VERSION.IOS) {
|
||||
showSnackBar({
|
||||
barType: isLink ? SNACK_BAR_TYPE.LINK_COPIED : SNACK_BAR_TYPE.TEXT_COPIED,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const Extra = ({channelId, createdAt, createdBy, customStatus, header, isCustomStatusEnabled}: Props) => {
|
||||
const intl = useIntl();
|
||||
const {bottom} = useSafeAreaInsets();
|
||||
const theme = useTheme();
|
||||
const managedConfig = useManagedConfig<ManagedConfig>();
|
||||
|
||||
const styles = getStyleSheet(theme);
|
||||
const blockStyles = getMarkdownBlockStyles(theme);
|
||||
const textStyles = getMarkdownTextStyles(theme);
|
||||
|
|
@ -81,6 +114,70 @@ const Extra = ({channelId, createdAt, createdBy, customStatus, header, isCustomS
|
|||
),
|
||||
}), [createdAt, createdBy, theme]);
|
||||
|
||||
const handleLongPress = useCallback((url?: string) => {
|
||||
if (managedConfig?.copyAndPasteProtection !== 'true') {
|
||||
const renderContent = () => (
|
||||
<View
|
||||
testID={`${headerTestId}.bottom_sheet`}
|
||||
style={style.bottomSheet}
|
||||
>
|
||||
<SlideUpPanelItem
|
||||
leftIcon='content-copy'
|
||||
onPress={() => {
|
||||
onCopy(header!);
|
||||
}}
|
||||
testID={`${headerTestId}.bottom_sheet.copy_header_text`}
|
||||
text={intl.formatMessage({
|
||||
id: 'mobile.markdown.copy_header',
|
||||
defaultMessage: 'Copy header text',
|
||||
})}
|
||||
/>
|
||||
{Boolean(url) && (
|
||||
<SlideUpPanelItem
|
||||
leftIcon='link-variant'
|
||||
onPress={() => {
|
||||
onCopy(url!, true);
|
||||
}}
|
||||
testID={`${headerTestId}.bottom_sheet.copy_url`}
|
||||
text={intl.formatMessage({
|
||||
id: 'mobile.markdown.link.copy_url',
|
||||
defaultMessage: 'Copy URL',
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
<SlideUpPanelItem
|
||||
destructive={true}
|
||||
leftIcon='cancel'
|
||||
onPress={() => {
|
||||
dismissBottomSheet();
|
||||
}}
|
||||
testID={`${headerTestId}.bottom_sheet.cancel`}
|
||||
text={intl.formatMessage({
|
||||
id: 'mobile.post.cancel',
|
||||
defaultMessage: 'Cancel',
|
||||
})}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
bottomSheet({
|
||||
closeButtonId: 'close-markdown-link',
|
||||
renderContent,
|
||||
snapPoints: [1, bottomSheetSnapPoint(url ? 3 : 2, ITEM_HEIGHT, bottom)],
|
||||
title: intl.formatMessage({id: 'post.options.title', defaultMessage: 'Options'}),
|
||||
theme,
|
||||
});
|
||||
}
|
||||
}, [
|
||||
header,
|
||||
bottom,
|
||||
theme,
|
||||
intl.formatMessage,
|
||||
managedConfig?.copyAndPasteProtection,
|
||||
]);
|
||||
|
||||
const touchableHandleLongPress = useCallback(() => handleLongPress(), [handleLongPress]);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{isCustomStatusEnabled && Boolean(customStatus) &&
|
||||
|
|
@ -131,25 +228,32 @@ const Extra = ({channelId, createdAt, createdBy, customStatus, header, isCustomS
|
|||
id='channel_info.header'
|
||||
defaultMessage='Header:'
|
||||
style={styles.extraHeading}
|
||||
testID='channel_info.extra.header'
|
||||
/>
|
||||
<Markdown
|
||||
channelId={channelId}
|
||||
baseTextStyle={styles.header}
|
||||
blockStyles={blockStyles}
|
||||
disableBlockQuote={true}
|
||||
disableCodeBlock={true}
|
||||
disableGallery={true}
|
||||
disableHeading={true}
|
||||
disableTables={true}
|
||||
location={Screens.CHANNEL_INFO}
|
||||
textStyles={textStyles}
|
||||
layoutHeight={48}
|
||||
layoutWidth={100}
|
||||
theme={theme}
|
||||
imagesMetadata={headerMetadata}
|
||||
value={header}
|
||||
testID={headerTestId}
|
||||
/>
|
||||
<TouchableWithFeedback
|
||||
type='opacity'
|
||||
activeOpacity={0.8}
|
||||
onLongPress={touchableHandleLongPress}
|
||||
>
|
||||
<Markdown
|
||||
channelId={channelId}
|
||||
baseTextStyle={styles.header}
|
||||
blockStyles={blockStyles}
|
||||
disableBlockQuote={true}
|
||||
disableCodeBlock={true}
|
||||
disableGallery={true}
|
||||
disableHeading={true}
|
||||
disableTables={true}
|
||||
location={Screens.CHANNEL_INFO}
|
||||
textStyles={textStyles}
|
||||
layoutHeight={48}
|
||||
layoutWidth={100}
|
||||
theme={theme}
|
||||
imagesMetadata={headerMetadata}
|
||||
value={header}
|
||||
onLinkLongPress={handleLongPress}
|
||||
/>
|
||||
</TouchableWithFeedback>
|
||||
</View>
|
||||
}
|
||||
{Boolean(createdAt && createdBy) &&
|
||||
|
|
|
|||
|
|
@ -613,6 +613,7 @@
|
|||
"mobile.managed.settings": "Go to settings",
|
||||
"mobile.markdown.code.copy_code": "Copy Code",
|
||||
"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_url": "Copy URL",
|
||||
"mobile.mention.copy_mention": "Copy Mention",
|
||||
|
|
|
|||
Loading…
Reference in a new issue