[IMPROVE] migrate all markdown container files

This commit is contained in:
AlexAlexandre 2021-07-21 12:15:13 -03:00
parent 1c7ae63ac1
commit a557d7f5d2
12 changed files with 147 additions and 179 deletions

View File

@ -1,5 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Text } from 'react-native';
import { themes } from '../../constants/colors';
@ -7,9 +6,19 @@ import { themes } from '../../constants/colors';
import styles from './styles';
import { logEvent, events } from '../../utils/log';
interface IAtMention {
mention: string;
username: string;
navToRoomInfo: Function;
style: any;
useRealName: boolean;
theme: string;
mentions: any;
}
const AtMention = React.memo(({
mention, mentions, username, navToRoomInfo, style = [], useRealName, theme
}) => {
}: IAtMention) => {
if (mention === 'all' || mention === 'here') {
return (
<Text
@ -36,7 +45,7 @@ const AtMention = React.memo(({
};
}
const user = mentions?.find?.(m => m && m.username === mention);
const user = mentions?.find?.((m: any) => m && m.username === mention);
const handlePress = () => {
logEvent(events.ROOM_MENTION_GO_USER_INFO);
@ -65,14 +74,4 @@ const AtMention = React.memo(({
);
});
AtMention.propTypes = {
mention: PropTypes.string,
username: PropTypes.string,
navToRoomInfo: PropTypes.func,
style: PropTypes.array,
useRealName: PropTypes.bool,
theme: PropTypes.string,
mentions: PropTypes.oneOfType([PropTypes.array, PropTypes.object])
};
export default AtMention;

View File

@ -1,12 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';
import { themes } from '../../constants/colors';
import styles from './styles';
const BlockQuote = React.memo(({ children, theme }) => (
interface IBlockQuote {
children: JSX.Element;
theme: string;
}
const BlockQuote = React.memo(({ children, theme }: IBlockQuote) => (
<View style={styles.container}>
<View style={[styles.quote, { backgroundColor: themes[theme].borderColor }]} />
<View style={styles.childContainer}>
@ -15,9 +19,4 @@ const BlockQuote = React.memo(({ children, theme }) => (
</View>
));
BlockQuote.propTypes = {
children: PropTypes.node.isRequired,
theme: PropTypes.string
};
export default BlockQuote;

View File

@ -1,4 +1,3 @@
import PropTypes from 'prop-types';
import React from 'react';
import { Text } from 'react-native';
@ -6,9 +5,20 @@ import { themes } from '../../constants/colors';
import styles from './styles';
const Hashtag = React.memo(({
hashtag, channels, navToRoomInfo, style = [], theme
}) => {
export type TChannel = {
name: string;
_id: number;
}
interface IHashtag {
hashtag: string;
navToRoomInfo: Function;
style: [];
theme: string;
channels: TChannel[];
}
const Hashtag = React.memo(({ hashtag, channels, navToRoomInfo, style = [], theme }: IHashtag) => {
const handlePress = () => {
const index = channels.findIndex(channel => channel.name === hashtag);
const navParam = {
@ -40,12 +50,4 @@ const Hashtag = React.memo(({
);
});
Hashtag.propTypes = {
hashtag: PropTypes.string,
navToRoomInfo: PropTypes.func,
style: PropTypes.array,
theme: PropTypes.string,
channels: PropTypes.oneOfType([PropTypes.array, PropTypes.object])
};
export default Hashtag;

View File

@ -1,5 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Text, Clipboard } from 'react-native';
import styles from './styles';
@ -9,9 +8,14 @@ import EventEmitter from '../../utils/events';
import I18n from '../../i18n';
import openLink from '../../utils/openLink';
const Link = React.memo(({
children, link, theme, onLinkPress
}) => {
interface ILink {
children: JSX.Element;
link: string;
theme: string;
onLinkPress: Function;
}
const Link = React.memo(({ children, link, theme, onLinkPress }: ILink) => {
const handlePress = () => {
if (!link) {
return;
@ -40,11 +44,4 @@ const Link = React.memo(({
);
});
Link.propTypes = {
children: PropTypes.node,
link: PropTypes.string,
theme: PropTypes.string,
onLinkPress: PropTypes.func
};
export default Link;

View File

@ -1,12 +1,18 @@
import PropTypes from 'prop-types';
import React from 'react';
const List = React.memo(({
children, ordered, start, tight, numberOfLines = 0
}) => {
interface IList {
children: JSX.Element;
ordered: boolean;
start: number;
tight: boolean;
numberOfLines: number;
}
const List = React.memo(({ children, ordered, start = 1, tight, numberOfLines = 0 }: IList) => {
let bulletWidth = 15;
if (ordered) {
// @ts-ignore
const lastNumber = (start + children.length) - 1;
bulletWidth = (9 * lastNumber.toString().length) + 7;
}
@ -17,7 +23,7 @@ const List = React.memo(({
items = items.slice(0, numberOfLines);
}
const _children = items.map((child, index) => React.cloneElement(child, {
const _children = items.map((child: any, index: number) => React.cloneElement(child, {
bulletWidth,
ordered,
tight,
@ -31,16 +37,4 @@ const List = React.memo(({
);
});
List.propTypes = {
children: PropTypes.node,
ordered: PropTypes.bool,
start: PropTypes.number,
tight: PropTypes.bool,
numberOfLines: PropTypes.number
};
List.defaultProps = {
start: 1
};
export default List;

View File

@ -1,10 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
StyleSheet,
Text,
View
} from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import { themes } from '../../constants/colors';
@ -22,9 +17,19 @@ const style = StyleSheet.create({
}
});
interface IListItem {
children: JSX.Element;
bulletWidth: number;
level: number;
ordered: boolean;
continue: boolean;
theme: string;
index: number;
}
const ListItem = React.memo(({
children, level, bulletWidth, continue: _continue, ordered, index, theme
}) => {
}: IListItem) => {
let bullet;
if (_continue) {
bullet = '';
@ -50,14 +55,4 @@ const ListItem = React.memo(({
);
});
ListItem.propTypes = {
children: PropTypes.node,
bulletWidth: PropTypes.number,
level: PropTypes.number,
ordered: PropTypes.bool,
continue: PropTypes.bool,
theme: PropTypes.string,
index: PropTypes.number
};
export default ListItem;

View File

@ -1,11 +1,5 @@
import { PropTypes } from 'prop-types';
import React from 'react';
import {
ScrollView,
TouchableOpacity,
View,
Text
} from 'react-native';
import { ScrollView, TouchableOpacity, View, Text } from 'react-native';
import { CELL_WIDTH } from './TableCell';
import styles from './styles';
@ -13,20 +7,24 @@ import Navigation from '../../lib/Navigation';
import I18n from '../../i18n';
import { themes } from '../../constants/colors';
interface ITable {
children: JSX.Element;
numColumns: number;
theme: string;
}
const MAX_HEIGHT = 300;
const Table = React.memo(({
children, numColumns, theme
}) => {
const Table = React.memo(({ children, numColumns, theme }: ITable) => {
const getTableWidth = () => numColumns * CELL_WIDTH;
const renderRows = (drawExtraBorders = true) => {
const renderRows = (drawExtraBorders: boolean = true) => {
const tableStyle = [styles.table, { borderColor: themes[theme].borderColor }];
if (drawExtraBorders) {
tableStyle.push(styles.tableExtraBorders);
}
const rows = React.Children.toArray(children);
const rows: any = React.Children.toArray(children);
rows[rows.length - 1] = React.cloneElement(rows[rows.length - 1], {
isLastRow: true
});
@ -55,10 +53,4 @@ const Table = React.memo(({
);
});
Table.propTypes = {
children: PropTypes.node.isRequired,
numColumns: PropTypes.number.isRequired,
theme: PropTypes.string
};
export default Table;

View File

@ -1,4 +1,3 @@
import PropTypes from 'prop-types';
import React from 'react';
import { Text, View } from 'react-native';
@ -6,11 +5,16 @@ import { themes } from '../../constants/colors';
import styles from './styles';
interface ITableCell {
align: '' | 'left' | 'center' | 'right';
children: JSX.Element;
isLastCell: boolean;
theme: string;
}
export const CELL_WIDTH = 100;
const TableCell = React.memo(({
isLastCell, align, children, theme
}) => {
const TableCell = React.memo(({ isLastCell, align, children, theme }: ITableCell) => {
const cellStyle = [styles.cell, { borderColor: themes[theme].borderColor }];
if (!isLastCell) {
cellStyle.push(styles.cellRightBorder);
@ -32,11 +36,4 @@ const TableCell = React.memo(({
);
});
TableCell.propTypes = {
align: PropTypes.oneOf(['', 'left', 'center', 'right']),
children: PropTypes.node,
isLastCell: PropTypes.bool,
theme: PropTypes.string
};
export default TableCell;

View File

@ -1,4 +1,3 @@
import PropTypes from 'prop-types';
import React from 'react';
import { View } from 'react-native';
@ -6,15 +5,19 @@ import { themes } from '../../constants/colors';
import styles from './styles';
const TableRow = React.memo(({
isLastRow, children: _children, theme
}) => {
interface ITableRow {
children: JSX.Element;
isLastRow: boolean;
theme: string;
}
const TableRow = React.memo(({ isLastRow, children: _children, theme }: ITableRow) => {
const rowStyle = [styles.row, { borderColor: themes[theme].borderColor }];
if (!isLastRow) {
rowStyle.push(styles.rowBottomBorder);
}
const children = React.Children.toArray(_children);
const children: any = React.Children.toArray(_children);
children[children.length - 1] = React.cloneElement(children[children.length - 1], {
isLastCell: true
});
@ -22,10 +25,4 @@ const TableRow = React.memo(({
return <View style={rowStyle}>{children}</View>;
});
TableRow.propTypes = {
children: PropTypes.node,
isLastRow: PropTypes.bool,
theme: PropTypes.string
};
export default TableRow;

View File

@ -2,7 +2,6 @@ import React, { PureComponent } from 'react';
import { Text, Image } from 'react-native';
import { Parser, Node } from 'commonmark';
import Renderer from 'commonmark-react-renderer';
import PropTypes from 'prop-types';
import removeMarkdown from 'remove-markdown';
import shortnameToUnicode from '../../utils/shortnameToUnicode';
@ -13,7 +12,7 @@ import MarkdownLink from './Link';
import MarkdownList from './List';
import MarkdownListItem from './ListItem';
import MarkdownAtMention from './AtMention';
import MarkdownHashtag from './Hashtag';
import MarkdownHashtag, {TChannel} from './Hashtag';
import MarkdownBlockQuote from './BlockQuote';
import MarkdownEmoji from './Emoji';
import MarkdownTable from './Table';
@ -24,8 +23,32 @@ import mergeTextNodes from './mergeTextNodes';
import styles from './styles';
import { isValidURL } from '../../utils/url';
interface IMarkdownProps {
msg: string;
getCustomEmoji: Function;
baseUrl: string;
username: string;
tmid: string;
isEdited: boolean;
numberOfLines: number;
customEmojis: boolean;
useRealName: boolean;
channels: TChannel[];
mentions: object[];
navToRoomInfo: Function;
preview: boolean;
theme: string;
testID: string;
style: any;
onLinkPress: Function;
}
type TLiteral = {
literal: string;
}
// Support <http://link|Text>
const formatText = text => text.replace(
const formatText = (text: string) => text.replace(
new RegExp('(?:<|<)((?:https|http):\\/\\/[^\\|]+)\\|(.+?)(?=>|>)(?:>|>)', 'gm'),
(match, url, title) => `[${ title }](${ url })`
);
@ -36,18 +59,18 @@ const emojiRanges = [
' |\n' // allow spaces and line breaks
].join('|');
const removeSpaces = str => str && str.replace(/\s/g, '');
const removeSpaces = (str: string) => str && str.replace(/\s/g, '');
const removeAllEmoji = str => str.replace(new RegExp(emojiRanges, 'g'), '');
const removeAllEmoji = (str: string) => str.replace(new RegExp(emojiRanges, 'g'), '');
const isOnlyEmoji = (str) => {
const isOnlyEmoji = (str: string) => {
str = removeSpaces(str);
return !removeAllEmoji(str).length;
};
const removeOneEmoji = str => str.replace(new RegExp(emojiRanges), '');
const removeOneEmoji = (str: string) => str.replace(new RegExp(emojiRanges), '');
const emojiCount = (str) => {
const emojiCount = (str: string) => {
str = removeSpaces(str);
let oldLength = 0;
let counter = 0;
@ -65,28 +88,11 @@ const emojiCount = (str) => {
const parser = new Parser();
class Markdown extends PureComponent {
static propTypes = {
msg: PropTypes.string,
getCustomEmoji: PropTypes.func,
baseUrl: PropTypes.string,
username: PropTypes.string,
tmid: PropTypes.string,
isEdited: PropTypes.bool,
numberOfLines: PropTypes.number,
customEmojis: PropTypes.bool,
useRealName: PropTypes.bool,
channels: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
mentions: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
navToRoomInfo: PropTypes.func,
preview: PropTypes.bool,
theme: PropTypes.string,
testID: PropTypes.string,
style: PropTypes.array,
onLinkPress: PropTypes.func
};
class Markdown extends PureComponent<IMarkdownProps, any> {
private renderer: any;
private isMessageContainsOnlyEmoji!: boolean;
constructor(props) {
constructor(props: IMarkdownProps) {
super(props);
this.renderer = this.createRenderer();
}
@ -129,7 +135,7 @@ class Markdown extends PureComponent {
renderParagraphsInLists: true
});
editedMessage = (ast) => {
editedMessage = (ast: any) => {
const { isEdited } = this.props;
if (isEdited) {
const editIndicatorNode = new Node('edited_indicator');
@ -144,7 +150,7 @@ class Markdown extends PureComponent {
}
};
renderText = ({ context, literal }) => {
renderText = ({ context, literal }: {context: []; literal: string}) => {
const {
numberOfLines, style = []
} = this.props;
@ -163,7 +169,7 @@ class Markdown extends PureComponent {
);
}
renderCodeInline = ({ literal }) => {
renderCodeInline = ({ literal }: TLiteral) => {
const { theme, style = [] } = this.props;
return (
<Text
@ -182,7 +188,7 @@ class Markdown extends PureComponent {
);
};
renderCodeBlock = ({ literal }) => {
renderCodeBlock = ({ literal }: TLiteral) => {
const { theme, style = [] } = this.props;
return (
<Text
@ -206,7 +212,7 @@ class Markdown extends PureComponent {
return <Text>{tmid ? ' ' : '\n'}</Text>;
}
renderParagraph = ({ children }) => {
renderParagraph = ({ children }: any) => {
const { numberOfLines, style, theme } = this.props;
if (!children || children.length === 0) {
return null;
@ -218,7 +224,7 @@ class Markdown extends PureComponent {
);
};
renderLink = ({ children, href }) => {
renderLink = ({ children, href }: any) => {
const { theme, onLinkPress } = this.props;
return (
<MarkdownLink
@ -231,10 +237,8 @@ class Markdown extends PureComponent {
);
}
renderHashtag = ({ hashtag }) => {
const {
channels, navToRoomInfo, style, theme
} = this.props;
renderHashtag = ({ hashtag }: {hashtag: string}) => {
const { channels, navToRoomInfo, style, theme } = this.props;
return (
<MarkdownHashtag
hashtag={hashtag}
@ -246,10 +250,8 @@ class Markdown extends PureComponent {
);
}
renderAtMention = ({ mentionName }) => {
const {
username, mentions, navToRoomInfo, useRealName, style, theme
} = this.props;
renderAtMention = ({ mentionName }: { mentionName: string }) => {
const { username, mentions, navToRoomInfo, useRealName, style, theme } = this.props;
return (
<MarkdownAtMention
mentions={mentions}
@ -263,10 +265,8 @@ class Markdown extends PureComponent {
);
}
renderEmoji = ({ literal }) => {
const {
getCustomEmoji, baseUrl, customEmojis, style, theme
} = this.props;
renderEmoji = ({ literal }: TLiteral) => {
const { getCustomEmoji, baseUrl, customEmojis, style, theme } = this.props;
return (
<MarkdownEmoji
literal={literal}
@ -280,7 +280,7 @@ class Markdown extends PureComponent {
);
}
renderImage = ({ src }) => {
renderImage = ({ src }: {src: string}) => {
if (!isValidURL(src)) {
return null;
}
@ -298,7 +298,7 @@ class Markdown extends PureComponent {
return <Text style={[styles.edited, { color: themes[theme].auxiliaryText }]}> ({I18n.t('edited')})</Text>;
}
renderHeading = ({ children, level }) => {
renderHeading = ({ children, level }: any) => {
const { numberOfLines, theme } = this.props;
const textStyle = styles[`heading${ level }Text`];
return (
@ -308,9 +308,7 @@ class Markdown extends PureComponent {
);
};
renderList = ({
children, start, tight, type
}) => {
renderList = ({ children, start, tight, type }: any) => {
const { numberOfLines } = this.props;
return (
<MarkdownList
@ -324,11 +322,9 @@ class Markdown extends PureComponent {
);
};
renderListItem = ({
children, context, ...otherProps
}) => {
renderListItem = ({ children, context, ...otherProps }: any) => {
const { theme } = this.props;
const level = context.filter(type => type === 'list').length;
const level = context.filter((type: string) => type === 'list').length;
return (
<MarkdownListItem
@ -341,7 +337,7 @@ class Markdown extends PureComponent {
);
};
renderBlockQuote = ({ children }) => {
renderBlockQuote = ({ children }: {children: JSX.Element}) => {
const { theme } = this.props;
return (
<MarkdownBlockQuote theme={theme}>
@ -350,7 +346,7 @@ class Markdown extends PureComponent {
);
}
renderTable = ({ children, numColumns }) => {
renderTable = ({ children, numColumns }: { children: JSX.Element; numColumns: number }) => {
const { theme } = this.props;
return (
<MarkdownTable numColumns={numColumns} theme={theme}>
@ -359,12 +355,12 @@ class Markdown extends PureComponent {
);
}
renderTableRow = (args) => {
renderTableRow = (args: any) => {
const { theme } = this.props;
return <MarkdownTableRow {...args} theme={theme} />;
}
renderTableCell = (args) => {
renderTableCell = (args: any) => {
const { theme } = this.props;
return <MarkdownTableCell {...args} theme={theme} />;
}

View File

@ -1,6 +1,6 @@
// TODO: should we add this to our commonmark fork instead?
// we loop through nodes and try to merge all texts
export default function mergeTextNodes(ast) {
export default function mergeTextNodes(ast: any) {
// https://github.com/commonmark/commonmark.js/blob/master/lib/node.js#L268
const walker = ast.walker();
let event;

View File

@ -7,7 +7,7 @@ const codeFontFamily = Platform.select({
android: { fontFamily: 'monospace' }
});
export default StyleSheet.create({
export default StyleSheet.create<any>({
container: {
alignItems: 'flex-start',
flexDirection: 'row'