[Gekidou] Markdown and Touchables (#6047)

* Fix markdown formatting and touchable interaction

* open gallery as overlay instead of modal

* update snapshots

* Add missing dependencies to useMemo
This commit is contained in:
Elias Nahum
2022-03-14 16:32:06 -03:00
committed by GitHub
parent acf4cbde8d
commit a43dad53e1
48 changed files with 793 additions and 825 deletions

View File

@@ -2,30 +2,20 @@
// See LICENSE.txt for license information.
import {useManagedConfig} from '@mattermost/react-native-emm';
import {Database, Q} from '@nozbe/watermelondb';
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import {Database} from '@nozbe/watermelondb';
import Clipboard from '@react-native-community/clipboard';
import React, {useCallback, useMemo} from 'react';
import {useIntl} from 'react-intl';
import {GestureResponderEvent, StyleProp, StyleSheet, Text, TextStyle, View, ViewStyle} from 'react-native';
import {TouchableOpacity} from 'react-native-gesture-handler';
import {combineLatest, of as of$} from 'rxjs';
import {map, switchMap} from 'rxjs/operators';
import {GestureResponderEvent, StyleProp, StyleSheet, Text, TextStyle, View} from 'react-native';
import CompassIcon from '@components/compass_icon';
import SlideUpPanelItem, {ITEM_HEIGHT} from '@components/slide_up_panel_item';
import {Preferences} from '@constants';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import {MM_TABLES} from '@constants/database';
import {useTheme} from '@context/theme';
import UserModel from '@database/models/server/user';
import {getTeammateNameDisplaySetting} from '@helpers/api/preference';
import {bottomSheet, dismissBottomSheet, showModal} from '@screens/navigation';
import {displayUsername, getUsersByUsername} from '@utils/user';
import type {WithDatabaseArgs} from '@typings/database/database';
import type PreferenceModel from '@typings/database/models/servers/preference';
import type SystemModel from '@typings/database/models/servers/system';
import type UserModelType from '@typings/database/models/servers/user';
type AtMentionProps = {
@@ -39,16 +29,13 @@ type AtMentionProps = {
onPostPress?: (e: GestureResponderEvent) => void;
teammateNameDisplay: string;
textStyle?: StyleProp<TextStyle>;
touchableStyle?: StyleProp<ViewStyle>;
users: UserModelType[];
}
const {SERVER: {PREFERENCE, SYSTEM, USER}} = MM_TABLES;
const {SERVER: {USER}} = MM_TABLES;
const style = StyleSheet.create({
bottomSheet: {
flex: 1,
},
bottomSheet: {flex: 1},
});
const AtMention = ({
@@ -62,7 +49,6 @@ const AtMention = ({
onPostPress,
teammateNameDisplay,
textStyle,
touchableStyle,
users,
}: AtMentionProps) => {
const intl = useIntl();
@@ -228,48 +214,17 @@ const AtMention = ({
}
return (
<TouchableOpacity
<Text
onPress={onPress!}
onLongPress={onLongPress}
style={touchableStyle}
style={styleText}
>
<Text style={styleText}>
<Text style={mentionTextStyle}>
{'@' + mention}
</Text>
{suffixElement}
<Text style={mentionTextStyle}>
{'@' + mention}
</Text>
</TouchableOpacity>
{suffixElement}
</Text>
);
};
const withAtMention = withObservables(['mentionName'], ({database, mentionName}: {mentionName: string} & WithDatabaseArgs) => {
const config = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG);
const license = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE);
const preferences = database.get<PreferenceModel>(PREFERENCE).query(Q.where('category', Preferences.CATEGORY_DISPLAY_SETTINGS)).observe();
const currentUserId = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
switchMap(({value}) => of$(value)),
);
const teammateNameDisplay = combineLatest([config, license, preferences]).pipe(
map(
([{value: cfg}, {value: lcs}, prefs]) => getTeammateNameDisplaySetting(prefs, cfg, lcs),
),
);
let mn = mentionName.toLowerCase();
if ((/[._-]$/).test(mn)) {
mn = mn.substring(0, mn.length - 1);
}
return {
currentUserId,
teammateNameDisplay,
users: database.get(USER).query(
Q.where('username', Q.like(
`%${Q.sanitizeLikeString(mn)}%`,
)),
).observeWithColumns(['username']),
};
});
export default withDatabase(withAtMention(React.memo(AtMention)));
export default React.memo(AtMention);

View File

@@ -0,0 +1,52 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Q} from '@nozbe/watermelondb';
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import {combineLatest, of as of$} from 'rxjs';
import {map, switchMap} from 'rxjs/operators';
import {Preferences} from '@constants';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import {getTeammateNameDisplaySetting} from '@helpers/api/preference';
import AtMention from './at_mention';
import type {WithDatabaseArgs} from '@typings/database/database';
import type PreferenceModel from '@typings/database/models/servers/preference';
import type SystemModel from '@typings/database/models/servers/system';
const {SERVER: {PREFERENCE, SYSTEM, USER}} = MM_TABLES;
const {CONFIG, CURRENT_USER_ID, LICENSE} = SYSTEM_IDENTIFIERS;
const enhance = withObservables(['mentionName'], ({database, mentionName}: {mentionName: string} & WithDatabaseArgs) => {
const config = database.get<SystemModel>(SYSTEM).findAndObserve(CONFIG);
const license = database.get<SystemModel>(SYSTEM).findAndObserve(LICENSE);
const preferences = database.get<PreferenceModel>(PREFERENCE).query(Q.where('category', Preferences.CATEGORY_DISPLAY_SETTINGS)).observe();
const currentUserId = database.get<SystemModel>(SYSTEM).findAndObserve(CURRENT_USER_ID).pipe(
switchMap(({value}) => of$(value)),
);
const teammateNameDisplay = combineLatest([config, license, preferences]).pipe(
map(
([{value: cfg}, {value: lcs}, prefs]) => getTeammateNameDisplaySetting(prefs, cfg, lcs),
),
);
let mn = mentionName.toLowerCase();
if ((/[._-]$/).test(mn)) {
mn = mn.substring(0, mn.length - 1);
}
return {
currentUserId,
teammateNameDisplay,
users: database.get(USER).query(
Q.where('username', Q.like(
`%${Q.sanitizeLikeString(mn)}%`,
)),
).observeWithColumns(['username']),
};
});
export default withDatabase(enhance(AtMention));

View File

@@ -1,26 +1,18 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Q} from '@nozbe/watermelondb';
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import React, {useCallback} from 'react';
import {useIntl} from 'react-intl';
import {StyleProp, Text, TextStyle} from 'react-native';
import {TouchableOpacity} from 'react-native-gesture-handler';
import {map, switchMap} from 'rxjs/operators';
import {joinChannel, switchToChannelById} from '@actions/remote/channel';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import {useServerUrl} from '@context/server';
import {t} from '@i18n';
import {dismissAllModals, popToRoot} from '@screens/navigation';
import {alertErrorWithFallback} from '@utils/draft';
import {preventDoubleTap} from '@utils/tap';
import type {WithDatabaseArgs} from '@typings/database/database';
import type ChannelModel from '@typings/database/models/servers/channel';
import type SystemModel from '@typings/database/models/servers/system';
import type TeamModel from '@typings/database/models/servers/team';
export type ChannelMentions = Record<string, {id?: string; display_name: string; name?: string; team_name: string}>;
@@ -65,8 +57,6 @@ function getChannelFromChannelName(name: string, channels: ChannelModel[], chann
return null;
}
const {SERVER: {CHANNEL, SYSTEM, TEAM}} = MM_TABLES;
const ChannelMention = ({
channelMentions, channelName, channels, currentTeamId, currentUserId,
linkStyle, team, textStyle,
@@ -112,33 +102,16 @@ const ChannelMention = ({
}
return (
<TouchableOpacity onPress={handlePress}>
<Text style={textStyle}>
<Text style={linkStyle}>
{`~${channel.display_name}`}
</Text>
{suffix}
<Text style={textStyle}>
<Text
onPress={handlePress}
style={linkStyle}
>
{`~${channel.display_name}`}
</Text>
</TouchableOpacity>
{suffix}
</Text>
);
};
const withChannelsForTeam = withObservables([], ({database}: WithDatabaseArgs) => {
const currentTeamId = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID);
const currentUserId = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID);
const channels = currentTeamId.pipe(
switchMap(({value}) => database.get<ChannelModel>(CHANNEL).query(Q.where('team_id', value)).observeWithColumns(['display_name'])),
);
const team = currentTeamId.pipe(
switchMap(({value}) => database.get<TeamModel>(TEAM).findAndObserve(value)),
);
return {
channels,
currentTeamId: currentTeamId.pipe(map((ct) => ct.value)),
currentUserId: currentUserId.pipe(map((cu) => cu.value)),
team,
};
});
export default withDatabase(withChannelsForTeam(ChannelMention));
export default ChannelMention;

