Advertisement
devil2010

Untitled

Jun 2nd, 2022
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.04 KB | None | 0 0
  1. import PropTypes from 'prop-types';
  2. import React from 'react';
  3. import { Platform, StyleSheet, View, SafeAreaView, KeyboardAvoidingView, } from 'react-native';
  4. import { ActionSheetProvider, } from '@expo/react-native-action-sheet';
  5. import uuid from 'uuid';
  6. import { getBottomSpace } from 'react-native-iphone-x-helper';
  7. import dayjs from 'dayjs';
  8. import localizedFormat from 'dayjs/plugin/localizedFormat';
  9. import * as utils from './utils';
  10. import Actions from './Actions';
  11. import Avatar from './Avatar';
  12. import Bubble from './Bubble';
  13. import SystemMessage from './SystemMessage';
  14. import MessageImage from './MessageImage';
  15. import MessageText from './MessageText';
  16. import Composer from './Composer';
  17. import Day from './Day';
  18. import InputToolbar from './InputToolbar';
  19. import LoadEarlier from './LoadEarlier';
  20. import Message from './Message';
  21. import MessageContainer from './MessageContainer';
  22. import Send from './Send';
  23. import Time from './Time';
  24. import GiftedAvatar from './GiftedAvatar';
  25. import { MIN_COMPOSER_HEIGHT, MAX_COMPOSER_HEIGHT, DEFAULT_PLACEHOLDER, TIME_FORMAT, DATE_FORMAT, } from './Constant';
  26. dayjs.extend(localizedFormat);
  27. class GiftedChat extends React.Component {
  28. constructor(props) {
  29. super(props);
  30. this._isMounted = false;
  31. this._keyboardHeight = 0;
  32. this._bottomOffset = 0;
  33. this._maxHeight = undefined;
  34. this._isFirstLayout = true;
  35. this._locale = 'en';
  36. this.invertibleScrollViewProps = undefined;
  37. this._actionSheetRef = undefined;
  38. this._messageContainerRef = React.createRef();
  39. this.state = {
  40. isInitialized: false,
  41. composerHeight: this.props.minComposerHeight,
  42. messagesContainerHeight: undefined,
  43. typingDisabled: false,
  44. text: undefined,
  45. messages: undefined,
  46. };
  47. this.getLocale = () => this._locale;
  48. this.safeAreaSupport = (bottomOffset) => {
  49. // return bottomOffset === this._bottomOffset
  50. // ? this.getBottomOffset()
  51. // ? this.getBottomOffset()
  52. // : getBottomSpace()
  53. // : bottomOffset;
  54. };
  55. this.onKeyboardWillShow = (e) => {
  56. // if (this.props.isKeyboardInternallyHandled) {
  57. // this.setIsTypingDisabled(true);
  58. // this.setKeyboardHeight(e.endCoordinates ? e.endCoordinates.height : e.end.height);
  59. // this.setBottomOffset(this.safeAreaSupport(this.props.bottomOffset));
  60. // const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard();
  61. // this.setState({
  62. // messagesContainerHeight: newMessagesContainerHeight,
  63. // });
  64. // }
  65. };
  66. this.onKeyboardWillHide = (_e) => {
  67. // if (this.props.isKeyboardInternallyHandled) {
  68. // this.setIsTypingDisabled(true);
  69. // this.setKeyboardHeight(0);
  70. // this.setBottomOffset(0);
  71. // const newMessagesContainerHeight = this.getBasicMessagesContainerHeight();
  72. // this.setState({
  73. // messagesContainerHeight: newMessagesContainerHeight,
  74. // });
  75. // }
  76. };
  77. this.onKeyboardDidShow = (e) => {
  78. // if (Platform.OS === 'android') {
  79. // this.onKeyboardWillShow(e);
  80. // }
  81. // this.setIsTypingDisabled(false);
  82. };
  83. this.onKeyboardDidHide = (e) => {
  84. // if (Platform.OS === 'android') {
  85. // this.onKeyboardWillHide(e);
  86. // }
  87. // this.setIsTypingDisabled(false);
  88. };
  89. this.onSend = (messages = [], shouldResetInputToolbar = false) => {
  90. // if (!Array.isArray(messages)) {
  91. // messages = [messages];
  92. // }
  93. // const newMessages = messages.map(message => {
  94. // return {
  95. // ...message,
  96. // user: this.props.user,
  97. // createdAt: new Date(),
  98. // _id: this.props.messageIdGenerator && this.props.messageIdGenerator(),
  99. // };
  100. // });
  101. // if (shouldResetInputToolbar === true) {
  102. // this.setIsTypingDisabled(true);
  103. // this.resetInputToolbar();
  104. // }
  105. // if (this.props.onSend) {
  106. // this.props.onSend(newMessages);
  107. // }
  108. // if (shouldResetInputToolbar === true) {
  109. // setTimeout(() => {
  110. // if (this.getIsMounted() === true) {
  111. // this.setIsTypingDisabled(false);
  112. // }
  113. // }, 100);
  114. // }
  115. };
  116. this.onInputSizeChanged = (size) => {
  117. // const newComposerHeight = Math.max(this.props.minComposerHeight, Math.min(this.props.maxComposerHeight, size.height));
  118. // const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(newComposerHeight);
  119. // this.setState({
  120. // composerHeight: newComposerHeight,
  121. // messagesContainerHeight: newMessagesContainerHeight,
  122. // });
  123. };
  124. this.onInputTextChanged = (text) => {
  125. // if (this.getIsTypingDisabled()) {
  126. // return;
  127. // }
  128. // if (this.props.onInputTextChanged) {
  129. // this.props.onInputTextChanged(text);
  130. // }
  131. // // Only set state if it's not being overridden by a prop.
  132. // if (this.props.text === undefined) {
  133. // this.setState({ text });
  134. // }
  135. };
  136. this.onInitialLayoutViewLayout = (e) => {
  137. const { layout } = e.nativeEvent;
  138. if (layout.height <= 0) {
  139. return;
  140. }
  141. this.notifyInputTextReset();
  142. this.setMaxHeight(layout.height);
  143. const newComposerHeight = this.props.minComposerHeight;
  144. const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(newComposerHeight);
  145. const initialText = this.props.initialText || '';
  146. this.setState({
  147. isInitialized: true,
  148. text: this.getTextFromProp(initialText),
  149. composerHeight: newComposerHeight,
  150. messagesContainerHeight: newMessagesContainerHeight,
  151. });
  152. };
  153. this.onMainViewLayout = (e) => {
  154. // fix an issue when keyboard is dismissing during the initialization
  155. // const { layout } = e.nativeEvent;
  156. // if (this.getMaxHeight() !== layout.height ||
  157. // this.getIsFirstLayout() === true) {
  158. // this.setMaxHeight(layout.height);
  159. // this.setState({
  160. // messagesContainerHeight: this._keyboardHeight > 0
  161. // ? this.getMessagesContainerHeightWithKeyboard()
  162. // : this.getBasicMessagesContainerHeight(),
  163. // });
  164. // }
  165. // if (this.getIsFirstLayout() === true) {
  166. // this.setIsFirstLayout(false);
  167. // }
  168. };
  169. this.invertibleScrollViewProps = {
  170. inverted: this.props.inverted,
  171. keyboardShouldPersistTaps: this.props.keyboardShouldPersistTaps,
  172. onKeyboardWillShow: this.onKeyboardWillShow,
  173. onKeyboardWillHide: this.onKeyboardWillHide,
  174. onKeyboardDidShow: this.onKeyboardDidShow,
  175. onKeyboardDidHide: this.onKeyboardDidHide,
  176. };
  177. }
  178. static append(currentMessages = [], messages, inverted = true) {
  179. if (!Array.isArray(messages)) {
  180. messages = [messages];
  181. }
  182. return inverted
  183. ? messages.concat(currentMessages)
  184. : currentMessages.concat(messages);
  185. }
  186. static prepend(currentMessages = [], messages, inverted = true) {
  187. if (!Array.isArray(messages)) {
  188. messages = [messages];
  189. }
  190. return inverted
  191. ? currentMessages.concat(messages)
  192. : messages.concat(currentMessages);
  193. }
  194. getChildContext() {
  195. return {
  196. actionSheet: this.props.actionSheet || (() => this._actionSheetRef.getContext()),
  197. getLocale: this.getLocale,
  198. };
  199. }
  200. componentDidMount() {
  201. const { messages, text } = this.props;
  202. this.setIsMounted(true);
  203. this.initLocale();
  204. this.setMessages(messages || []);
  205. this.setTextFromProp(text);
  206. }
  207. componentWillUnmount() {
  208. this.setIsMounted(false);
  209. }
  210. componentDidUpdate(prevProps = {}) {
  211. const { messages, text, inverted } = this.props;
  212. if (this.props !== prevProps) {
  213. this.setMessages(messages || []);
  214. }
  215. if (inverted === false &&
  216. messages &&
  217. prevProps.messages &&
  218. messages.length !== prevProps.messages.length) {
  219. setTimeout(() => this.scrollToBottom(false), 200);
  220. }
  221. if (text !== prevProps.text) {
  222. this.setTextFromProp(text);
  223. }
  224. }
  225. initLocale() {
  226. if (this.props.locale === null) {
  227. this.setLocale('en');
  228. }
  229. else {
  230. this.setLocale(this.props.locale || 'en');
  231. }
  232. }
  233. setLocale(locale) {
  234. this._locale = locale;
  235. }
  236. setTextFromProp(textProp) {
  237. // Text prop takes precedence over state.
  238. if (textProp !== undefined && textProp !== this.state.text) {
  239. this.setState({ text: textProp });
  240. }
  241. }
  242. getTextFromProp(fallback) {
  243. if (this.props.text === undefined) {
  244. return fallback;
  245. }
  246. return this.props.text;
  247. }
  248. setMessages(messages) {
  249. this.setState({ messages });
  250. }
  251. getMessages() {
  252. return this.state.messages;
  253. }
  254. setMaxHeight(height) {
  255. this._maxHeight = height;
  256. }
  257. getMaxHeight() {
  258. return this._maxHeight;
  259. }
  260. setKeyboardHeight(height) {
  261. this._keyboardHeight = height;
  262. }
  263. getKeyboardHeight() {
  264. if (Platform.OS === 'android' && !this.props.forceGetKeyboardHeight) {
  265. // For android: on-screen keyboard resized main container and has own height.
  266. // @see https://developer.android.com/training/keyboard-input/visibility.html
  267. // So for calculate the messages container height ignore keyboard height.
  268. return 0;
  269. }
  270. return this._keyboardHeight;
  271. }
  272. setBottomOffset(value) {
  273. this._bottomOffset = value;
  274. }
  275. getBottomOffset() {
  276. return this._bottomOffset;
  277. }
  278. setIsFirstLayout(value) {
  279. this._isFirstLayout = value;
  280. }
  281. getIsFirstLayout() {
  282. return this._isFirstLayout;
  283. }
  284. setIsTypingDisabled(value) {
  285. this.setState({
  286. typingDisabled: value,
  287. });
  288. }
  289. getIsTypingDisabled() {
  290. return this.state.typingDisabled;
  291. }
  292. setIsMounted(value) {
  293. this._isMounted = value;
  294. }
  295. getIsMounted() {
  296. return this._isMounted;
  297. }
  298. getMinInputToolbarHeight() {
  299. return this.props.minInputToolbarHeight;
  300. }
  301. setMinInputToolbarHeight(height){
  302. const newMessagesContainerHeight = this.getBasicMessagesContainerHeight() - height;
  303. this.setState({
  304. messagesContainerHeight: newMessagesContainerHeight,
  305. });
  306. }
  307.  
  308. calculateInputToolbarHeight(composerHeight) {
  309. return (composerHeight +
  310. (this.getMinInputToolbarHeight() - this.props.minComposerHeight));
  311. }
  312. /**
  313. * Returns the height, based on current window size, without taking the keyboard into account.
  314. */
  315. getBasicMessagesContainerHeight(composerHeight = this.state.composerHeight) {
  316. return (this.getMaxHeight() - this.calculateInputToolbarHeight(composerHeight));
  317. }
  318. /**
  319. * Returns the height, based on current window size, taking the keyboard into account.
  320. */
  321. getMessagesContainerHeightWithKeyboard(composerHeight = this.state.composerHeight) {
  322. return (this.getBasicMessagesContainerHeight(composerHeight) -
  323. this.getKeyboardHeight() +
  324. this.getBottomOffset());
  325. }
  326. scrollToBottom(animated = true) {
  327. if (this._messageContainerRef && this._messageContainerRef.current) {
  328. const { inverted } = this.props;
  329. if (!inverted) {
  330. this._messageContainerRef.current.scrollToEnd({ animated });
  331. }
  332. else {
  333. this._messageContainerRef.current.scrollToOffset({
  334. offset: 0,
  335. animated,
  336. });
  337. }
  338. }
  339. }
  340. renderMessages() {
  341. const { messagesContainerStyle, ...messagesContainerProps } = this.props;
  342. const fragment = (<View style={[
  343. {
  344. height: this.state.messagesContainerHeight,
  345. },
  346. messagesContainerStyle,
  347. ]}>
  348. <MessageContainer {...messagesContainerProps} invertibleScrollViewProps={this.invertibleScrollViewProps} messages={this.getMessages()} forwardRef={this._messageContainerRef} isTyping={this.props.isTyping}/>
  349. {/* {this.renderChatFooter()} */}
  350. </View>);
  351. // return this.props.isKeyboardInternallyHandled ? (<KeyboardAvoidingView enabled>{fragment}</KeyboardAvoidingView>) : (fragment);
  352. return <MessageContainer {...messagesContainerProps} invertibleScrollViewProps={this.invertibleScrollViewProps} messages={this.getMessages()} forwardRef={this._messageContainerRef} isTyping={this.props.isTyping}/>
  353.  
  354. }
  355. resetInputToolbar() {
  356. if (this.textInput) {
  357. this.textInput.clear();
  358. }
  359. this.notifyInputTextReset();
  360. const newComposerHeight = this.props.minComposerHeight;
  361. const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(newComposerHeight);
  362. this.setState({
  363. text: this.getTextFromProp(''),
  364. composerHeight: newComposerHeight,
  365. messagesContainerHeight: newMessagesContainerHeight,
  366. });
  367. }
  368. focusTextInput() {
  369. if (this.textInput) {
  370. this.textInput.focus();
  371. }
  372. }
  373. notifyInputTextReset() {
  374. // if (this.props.onInputTextChanged) {
  375. // this.props.onInputTextChanged('');
  376. // }
  377. }
  378. renderInputToolbar() {
  379. const inputToolbarProps = {
  380. ...this.props,
  381. text: this.getTextFromProp(this.state.text),
  382. composerHeight: Math.max(this.props.minComposerHeight, this.state.composerHeight),
  383. onSend: this.onSend,
  384. onInputSizeChanged: this.onInputSizeChanged,
  385. onTextChanged: this.onInputTextChanged,
  386. textInputProps: {
  387. ...this.props.textInputProps,
  388. ref: (textInput) => (this.textInput = textInput),
  389. maxLength: this.getIsTypingDisabled() ? 0 : this.props.maxInputLength,
  390. },
  391. };
  392. if (this.props.renderInputToolbar) {
  393. return this.props.renderInputToolbar(inputToolbarProps);
  394. }
  395. return <InputToolbar {...inputToolbarProps}/>;
  396. }
  397. renderChatFooter() {
  398. if (this.props.renderChatFooter) {
  399. return this.props.renderChatFooter();
  400. }
  401. return null;
  402. }
  403. renderLoading() {
  404. if (this.props.renderLoading) {
  405. return this.props.renderLoading();
  406. }
  407. return null;
  408. }
  409. render() {
  410. if (this.state.isInitialized === true) {
  411. const { wrapInSafeArea } = this.props;
  412. const Wrapper = wrapInSafeArea ? SafeAreaView : View;
  413. // return (<Wrapper style={styles.safeArea}>
  414. {/* <ActionSheetProvider ref={(component) => (this._actionSheetRef = component)}> */}
  415. return <View style={styles.container} onLayout={this.onMainViewLayout}>
  416. {this.renderMessages()}
  417. {this.renderInputToolbar()}
  418. </View>
  419. {/* </ActionSheetProvider> */}
  420. // </Wrapper>);
  421. }
  422. return (<View style={styles.container} onLayout={this.onInitialLayoutViewLayout}>
  423. {this.renderLoading()}
  424. </View>);
  425. }
  426. }
  427. GiftedChat.childContextTypes = {
  428. actionSheet: PropTypes.func,
  429. getLocale: PropTypes.func,
  430. };
  431. GiftedChat.defaultProps = {
  432. messages: [],
  433. messagesContainerStyle: undefined,
  434. text: undefined,
  435. placeholder: DEFAULT_PLACEHOLDER,
  436. disableComposer: false,
  437. messageIdGenerator: () => uuid.v4(),
  438. user: {},
  439. onSend: () => { },
  440. locale: null,
  441. timeFormat: TIME_FORMAT,
  442. dateFormat: DATE_FORMAT,
  443. loadEarlier: false,
  444. onLoadEarlier: () => { },
  445. isLoadingEarlier: false,
  446. renderLoading: null,
  447. renderLoadEarlier: null,
  448. renderAvatar: undefined,
  449. showUserAvatar: false,
  450. actionSheet: null,
  451. onPressAvatar: null,
  452. onLongPressAvatar: null,
  453. renderUsernameOnMessage: false,
  454. renderAvatarOnTop: false,
  455. renderBubble: null,
  456. renderSystemMessage: null,
  457. onLongPress: null,
  458. renderMessage: null,
  459. renderMessageText: null,
  460. renderMessageImage: null,
  461. imageProps: {},
  462. videoProps: {},
  463. audioProps: {},
  464. lightboxProps: {},
  465. textInputProps: {},
  466. listViewProps: {},
  467. renderCustomView: null,
  468. isCustomViewBottom: false,
  469. renderDay: null,
  470. renderTime: null,
  471. renderFooter: null,
  472. renderChatEmpty: null,
  473. renderChatFooter: null,
  474. renderInputToolbar: null,
  475. renderComposer: null,
  476. renderActions: null,
  477. renderSend: null,
  478. renderAccessory: null,
  479. isKeyboardInternallyHandled: true,
  480. onPressActionButton: null,
  481. bottomOffset: 0,
  482. minInputToolbarHeight: 44,
  483. keyboardShouldPersistTaps: Platform.select({
  484. ios: 'never',
  485. android: 'always',
  486. default: 'never',
  487. }),
  488. onInputTextChanged: null,
  489. maxInputLength: null,
  490. forceGetKeyboardHeight: false,
  491. inverted: true,
  492. extraData: null,
  493. minComposerHeight: MIN_COMPOSER_HEIGHT,
  494. maxComposerHeight: MAX_COMPOSER_HEIGHT,
  495. wrapInSafeArea: true,
  496. };
  497. GiftedChat.propTypes = {
  498. messages: PropTypes.arrayOf(PropTypes.object),
  499. messagesContainerStyle: utils.StylePropType,
  500. text: PropTypes.string,
  501. initialText: PropTypes.string,
  502. placeholder: PropTypes.string,
  503. disableComposer: PropTypes.bool,
  504. messageIdGenerator: PropTypes.func,
  505. user: PropTypes.object,
  506. onSend: PropTypes.func,
  507. locale: PropTypes.string,
  508. timeFormat: PropTypes.string,
  509. dateFormat: PropTypes.string,
  510. isKeyboardInternallyHandled: PropTypes.bool,
  511. loadEarlier: PropTypes.bool,
  512. onLoadEarlier: PropTypes.func,
  513. isLoadingEarlier: PropTypes.bool,
  514. renderLoading: PropTypes.func,
  515. renderLoadEarlier: PropTypes.func,
  516. renderAvatar: PropTypes.func,
  517. showUserAvatar: PropTypes.bool,
  518. actionSheet: PropTypes.func,
  519. onPressAvatar: PropTypes.func,
  520. onLongPressAvatar: PropTypes.func,
  521. renderUsernameOnMessage: PropTypes.bool,
  522. renderAvatarOnTop: PropTypes.bool,
  523. isCustomViewBottom: PropTypes.bool,
  524. renderBubble: PropTypes.func,
  525. renderSystemMessage: PropTypes.func,
  526. onLongPress: PropTypes.func,
  527. renderMessage: PropTypes.func,
  528. renderMessageText: PropTypes.func,
  529. renderMessageImage: PropTypes.func,
  530. imageProps: PropTypes.object,
  531. videoProps: PropTypes.object,
  532. audioProps: PropTypes.object,
  533. lightboxProps: PropTypes.object,
  534. renderCustomView: PropTypes.func,
  535. renderDay: PropTypes.func,
  536. renderTime: PropTypes.func,
  537. renderFooter: PropTypes.func,
  538. renderChatEmpty: PropTypes.func,
  539. renderChatFooter: PropTypes.func,
  540. renderInputToolbar: PropTypes.func,
  541. renderComposer: PropTypes.func,
  542. renderActions: PropTypes.func,
  543. renderSend: PropTypes.func,
  544. renderAccessory: PropTypes.func,
  545. onPressActionButton: PropTypes.func,
  546. bottomOffset: PropTypes.number,
  547. minInputToolbarHeight: PropTypes.number,
  548. listViewProps: PropTypes.object,
  549. keyboardShouldPersistTaps: PropTypes.oneOf(['always', 'never', 'handled']),
  550. onInputTextChanged: PropTypes.func,
  551. maxInputLength: PropTypes.number,
  552. forceGetKeyboardHeight: PropTypes.bool,
  553. inverted: PropTypes.bool,
  554. textInputProps: PropTypes.object,
  555. extraData: PropTypes.object,
  556. minComposerHeight: PropTypes.number,
  557. maxComposerHeight: PropTypes.number,
  558. alignTop: PropTypes.bool,
  559. wrapInSafeArea: PropTypes.bool,
  560. };
  561. const styles = StyleSheet.create({
  562. container: {
  563. flex: 1,
  564. },
  565. safeArea: {
  566. flex: 1,
  567. },
  568. });
  569. export { GiftedChat, Actions, Avatar, Bubble, SystemMessage, MessageImage, MessageText, Composer, Day, InputToolbar, LoadEarlier, Message, MessageContainer, Send, Time, GiftedAvatar, utils, };
  570. //# sourceMappingURL=GiftedChat.js.map
  571.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement