1*26ad19fcSEvan Bacon/**
2*26ad19fcSEvan Bacon * Copyright (c) 650 Industries.
3*26ad19fcSEvan Bacon * Copyright (c) Meta Platforms, Inc. and affiliates.
4*26ad19fcSEvan Bacon *
5*26ad19fcSEvan Bacon * This source code is licensed under the MIT license found in the
6*26ad19fcSEvan Bacon * LICENSE file in the root directory of this source tree.
7*26ad19fcSEvan Bacon */
8*26ad19fcSEvan Baconimport React from 'react';
9*26ad19fcSEvan Baconimport { StyleProp, Text, TextStyle } from 'react-native';
10*26ad19fcSEvan Bacon
11*26ad19fcSEvan Baconimport type { Message } from '../Data/parseLogBoxLog';
12*26ad19fcSEvan Bacon
13*26ad19fcSEvan Bacontype Props = {
14*26ad19fcSEvan Bacon  message: Message;
15*26ad19fcSEvan Bacon  style: StyleProp<TextStyle>;
16*26ad19fcSEvan Bacon  plaintext?: boolean;
17*26ad19fcSEvan Bacon  maxLength?: number;
18*26ad19fcSEvan Bacon};
19*26ad19fcSEvan Bacon
20*26ad19fcSEvan Baconconst cleanContent = (content: string) =>
21*26ad19fcSEvan Bacon  content.replace(/^(TransformError |Warning: (Warning: )?|Error: )/g, '');
22*26ad19fcSEvan Bacon
23*26ad19fcSEvan Baconexport function LogBoxMessage(props: Props): JSX.Element {
24*26ad19fcSEvan Bacon  const { content, substitutions }: Message = props.message;
25*26ad19fcSEvan Bacon
26*26ad19fcSEvan Bacon  if (props.plaintext === true) {
27*26ad19fcSEvan Bacon    return <Text>{cleanContent(content)}</Text>;
28*26ad19fcSEvan Bacon  }
29*26ad19fcSEvan Bacon
30*26ad19fcSEvan Bacon  const maxLength = props.maxLength != null ? props.maxLength : Infinity;
31*26ad19fcSEvan Bacon  const substitutionStyle: StyleProp<TextStyle> = props.style;
32*26ad19fcSEvan Bacon  const elements: JSX.Element[] = [];
33*26ad19fcSEvan Bacon  let length = 0;
34*26ad19fcSEvan Bacon  const createUnderLength = (key: string | '-1', message: string, style?: StyleProp<TextStyle>) => {
35*26ad19fcSEvan Bacon    let cleanMessage = cleanContent(message);
36*26ad19fcSEvan Bacon
37*26ad19fcSEvan Bacon    if (props.maxLength != null) {
38*26ad19fcSEvan Bacon      cleanMessage = cleanMessage.slice(0, props.maxLength - length);
39*26ad19fcSEvan Bacon    }
40*26ad19fcSEvan Bacon
41*26ad19fcSEvan Bacon    if (length < maxLength) {
42*26ad19fcSEvan Bacon      elements.push(
43*26ad19fcSEvan Bacon        <Text key={key} style={style}>
44*26ad19fcSEvan Bacon          {cleanMessage}
45*26ad19fcSEvan Bacon        </Text>
46*26ad19fcSEvan Bacon      );
47*26ad19fcSEvan Bacon    }
48*26ad19fcSEvan Bacon
49*26ad19fcSEvan Bacon    length += cleanMessage.length;
50*26ad19fcSEvan Bacon  };
51*26ad19fcSEvan Bacon
52*26ad19fcSEvan Bacon  const lastOffset = substitutions.reduce((prevOffset, substitution, index) => {
53*26ad19fcSEvan Bacon    const key = String(index);
54*26ad19fcSEvan Bacon
55*26ad19fcSEvan Bacon    if (substitution.offset > prevOffset) {
56*26ad19fcSEvan Bacon      const prevPart = content.substr(prevOffset, substitution.offset - prevOffset);
57*26ad19fcSEvan Bacon
58*26ad19fcSEvan Bacon      createUnderLength(key, prevPart);
59*26ad19fcSEvan Bacon    }
60*26ad19fcSEvan Bacon
61*26ad19fcSEvan Bacon    const substititionPart = content.substr(substitution.offset, substitution.length);
62*26ad19fcSEvan Bacon
63*26ad19fcSEvan Bacon    createUnderLength(key + '.5', substititionPart, substitutionStyle);
64*26ad19fcSEvan Bacon    return substitution.offset + substitution.length;
65*26ad19fcSEvan Bacon  }, 0);
66*26ad19fcSEvan Bacon
67*26ad19fcSEvan Bacon  if (lastOffset < content.length) {
68*26ad19fcSEvan Bacon    const lastPart = content.substr(lastOffset);
69*26ad19fcSEvan Bacon    createUnderLength('-1', lastPart);
70*26ad19fcSEvan Bacon  }
71*26ad19fcSEvan Bacon
72*26ad19fcSEvan Bacon  return <>{elements}</>;
73*26ad19fcSEvan Bacon}
74