View File

@@ -0,0 +1,40 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Q} from '@nozbe/watermelondb';
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import {map, switchMap} from 'rxjs/operators';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import ChannelMention from './channel_mention';
import type {WithDatabaseArgs} from '@typings/database/database';
import type ChannelModel from '@typings/database/models/servers/channel';
import type SystemModel from '@typings/database/models/servers/system';
import type TeamModel from '@typings/database/models/servers/team';
export type ChannelMentions = Record<string, {id?: string; display_name: string; name?: string; team_name: string}>;
const {SERVER: {CHANNEL, SYSTEM, TEAM}} = MM_TABLES;
const enhance = withObservables([], ({database}: WithDatabaseArgs) => {
const currentTeamId = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID);
const currentUserId = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID);
const channels = currentTeamId.pipe(
switchMap(({value}) => database.get<ChannelModel>(CHANNEL).query(Q.where('team_id', value)).observeWithColumns(['display_name'])),
);
const team = currentTeamId.pipe(
switchMap(({value}) => database.get<TeamModel>(TEAM).findAndObserve(value)),
);
return {
channels,
currentTeamId: currentTeamId.pipe(map((ct) => ct.value)),
currentUserId: currentUserId.pipe(map((cu) => cu.value)),
team,
};
});
export default withDatabase(enhance(ChannelMention));

View File

@@ -3,7 +3,6 @@
import React from 'react';
import {Text, TextStyle} from 'react-native';
import {TouchableOpacity} from 'react-native-gesture-handler';
import {popToRoot, showSearchModal, dismissAllModals} from '@screens/navigation';
@@ -22,11 +21,12 @@ const Hashtag = ({hashtag, linkStyle}: HashtagProps) => {
};
return (
<TouchableOpacity onPress={handlePress}>
<Text style={linkStyle}>
{`#${hashtag}`}
</Text>
</TouchableOpacity>
<Text
onPress={handlePress}
style={linkStyle}
>
{`#${hashtag}`}
</Text>
);
};

View File

@@ -56,6 +56,34 @@ type MarkdownProps = {
value: string | number;
}
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
// Android has trouble giving text transparency depending on how it's nested,
// so we calculate the resulting colour manually
const editedOpacity = Platform.select({
ios: 0.3,
android: 1.0,
});
const editedColor = Platform.select({
ios: theme.centerChannelColor,
android: blendColors(theme.centerChannelBg, theme.centerChannelColor, 0.3),
});
return {
block: {
alignItems: 'flex-start',
flexDirection: 'row',
flexWrap: 'wrap',
},
editedIndicatorText: {
color: editedColor,
opacity: editedOpacity,
},
atMentionOpacity: {
opacity: 1,
},
};
});
class Markdown extends PureComponent<MarkdownProps> {
static defaultProps = {
textStyles: {},
@@ -294,7 +322,9 @@ class Markdown extends PureComponent<MarkdownProps> {
return (
<View style={blockStyle}>
{children}
<Text>
{children}
</Text>
</View>
);
};
@@ -476,32 +506,4 @@ class Markdown extends PureComponent<MarkdownProps> {
}
}
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
// Android has trouble giving text transparency depending on how it's nested,
// so we calculate the resulting colour manually
const editedOpacity = Platform.select({
ios: 0.3,
android: 1.0,
});
const editedColor = Platform.select({
ios: theme.centerChannelColor,
android: blendColors(theme.centerChannelBg, theme.centerChannelColor, 0.3),
});
return {
block: {
alignItems: 'flex-start',
flexDirection: 'row',
flexWrap: 'wrap',
},
editedIndicatorText: {
color: editedColor,
opacity: editedOpacity,
},
atMentionOpacity: {
opacity: 1,
},
};
});
export default Markdown;

View File

@@ -5,8 +5,7 @@ import {useManagedConfig} from '@mattermost/react-native-emm';
import Clipboard from '@react-native-community/clipboard';
import React, {useCallback} from 'react';
import {useIntl} from 'react-intl';
import {Keyboard, StyleSheet, Text, TextStyle, View} from 'react-native';
import {TouchableOpacity} from 'react-native-gesture-handler';
import {Keyboard, StyleSheet, Text, TextStyle, TouchableOpacity, View} from 'react-native';
import FormattedText from '@components/formatted_text';
import SlideUpPanelItem, {ITEM_HEIGHT} from '@components/slide_up_panel_item';

View File

@@ -5,8 +5,7 @@ import {useManagedConfig} from '@mattermost/react-native-emm';
import Clipboard from '@react-native-community/clipboard';
import React, {useCallback, useMemo, useRef, useState} from 'react';
import {useIntl} from 'react-intl';
import {Alert, Platform, StyleProp, Text, TextStyle, View} from 'react-native';
import {LongPressGestureHandler, TapGestureHandler} from 'react-native-gesture-handler';
import {Alert, Platform, StyleProp, Text, TextStyle, TouchableWithoutFeedback, View} from 'react-native';
import Animated from 'react-native-reanimated';
import {SvgUri} from 'react-native-svg';
import parseUrl from 'url-parse';
@@ -74,8 +73,7 @@ const MarkdownImage = ({
const style = getStyleSheet(theme);
const managedConfig = useManagedConfig();
const genericFileId = useRef(generateId('uid')).current;
const tapRef = useRef<TapGestureHandler>();
const metadata = imagesMetadata?.[source] || Object.values(imagesMetadata || {})?.[0];
const metadata = imagesMetadata?.[source] || Object.values(imagesMetadata || {})[0];
const [failed, setFailed] = useState(isGifTooLarge(metadata));
const originalSize = getMarkdownImageSize(isReplyPost, isTablet, sourceSize, metadata, layoutWidth);
const serverUrl = useServerUrl();
@@ -109,11 +107,12 @@ const MarkdownImage = ({
width: originalSize.width,
height: originalSize.height,
} as FileInfo;
}, [uri, originalSize, metadata, isReplyPost, isTablet]);
}, [originalSize, metadata]);
const handlePreviewImage = useCallback(() => {
const item: GalleryItemType = {
...fileToGalleryItem(fileInfo),
mime_type: lookupMimeType(fileInfo.name),
type: 'image',
};
openGalleryAtIndex(galleryIdentifier, 0, [item]);
@@ -233,28 +232,43 @@ const MarkdownImage = ({
);
} else {
image = (
<TouchableWithoutFeedback
disabled={disabled}
onLongPress={handleLinkLongPress}
onPress={onGestureEvent}
>
<Animated.View
style={[styles, {width, height}, style.container]}
testID='markdown_image'
>
<ProgressiveImage
forwardRef={ref}
id={fileInfo.id!}
defaultSource={{uri: fileInfo.uri!}}
onError={handleOnError}
resizeMode='contain'
style={{width, height}}
/>
</Animated.View>
</TouchableWithoutFeedback>
);
}
}
if (image && linkDestination && !disabled) {
image = (
<TouchableWithFeedback
onPress={handleLinkPress}
onLongPress={handleLinkLongPress}
style={[{width, height}, style.container]}
>
<ProgressiveImage
forwardRef={ref}
id={fileInfo.id!}
defaultSource={{uri: fileInfo.uri!}}
onError={handleOnError}
resizeMode='contain'
style={{width, height}}
/>
);
}
}
if (image && linkDestination && !disabled) {
return (
<TouchableWithFeedback
onPress={handleLinkPress}
onLongPress={handleLinkLongPress}
style={[{width, height}, style.container]}
testID='markdown_image_link'
>
{image}
</TouchableWithFeedback>
);
}
@@ -262,23 +276,7 @@ const MarkdownImage = ({
return (
<GalleryInit galleryIdentifier={galleryIdentifier}>
<Animated.View testID='markdown_image'>
<LongPressGestureHandler
enabled={!disabled}
onGestureEvent={handleLinkLongPress}
waitFor={tapRef}
>
<Animated.View style={[styles, {width, height}, style.container]}>
<TapGestureHandler
enabled={!disabled}
onGestureEvent={onGestureEvent}
ref={tapRef}
>
<Animated.View>
{image}
</Animated.View>
</TapGestureHandler>
</Animated.View>
</LongPressGestureHandler>
{image}
</Animated.View>
</GalleryInit>
);

View File

@@ -0,0 +1,35 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import {of as of$} from 'rxjs';
import {switchMap} from 'rxjs/operators';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import MarkdownLink from './markdown_link';
import type {WithDatabaseArgs} from '@typings/database/database';
import type SystemModel from '@typings/database/models/servers/system';
type ConfigValue = {
value: ClientConfig;
}
const enhance = withObservables([], ({database}: WithDatabaseArgs) => {
const config = database.get<SystemModel>(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG);
const experimentalNormalizeMarkdownLinks = config.pipe(
switchMap(({value}: ConfigValue) => of$(value.ExperimentalNormalizeMarkdownLinks)),
);
const siteURL = config.pipe(
switchMap(({value}: ConfigValue) => of$(value.SiteURL)),
);
return {
experimentalNormalizeMarkdownLinks,
siteURL,
};
});
export default withDatabase(enhance(MarkdownLink));

View File

@@ -2,21 +2,15 @@
// See LICENSE.txt for license information.
import {useManagedConfig} from '@mattermost/react-native-emm';
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import Clipboard from '@react-native-community/clipboard';
import React, {Children, ReactElement, useCallback} from 'react';
import {useIntl} from 'react-intl';
import {Alert, StyleSheet, Text, View} from 'react-native';
import {TouchableOpacity} from 'react-native-gesture-handler';
import {of as of$} from 'rxjs';
import {switchMap} from 'rxjs/operators';
import urlParse from 'url-parse';
import {showPermalink} from '@actions/local/permalink';
import {switchToChannelByName} from '@actions/remote/channel';
import SlideUpPanelItem, {ITEM_HEIGHT} from '@components/slide_up_panel_item';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import DeepLinkTypes from '@constants/deep_linking';
import {useServerUrl} from '@context/server';
import {useTheme} from '@context/theme';
@@ -25,8 +19,6 @@ import {errorBadChannel} from '@utils/draft';
import {preventDoubleTap} from '@utils/tap';
import {matchDeepLink, normalizeProtocol, tryOpenURL} from '@utils/url';
import type {WithDatabaseArgs} from '@typings/database/database';
import type SystemModel from '@typings/database/models/servers/system';
import type {DeepLinkChannel, DeepLinkPermalink, DeepLinkWithData} from '@typings/launch';
type MarkdownLinkProps = {
@@ -165,34 +157,13 @@ const MarkdownLink = ({children, experimentalNormalizeMarkdownLinks, href, siteU
const renderChildren = experimentalNormalizeMarkdownLinks ? parseChildren() : children;
return (
<TouchableOpacity
<Text
onPress={handlePress}
onLongPress={handleLongPress}
>
<Text>
{renderChildren}
</Text>
</TouchableOpacity>
{renderChildren}
</Text>
);
};
type ConfigValue = {
value: ClientConfig;
}
const withConfigValues = withObservables([], ({database}: WithDatabaseArgs) => {
const config = database.get<SystemModel>(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG);
const experimentalNormalizeMarkdownLinks = config.pipe(
switchMap(({value}: ConfigValue) => of$(value.ExperimentalNormalizeMarkdownLinks)),
);
const siteURL = config.pipe(
switchMap(({value}: ConfigValue) => of$(value.SiteURL)),
);
return {
experimentalNormalizeMarkdownLinks,
siteURL,
};
});
export default withDatabase(withConfigValues(MarkdownLink));
export default MarkdownLink;

View File

@@ -3,8 +3,7 @@
import React, {PureComponent, ReactNode} from 'react';
import {injectIntl, IntlShape} from 'react-intl';
import {Dimensions, EventSubscription, LayoutChangeEvent, Platform, ScaledSize, ScrollView, View} from 'react-native';
import {TouchableOpacity} from 'react-native-gesture-handler';
import {Dimensions, EventSubscription, LayoutChangeEvent, Platform, ScaledSize, ScrollView, TouchableOpacity, View} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import CompassIcon from '@components/compass_icon';
@@ -34,6 +33,80 @@ type MarkdownTableProps = MarkdownTableInputProps & {
theme: Theme;
}
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
container: {
maxHeight: MAX_HEIGHT,
},
expandButton: {
height: 34,
width: 34,
},
iconContainer: {
maxWidth: '100%',
alignItems: 'flex-end',
paddingTop: 8,
paddingBottom: 4,
...Platform.select({
ios: {
paddingRight: 14,
},
}),
},
iconButton: {
backgroundColor: theme.centerChannelBg,
marginTop: -32,
marginRight: -6,
borderWidth: 1,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 50,
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
width: 34,
height: 34,
},
icon: {
fontSize: 14,
color: theme.linkColor,
...Platform.select({
ios: {
fontSize: 13,
},
}),
},
displayFlex: {
flex: 1,
},
table: {
width: '100%',
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
borderWidth: 1,
},
tablePadding: {
paddingRight: 10,
},
moreBelow: {
bottom: Platform.select({
ios: 34,
android: 33.75,
}),
height: 20,
position: 'absolute',
left: 0,
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
},
moreRight: {
maxHeight: MAX_HEIGHT,
position: 'absolute',
top: 0,
width: 20,
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
borderRightWidth: 1,
},
};
});
class MarkdownTable extends PureComponent<MarkdownTableProps, MarkdownTableState> {
private rowsSliced: boolean | undefined;
private colsSliced: boolean | undefined;
@@ -284,78 +357,4 @@ class MarkdownTable extends PureComponent<MarkdownTableProps, MarkdownTableState
}
}
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
container: {
maxHeight: MAX_HEIGHT,
},
expandButton: {
height: 34,
width: 34,
},
iconContainer: {
maxWidth: '100%',
alignItems: 'flex-end',
paddingTop: 8,
paddingBottom: 4,
...Platform.select({
ios: {
paddingRight: 14,
},
}),
},
iconButton: {
backgroundColor: theme.centerChannelBg,
marginTop: -32,
marginRight: -6,
borderWidth: 1,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 50,
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
width: 34,
height: 34,
},
icon: {
fontSize: 14,
color: theme.linkColor,
...Platform.select({
ios: {
fontSize: 13,
},
}),
},
displayFlex: {
flex: 1,
},
table: {
width: '100%',
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
borderWidth: 1,
},
tablePadding: {
paddingRight: 10,
},
moreBelow: {
bottom: Platform.select({
ios: 34,
android: 33.75,
}),
height: 20,
position: 'absolute',
left: 0,
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
},
moreRight: {
maxHeight: MAX_HEIGHT,
position: 'absolute',
top: 0,
width: 20,
borderColor: changeOpacity(theme.centerChannelColor, 0.2),
borderRightWidth: 1,
},
};
});
export default injectIntl(MarkdownTable);

View File

@@ -2,8 +2,7 @@
// See LICENSE.txt for license information.
import React, {memo, useCallback, useRef, useState} from 'react';
import {StyleSheet, View} from 'react-native';
import {TapGestureHandler} from 'react-native-gesture-handler';
import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native';
import Animated from 'react-native-reanimated';
import parseUrl from 'url-parse';
@@ -110,9 +109,9 @@ const MarkTableImage = ({disabled, imagesMetadata, location, postId, serverURL,
} else {
const {height, width} = calculateDimensions(metadata.height, metadata.width, 100, 100);
image = (
<TapGestureHandler
enabled={!disabled}
onGestureEvent={onGestureEvent}
<TouchableWithoutFeedback
disabled={disabled}
onPress={onGestureEvent}
>
<Animated.View
style={[styles, {width, height}]}
@@ -127,7 +126,7 @@ const MarkTableImage = ({disabled, imagesMetadata, location, postId, serverURL,
style={{width, height}}
/>
</Animated.View>
</TapGestureHandler>
</TouchableWithoutFeedback>
);
}