From a557d7f5d256c97cebd8d2329479016673b69e2d Mon Sep 17 00:00:00 2001 From: AlexAlexandre Date: Wed, 21 Jul 2021 12:15:13 -0300 Subject: [PATCH] [IMPROVE] migrate all markdown container files --- .../markdown/{AtMention.js => AtMention.tsx} | 25 ++-- .../{BlockQuote.js => BlockQuote.tsx} | 13 +- .../markdown/{Hashtag.js => Hashtag.tsx} | 26 ++-- app/containers/markdown/{Link.js => Link.tsx} | 19 ++- app/containers/markdown/{List.js => List.tsx} | 28 ++--- .../markdown/{ListItem.js => ListItem.tsx} | 29 ++--- .../markdown/{Table.js => Table.tsx} | 28 ++--- .../markdown/{TableCell.js => TableCell.tsx} | 19 ++- .../markdown/{TableRow.js => TableRow.tsx} | 19 ++- .../markdown/{index.js => index.tsx} | 116 +++++++++--------- .../{mergeTextNodes.js => mergeTextNodes.ts} | 2 +- .../markdown/{styles.js => styles.ts} | 2 +- 12 files changed, 147 insertions(+), 179 deletions(-) rename app/containers/markdown/{AtMention.js => AtMention.tsx} (76%) rename app/containers/markdown/{BlockQuote.js => BlockQuote.tsx} (66%) rename app/containers/markdown/{Hashtag.js => Hashtag.tsx} (70%) rename app/containers/markdown/{Link.js => Link.tsx} (80%) rename app/containers/markdown/{List.js => List.tsx} (52%) rename app/containers/markdown/{ListItem.js => ListItem.tsx} (72%) rename app/containers/markdown/{Table.js => Table.tsx} (75%) rename app/containers/markdown/{TableCell.js => TableCell.tsx} (71%) rename app/containers/markdown/{TableRow.js => TableRow.tsx} (63%) rename app/containers/markdown/{index.js => index.tsx} (77%) rename app/containers/markdown/{mergeTextNodes.js => mergeTextNodes.ts} (93%) rename app/containers/markdown/{styles.js => styles.ts} (98%) diff --git a/app/containers/markdown/AtMention.js b/app/containers/markdown/AtMention.tsx similarity index 76% rename from app/containers/markdown/AtMention.js rename to app/containers/markdown/AtMention.tsx index 06be56806..72aba8534 100644 --- a/app/containers/markdown/AtMention.js +++ b/app/containers/markdown/AtMention.tsx @@ -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 ( 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; diff --git a/app/containers/markdown/BlockQuote.js b/app/containers/markdown/BlockQuote.tsx similarity index 66% rename from app/containers/markdown/BlockQuote.js rename to app/containers/markdown/BlockQuote.tsx index 98c929144..3174ca4de 100644 --- a/app/containers/markdown/BlockQuote.js +++ b/app/containers/markdown/BlockQuote.tsx @@ -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) => ( @@ -15,9 +19,4 @@ const BlockQuote = React.memo(({ children, theme }) => ( )); -BlockQuote.propTypes = { - children: PropTypes.node.isRequired, - theme: PropTypes.string -}; - export default BlockQuote; diff --git a/app/containers/markdown/Hashtag.js b/app/containers/markdown/Hashtag.tsx similarity index 70% rename from app/containers/markdown/Hashtag.js rename to app/containers/markdown/Hashtag.tsx index 8d9672e40..5ca3e7f36 100644 --- a/app/containers/markdown/Hashtag.js +++ b/app/containers/markdown/Hashtag.tsx @@ -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; diff --git a/app/containers/markdown/Link.js b/app/containers/markdown/Link.tsx similarity index 80% rename from app/containers/markdown/Link.js rename to app/containers/markdown/Link.tsx index 615b66128..5c30baf05 100644 --- a/app/containers/markdown/Link.js +++ b/app/containers/markdown/Link.tsx @@ -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; diff --git a/app/containers/markdown/List.js b/app/containers/markdown/List.tsx similarity index 52% rename from app/containers/markdown/List.js rename to app/containers/markdown/List.tsx index f934a878e..fb741d5d4 100644 --- a/app/containers/markdown/List.js +++ b/app/containers/markdown/List.tsx @@ -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; diff --git a/app/containers/markdown/ListItem.js b/app/containers/markdown/ListItem.tsx similarity index 72% rename from app/containers/markdown/ListItem.js rename to app/containers/markdown/ListItem.tsx index 9b14569e0..140619e86 100644 --- a/app/containers/markdown/ListItem.js +++ b/app/containers/markdown/ListItem.tsx @@ -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; diff --git a/app/containers/markdown/Table.js b/app/containers/markdown/Table.tsx similarity index 75% rename from app/containers/markdown/Table.js rename to app/containers/markdown/Table.tsx index b1bb5a309..efa0fa9af 100644 --- a/app/containers/markdown/Table.js +++ b/app/containers/markdown/Table.tsx @@ -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; diff --git a/app/containers/markdown/TableCell.js b/app/containers/markdown/TableCell.tsx similarity index 71% rename from app/containers/markdown/TableCell.js rename to app/containers/markdown/TableCell.tsx index 68c1e2f56..03d3913c4 100644 --- a/app/containers/markdown/TableCell.js +++ b/app/containers/markdown/TableCell.tsx @@ -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; diff --git a/app/containers/markdown/TableRow.js b/app/containers/markdown/TableRow.tsx similarity index 63% rename from app/containers/markdown/TableRow.js rename to app/containers/markdown/TableRow.tsx index e1d0c54ee..75a5ab785 100644 --- a/app/containers/markdown/TableRow.js +++ b/app/containers/markdown/TableRow.tsx @@ -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 {children}; }); -TableRow.propTypes = { - children: PropTypes.node, - isLastRow: PropTypes.bool, - theme: PropTypes.string -}; - export default TableRow; diff --git a/app/containers/markdown/index.js b/app/containers/markdown/index.tsx similarity index 77% rename from app/containers/markdown/index.js rename to app/containers/markdown/index.tsx index bc2fdba73..cad569e7a 100644 --- a/app/containers/markdown/index.js +++ b/app/containers/markdown/index.tsx @@ -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 -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 { + 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 ( { + renderCodeBlock = ({ literal }: TLiteral) => { const { theme, style = [] } = this.props; return ( {tmid ? ' ' : '\n'}; } - 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 ( { - const { - channels, navToRoomInfo, style, theme - } = this.props; + renderHashtag = ({ hashtag }: {hashtag: string}) => { + const { channels, navToRoomInfo, style, theme } = this.props; return ( { - const { - username, mentions, navToRoomInfo, useRealName, style, theme - } = this.props; + renderAtMention = ({ mentionName }: { mentionName: string }) => { + const { username, mentions, navToRoomInfo, useRealName, style, theme } = this.props; return ( { - const { - getCustomEmoji, baseUrl, customEmojis, style, theme - } = this.props; + renderEmoji = ({ literal }: TLiteral) => { + const { getCustomEmoji, baseUrl, customEmojis, style, theme } = this.props; return ( { + renderImage = ({ src }: {src: string}) => { if (!isValidURL(src)) { return null; } @@ -298,7 +298,7 @@ class Markdown extends PureComponent { return ({I18n.t('edited')}); } - 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 ( { + 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 ( { + renderBlockQuote = ({ children }: {children: JSX.Element}) => { const { theme } = this.props; return ( @@ -350,7 +346,7 @@ class Markdown extends PureComponent { ); } - renderTable = ({ children, numColumns }) => { + renderTable = ({ children, numColumns }: { children: JSX.Element; numColumns: number }) => { const { theme } = this.props; return ( @@ -359,12 +355,12 @@ class Markdown extends PureComponent { ); } - renderTableRow = (args) => { + renderTableRow = (args: any) => { const { theme } = this.props; return ; } - renderTableCell = (args) => { + renderTableCell = (args: any) => { const { theme } = this.props; return ; } diff --git a/app/containers/markdown/mergeTextNodes.js b/app/containers/markdown/mergeTextNodes.ts similarity index 93% rename from app/containers/markdown/mergeTextNodes.js rename to app/containers/markdown/mergeTextNodes.ts index 768395236..d47bd8ade 100644 --- a/app/containers/markdown/mergeTextNodes.js +++ b/app/containers/markdown/mergeTextNodes.ts @@ -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; diff --git a/app/containers/markdown/styles.js b/app/containers/markdown/styles.ts similarity index 98% rename from app/containers/markdown/styles.js rename to app/containers/markdown/styles.ts index f78ad3c3a..f91d02458 100644 --- a/app/containers/markdown/styles.js +++ b/app/containers/markdown/styles.ts @@ -7,7 +7,7 @@ const codeFontFamily = Platform.select({ android: { fontFamily: 'monospace' } }); -export default StyleSheet.create({ +export default StyleSheet.create({ container: { alignItems: 'flex-start', flexDirection: 'row'