From b82c991610fffa76dc1f02442d18bcc70a887787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Mon, 17 Feb 2025 09:38:33 +0000 Subject: [PATCH 1/2] Use simple styles for code blocks in Native platforms --- src/components/InlineCodeBlock/index.native.tsx | 6 ++++-- src/styles/index.ts | 3 ++- src/styles/utils/codeStyles/index.android.ts | 10 +++++----- src/styles/utils/codeStyles/index.ios.ts | 12 ++++++------ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/components/InlineCodeBlock/index.native.tsx b/src/components/InlineCodeBlock/index.native.tsx index 048bcfc960bd..8c6da229ff38 100644 --- a/src/components/InlineCodeBlock/index.native.tsx +++ b/src/components/InlineCodeBlock/index.native.tsx @@ -1,5 +1,6 @@ import React from 'react'; import type {TDefaultRendererProps} from 'react-native-render-html'; +import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; import type InlineCodeBlockProps from './types'; import type {TTextOrTPhrasing} from './types'; @@ -29,12 +30,13 @@ function InlineCodeBlock({TDefaultRenderer, // eslint-disable-next-line react/jsx-props-no-spreading {...defaultRendererProps} > - {data} + {/* {data} - + */} ); } diff --git a/src/styles/index.ts b/src/styles/index.ts index 1b0ed63e0a2f..f90d4ee48ecd 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -130,6 +130,7 @@ const baseCodeTagStyles = (theme: ThemeColors) => borderRadius: 5, borderColor: theme.border, backgroundColor: theme.textBackground, + // backgroundColor: theme.activeComponentBG, // If we want it more highlighted } satisfies ViewStyle & MixedStyleDeclaration); const headlineFont = { @@ -205,11 +206,11 @@ const webViewStyles = (theme: ThemeColors) => code: { ...baseCodeTagStyles(theme), - ...(codeStyles.codeTextStyle as MixedStyleDeclaration), paddingLeft: 5, paddingRight: 5, fontFamily: FontUtils.fontFamily.platform.MONOSPACE.fontFamily, // Font size is determined by getCodeFontSize function in `StyleUtils.js` + ...(codeStyles.codeTextStyle as MixedStyleDeclaration), }, img: { diff --git a/src/styles/utils/codeStyles/index.android.ts b/src/styles/utils/codeStyles/index.android.ts index 0ac77729c83c..790c5ce457a3 100644 --- a/src/styles/utils/codeStyles/index.android.ts +++ b/src/styles/utils/codeStyles/index.android.ts @@ -1,20 +1,20 @@ import type {CodeTextStyles, CodeWordStyles, CodeWordWrapperStyles} from './types'; const codeWordWrapper: CodeWordWrapperStyles = { - height: 20, + // height: 20, }; const codeWordStyle: CodeWordStyles = { - height: 18, - top: 4, + // height: 18, + // top: 4, }; const codeTextStyle: CodeTextStyles = { - lineHeight: 15, + // lineHeight: 15, }; const codePlainTextStyle: CodeTextStyles = { - lineHeight: 14.5, + // lineHeight: 14.5, }; export default {codeWordWrapper, codeWordStyle, codeTextStyle, codePlainTextStyle}; diff --git a/src/styles/utils/codeStyles/index.ios.ts b/src/styles/utils/codeStyles/index.ios.ts index 05e2b55ec205..eca32f18231e 100644 --- a/src/styles/utils/codeStyles/index.ios.ts +++ b/src/styles/utils/codeStyles/index.ios.ts @@ -1,21 +1,21 @@ import type {CodeTextStyles, CodeWordStyles, CodeWordWrapperStyles} from './types'; const codeWordWrapper: CodeWordWrapperStyles = { - height: 22, - justifyContent: 'center', + // height: 22, + // justifyContent: 'center', }; const codeWordStyle: CodeWordStyles = { - height: 18, - top: 4, + // height: 18, + // top: 4, }; const codeTextStyle: CodeTextStyles = { - lineHeight: 18, + // lineHeight: 18, }; const codePlainTextStyle: CodeTextStyles = { - lineHeight: 15, + // lineHeight: 15, }; export default {codeWordWrapper, codeWordStyle, codeTextStyle, codePlainTextStyle}; From da6c3802f03461e661f5d743371856105248aebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Tue, 18 Feb 2025 19:14:57 +0000 Subject: [PATCH 2/2] Cleanup --- .../InlineCodeBlock/WrappedText.tsx | 137 ------------------ .../InlineCodeBlock/index.native.tsx | 9 -- src/styles/index.ts | 12 -- src/styles/utils/codeStyles/index.android.ts | 20 --- src/styles/utils/codeStyles/index.ios.ts | 21 --- src/styles/utils/codeStyles/index.ts | 8 - src/styles/utils/codeStyles/types.ts | 7 - tests/unit/splitLongWordTest.ts | 47 ------ 8 files changed, 261 deletions(-) delete mode 100644 src/components/InlineCodeBlock/WrappedText.tsx delete mode 100644 src/styles/utils/codeStyles/index.android.ts delete mode 100644 src/styles/utils/codeStyles/index.ios.ts delete mode 100644 src/styles/utils/codeStyles/index.ts delete mode 100644 src/styles/utils/codeStyles/types.ts delete mode 100644 tests/unit/splitLongWordTest.ts diff --git a/src/components/InlineCodeBlock/WrappedText.tsx b/src/components/InlineCodeBlock/WrappedText.tsx deleted file mode 100644 index 237530223246..000000000000 --- a/src/components/InlineCodeBlock/WrappedText.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import React, {Fragment, useMemo} from 'react'; -import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; -import {View} from 'react-native'; -import Text from '@components/Text'; -import useThemeStyles from '@hooks/useThemeStyles'; -import useWindowDimensions from '@hooks/useWindowDimensions'; -import {containsOnlyEmojis} from '@libs/EmojiUtils'; -import variables from '@styles/variables'; -import CONST from '@src/CONST'; -import type ChildrenProps from '@src/types/utils/ChildrenProps'; - -type WrappedTextProps = ChildrenProps & { - /** Style to be applied to Text */ - textStyles?: StyleProp; - - /** - * Style for each individual word (token) in the text. Note that a token can also include whitespace characters between words. - */ - wordStyles?: StyleProp; -}; - -/** - * Breaks the text into matrix - * - * @example - * const text = "My Name is Rajat"; - * const resultMatrix = getTextMatrix(text); - * console.log(resultMatrix); - * // Output: - * // [ - * // ['My', ' ', 'Name', ' ', 'is', ' ', 'Rajat'], - * // ] - */ -function getTextMatrix(text: string): string[][] { - return text.split('\n').map((row) => row.split(CONST.REGEX.SPACE_OR_EMOJI).filter((value) => value !== '')); -} - -/** - * Validates if the text contains any emoji - */ -function containsEmoji(text: string): boolean { - return CONST.REGEX.ALL_EMOJIS.test(text); -} - -/** - * Takes a long word and splits it into an array of sub-strings. - * - * The function tests whether the length of the provided word exceeds the provided maximum length. - * If the word's length is less than or equal to `maxLength`, it returns an array with the original word. - * If the word's length exceeds 'maxLength', it utilizes a regular expression to split the word into - * substrings with a specified 'maxLength' and returns them as an array of strings. - * - * @param word The original word to be split. - * @param maxLength The maximum length of each substring. - * @return An array of substrings derived from the original word. - * - * @example - * splitLongWord('longteststring', 4); - * // Output: ['long', 'test', 'stri', 'ng'] - */ -function splitLongWord(word: string, maxLength: number): string[] { - if (word.length <= maxLength) { - return [word]; - } - - return word.match(new RegExp(`.{1,${maxLength}}`, 'g')) ?? []; -} - -function getFontSizeFromStyles(textStyles: StyleProp): number { - if (Array.isArray(textStyles)) { - for (const style of textStyles) { - if (style && 'fontSize' in style && style.fontSize) { - return style.fontSize; - } - } - } else if (textStyles && 'fontSize' in textStyles && textStyles.fontSize) { - return textStyles.fontSize; - } - - // if we cannot infer fontSize from styles, a default value is returned - return variables.fontSizeLabel; -} - -function WrappedText({children, wordStyles, textStyles}: WrappedTextProps) { - const styles = useThemeStyles(); - const {windowWidth} = useWindowDimensions(); - - const fontSize = useMemo(() => getFontSizeFromStyles(textStyles), [textStyles]); - const childrenString = typeof children === 'string' ? children : ''; - const charsPerLine = useMemo(() => Math.floor(windowWidth / (fontSize * variables.fontSizeToWidthRatio)), [windowWidth, fontSize]); - - const textMatrix = getTextMatrix(childrenString).map((row) => row.flatMap((word) => splitLongWord(word, charsPerLine))); - - if (typeof children !== 'string') { - return null; - } - - return textMatrix.map((rowText, rowIndex) => ( - - {rowText.map((colText, colIndex) => ( - // Outer View is important to vertically center the Text - - - - {Array.from(colText).map((char, charIndex) => - containsOnlyEmojis(char) ? ( - - {char} - - ) : ( - char - ), - )} - - - - ))} - - )); -} - -WrappedText.displayName = 'WrappedText'; - -export default WrappedText; - -export {splitLongWord}; diff --git a/src/components/InlineCodeBlock/index.native.tsx b/src/components/InlineCodeBlock/index.native.tsx index 8c6da229ff38..7a896dc25088 100644 --- a/src/components/InlineCodeBlock/index.native.tsx +++ b/src/components/InlineCodeBlock/index.native.tsx @@ -1,10 +1,8 @@ import React from 'react'; import type {TDefaultRendererProps} from 'react-native-render-html'; import Text from '@components/Text'; -import useThemeStyles from '@hooks/useThemeStyles'; import type InlineCodeBlockProps from './types'; import type {TTextOrTPhrasing} from './types'; -import WrappedText from './WrappedText'; /** * Retrieves the text content from a Text or Phrasing node. @@ -22,7 +20,6 @@ function getCurrentData(defaultRendererProps: TDefaultRendererProps({TDefaultRenderer, defaultRendererProps, textStyle, boxModelStyle}: InlineCodeBlockProps) { - const styles = useThemeStyles(); const data = getCurrentData(defaultRendererProps); return ( @@ -31,12 +28,6 @@ function InlineCodeBlock({TDefaultRenderer, {...defaultRendererProps} > {data} - {/* - {data} - */} ); } diff --git a/src/styles/index.ts b/src/styles/index.ts index 1afb324696a7..01437f9cc5ee 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -22,7 +22,6 @@ import type {ThemeColors} from './theme/types'; import addOutlineWidth from './utils/addOutlineWidth'; import borders from './utils/borders'; import chatContentScrollViewPlatformStyles from './utils/chatContentScrollViewPlatformStyles'; -import codeStyles from './utils/codeStyles'; import cursor from './utils/cursor'; import display from './utils/display'; import editedLabelStyles from './utils/editedLabelStyles'; @@ -130,7 +129,6 @@ const baseCodeTagStyles = (theme: ThemeColors) => borderRadius: 5, borderColor: theme.border, backgroundColor: theme.textBackground, - // backgroundColor: theme.activeComponentBG, // If we want it more highlighted } satisfies ViewStyle & MixedStyleDeclaration); const headlineFont = { @@ -210,7 +208,6 @@ const webViewStyles = (theme: ThemeColors) => paddingRight: 5, fontFamily: FontUtils.fontFamily.platform.MONOSPACE.fontFamily, // Font size is determined by getCodeFontSize function in `StyleUtils.js` - ...(codeStyles.codeTextStyle as MixedStyleDeclaration), }, img: { @@ -3359,10 +3356,6 @@ const styles = (theme: ThemeColors) => alignSelf: 'center', }, - codeWordWrapper: { - ...codeStyles.codeWordWrapper, - }, - codeWordStyle: { borderLeftWidth: 0, borderRightWidth: 0, @@ -3373,7 +3366,6 @@ const styles = (theme: ThemeColors) => paddingLeft: 0, paddingRight: 0, justifyContent: 'center', - ...codeStyles.codeWordStyle, }, codeFirstWordStyle: { @@ -3390,10 +3382,6 @@ const styles = (theme: ThemeColors) => paddingRight: 5, }, - codePlainTextStyle: { - ...codeStyles.codePlainTextStyle, - }, - fullScreenLoading: { backgroundColor: theme.componentBG, opacity: 0.8, diff --git a/src/styles/utils/codeStyles/index.android.ts b/src/styles/utils/codeStyles/index.android.ts deleted file mode 100644 index 790c5ce457a3..000000000000 --- a/src/styles/utils/codeStyles/index.android.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type {CodeTextStyles, CodeWordStyles, CodeWordWrapperStyles} from './types'; - -const codeWordWrapper: CodeWordWrapperStyles = { - // height: 20, -}; - -const codeWordStyle: CodeWordStyles = { - // height: 18, - // top: 4, -}; - -const codeTextStyle: CodeTextStyles = { - // lineHeight: 15, -}; - -const codePlainTextStyle: CodeTextStyles = { - // lineHeight: 14.5, -}; - -export default {codeWordWrapper, codeWordStyle, codeTextStyle, codePlainTextStyle}; diff --git a/src/styles/utils/codeStyles/index.ios.ts b/src/styles/utils/codeStyles/index.ios.ts deleted file mode 100644 index eca32f18231e..000000000000 --- a/src/styles/utils/codeStyles/index.ios.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type {CodeTextStyles, CodeWordStyles, CodeWordWrapperStyles} from './types'; - -const codeWordWrapper: CodeWordWrapperStyles = { - // height: 22, - // justifyContent: 'center', -}; - -const codeWordStyle: CodeWordStyles = { - // height: 18, - // top: 4, -}; - -const codeTextStyle: CodeTextStyles = { - // lineHeight: 18, -}; - -const codePlainTextStyle: CodeTextStyles = { - // lineHeight: 15, -}; - -export default {codeWordWrapper, codeWordStyle, codeTextStyle, codePlainTextStyle}; diff --git a/src/styles/utils/codeStyles/index.ts b/src/styles/utils/codeStyles/index.ts deleted file mode 100644 index 80a66df95c7c..000000000000 --- a/src/styles/utils/codeStyles/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type {CodeTextStyles, CodeWordStyles, CodeWordWrapperStyles} from './types'; - -// We do not need these on Web/Desktop as their implementation defer from Native devices so just noop them -const codeWordWrapper: CodeWordWrapperStyles = {}; -const codeWordStyle: CodeWordStyles = {}; -const codeTextStyle: CodeTextStyles = {}; -const codePlainTextStyle: CodeTextStyles = {}; -export default {codeWordWrapper, codeWordStyle, codeTextStyle, codePlainTextStyle}; diff --git a/src/styles/utils/codeStyles/types.ts b/src/styles/utils/codeStyles/types.ts deleted file mode 100644 index 245676b0a331..000000000000 --- a/src/styles/utils/codeStyles/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type {TextStyle, ViewStyle} from 'react-native'; - -type CodeWordWrapperStyles = ViewStyle; -type CodeWordStyles = ViewStyle; -type CodeTextStyles = TextStyle; - -export type {CodeTextStyles, CodeWordStyles, CodeWordWrapperStyles}; diff --git a/tests/unit/splitLongWordTest.ts b/tests/unit/splitLongWordTest.ts deleted file mode 100644 index 19f8fc98e73f..000000000000 --- a/tests/unit/splitLongWordTest.ts +++ /dev/null @@ -1,47 +0,0 @@ -import {splitLongWord} from '@components/InlineCodeBlock/WrappedText'; - -describe('splitLongWord', () => { - const testCases = [ - { - word: 'thissadasdasdsadsadasdadsadasdasdasdasdasdasdasdasdasdsadsadggggggggggggggggg', - maxLength: 4, - output: ['this', 'sada', 'sdas', 'dsad', 'sada', 'sdad', 'sada', 'sdas', 'dasd', 'asda', 'sdas', 'dasd', 'asda', 'sdsa', 'dsad', 'gggg', 'gggg', 'gggg', 'gggg', 'g'], - }, - { - word: 'https://www.google.com/search?q=google&oq=goog&gs_lcrp=EgZjaHJvbWUqEAgAEAAYgwEY4wIYsQMYgAQyEAgAEAAYgwEY4wIYsQMYgAQyEwgBEC4YgwEYxwEYsQMY0QMYgAQyDQgCEAAYgwEYsQMYgAQyBggDEEUYOzIGCAQQRRg8MgYIBRBFGDwyBggGEEUYPDIGCAcQBRhA0gEHNzM1ajBqN6gCALACAA&sourceid=chrome&ie=UTF-8', - maxLength: 20, - output: [ - 'https://www.google.c', - 'om/search?q=google&o', - 'q=goog&gs_lcrp=EgZja', - 'HJvbWUqEAgAEAAYgwEY4', - 'wIYsQMYgAQyEAgAEAAYg', - 'wEY4wIYsQMYgAQyEwgBE', - 'C4YgwEYxwEYsQMY0QMYg', - 'AQyDQgCEAAYgwEYsQMYg', - 'AQyBggDEEUYOzIGCAQQR', - 'Rg8MgYIBRBFGDwyBggGE', - 'EUYPDIGCAcQBRhA0gEHN', - 'zM1ajBqN6gCALACAA&so', - 'urceid=chrome&ie=UTF', - '-8', - ], - }, - { - word: 'superkalifragilistischexpialigetisch', - maxLength: 5, - output: ['super', 'kalif', 'ragil', 'istis', 'chexp', 'ialig', 'etisc', 'h'], - }, - { - word: 'Este es un ejemplo de texto en español para la prueba', - maxLength: 8, - output: ['Este es ', 'un ejemp', 'lo de te', 'xto en e', 'spañol p', 'ara la p', 'rueba'], - }, - ]; - - testCases.forEach(({word, maxLength, output}) => { - test(`should split ${word} into ${output.join()} with maxLength of ${maxLength}`, () => { - expect(splitLongWord(word, maxLength)).toEqual(output); - }); - }); -});