Created
October 29, 2019 19:02
-
-
Save GollyJer/9a53bc2b3346b14e811bf0fe5a663ddb to your computer and use it in GitHub Desktop.
Patch react-native-gifted-chat to eliminate need for sizing code. Allows the chat data to stay cached.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/node_modules/react-native-gifted-chat/lib/GiftedChat.js b/node_modules/react-native-gifted-chat/lib/GiftedChat.js | |
| index 7f3f4b5..78ea7a1 100644 | |
| --- a/node_modules/react-native-gifted-chat/lib/GiftedChat.js | |
| +++ b/node_modules/react-native-gifted-chat/lib/GiftedChat.js | |
| @@ -1,6 +1,13 @@ | |
| import PropTypes from 'prop-types'; | |
| import React from 'react'; | |
| -import { Animated, Platform, StyleSheet, View, SafeAreaView, } from 'react-native'; | |
| +import { | |
| + Animated, | |
| + Platform, | |
| + StyleSheet, | |
| + View, | |
| + KeyboardAvoidingView, | |
| + SafeAreaView, | |
| +} from 'react-native'; | |
| import ActionSheet from '@expo/react-native-action-sheet'; | |
| import moment from 'moment'; | |
| import uuid from 'uuid'; | |
| @@ -21,520 +28,626 @@ import MessageContainer from './MessageContainer'; | |
| import Send from './Send'; | |
| import Time from './Time'; | |
| import GiftedAvatar from './GiftedAvatar'; | |
| -import { MIN_COMPOSER_HEIGHT, MAX_COMPOSER_HEIGHT, DEFAULT_PLACEHOLDER, TIME_FORMAT, DATE_FORMAT, } from './Constant'; | |
| +import { | |
| + MIN_COMPOSER_HEIGHT, | |
| + MAX_COMPOSER_HEIGHT, | |
| + DEFAULT_PLACEHOLDER, | |
| + TIME_FORMAT, | |
| + DATE_FORMAT, | |
| +} from './Constant'; | |
| + | |
| const GiftedActionSheet = ActionSheet; | |
| class GiftedChat extends React.Component { | |
| - constructor(props) { | |
| - super(props); | |
| - this._isMounted = false; | |
| - this._keyboardHeight = 0; | |
| - this._bottomOffset = 0; | |
| - this._maxHeight = undefined; | |
| - this._isFirstLayout = true; | |
| - this._locale = 'en'; | |
| - this._messages = []; | |
| - this.invertibleScrollViewProps = undefined; | |
| - this._actionSheetRef = undefined; | |
| - this._messageContainerRef = React.createRef(); | |
| - this.state = { | |
| - isInitialized: false, | |
| - composerHeight: this.props.minComposerHeight, | |
| - messagesContainerHeight: undefined, | |
| - typingDisabled: false, | |
| - text: undefined, | |
| - }; | |
| - this.getLocale = () => this._locale; | |
| - this.safeAreaIphoneX = (bottomOffset) => { | |
| - if (isIphoneX()) { | |
| - return bottomOffset === this._bottomOffset ? 33 : bottomOffset; | |
| - } | |
| - return bottomOffset; | |
| - }; | |
| - this.onKeyboardWillShow = (e) => { | |
| - this.setIsTypingDisabled(true); | |
| - this.setKeyboardHeight(e.endCoordinates ? e.endCoordinates.height : e.end.height); | |
| - this.setBottomOffset(this.safeAreaIphoneX(this.props.bottomOffset)); | |
| - const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(); | |
| - if (this.props.isAnimated === true) { | |
| - Animated.timing(this.state.messagesContainerHeight, { | |
| - toValue: newMessagesContainerHeight, | |
| - duration: 210, | |
| - }).start(); | |
| - } | |
| - else { | |
| - this.setState({ | |
| - messagesContainerHeight: newMessagesContainerHeight, | |
| - }); | |
| - } | |
| - }; | |
| - this.onKeyboardWillHide = (_e) => { | |
| - this.setIsTypingDisabled(true); | |
| - this.setKeyboardHeight(0); | |
| - this.setBottomOffset(0); | |
| - const newMessagesContainerHeight = this.getBasicMessagesContainerHeight(); | |
| - if (this.props.isAnimated === true) { | |
| - Animated.timing(this.state.messagesContainerHeight, { | |
| - toValue: newMessagesContainerHeight, | |
| - duration: 210, | |
| - }).start(); | |
| - } | |
| - else { | |
| - this.setState({ | |
| - messagesContainerHeight: newMessagesContainerHeight, | |
| - }); | |
| - } | |
| - }; | |
| - this.onKeyboardDidShow = (e) => { | |
| - if (Platform.OS === 'android') { | |
| - this.onKeyboardWillShow(e); | |
| - } | |
| - this.setIsTypingDisabled(false); | |
| - }; | |
| - this.onKeyboardDidHide = (e) => { | |
| - if (Platform.OS === 'android') { | |
| - this.onKeyboardWillHide(e); | |
| - } | |
| - this.setIsTypingDisabled(false); | |
| - }; | |
| - this.onSend = (messages = [], shouldResetInputToolbar = false) => { | |
| - if (!Array.isArray(messages)) { | |
| - messages = [messages]; | |
| - } | |
| - const newMessages = messages.map(message => { | |
| - return { | |
| - ...message, | |
| - user: this.props.user, | |
| - createdAt: new Date(), | |
| - _id: this.props.messageIdGenerator && this.props.messageIdGenerator(), | |
| - }; | |
| - }); | |
| - if (shouldResetInputToolbar === true) { | |
| - this.setIsTypingDisabled(true); | |
| - this.resetInputToolbar(); | |
| - } | |
| - if (this.props.onSend) { | |
| - this.props.onSend(newMessages); | |
| - } | |
| - this.scrollToBottom(); | |
| - if (shouldResetInputToolbar === true) { | |
| - setTimeout(() => { | |
| - if (this.getIsMounted() === true) { | |
| - this.setIsTypingDisabled(false); | |
| - } | |
| - }, 100); | |
| - } | |
| - }; | |
| - this.onInputSizeChanged = (size) => { | |
| - const newComposerHeight = Math.max(this.props.minComposerHeight, Math.min(this.props.maxComposerHeight, size.height)); | |
| - const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(newComposerHeight); | |
| - this.setState({ | |
| - composerHeight: newComposerHeight, | |
| - messagesContainerHeight: this.prepareMessagesContainerHeight(newMessagesContainerHeight), | |
| - }); | |
| - }; | |
| - this.onInputTextChanged = (text) => { | |
| - if (this.getIsTypingDisabled()) { | |
| - return; | |
| - } | |
| - if (this.props.onInputTextChanged) { | |
| - this.props.onInputTextChanged(text); | |
| - } | |
| - // Only set state if it's not being overridden by a prop. | |
| - if (this.props.text === undefined) { | |
| - this.setState({ text }); | |
| - } | |
| - }; | |
| - this.onInitialLayoutViewLayout = (e) => { | |
| - const { layout } = e.nativeEvent; | |
| - if (layout.height <= 0) { | |
| - return; | |
| - } | |
| - this.notifyInputTextReset(); | |
| - this.setMaxHeight(layout.height); | |
| - const newComposerHeight = this.props.minComposerHeight; | |
| - const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(newComposerHeight); | |
| - const initialText = this.props.initialText || ''; | |
| - this.setState({ | |
| - isInitialized: true, | |
| - text: this.getTextFromProp(initialText), | |
| - composerHeight: newComposerHeight, | |
| - messagesContainerHeight: this.prepareMessagesContainerHeight(newMessagesContainerHeight), | |
| - }); | |
| - }; | |
| - this.onMainViewLayout = (e) => { | |
| - // fix an issue when keyboard is dismissing during the initialization | |
| - const { layout } = e.nativeEvent; | |
| - if (this.getMaxHeight() !== layout.height || | |
| - this.getIsFirstLayout() === true) { | |
| - this.setMaxHeight(layout.height); | |
| - this.setState({ | |
| - messagesContainerHeight: this.prepareMessagesContainerHeight(this.getBasicMessagesContainerHeight()), | |
| - }); | |
| - } | |
| - if (this.getIsFirstLayout() === true) { | |
| - this.setIsFirstLayout(false); | |
| - } | |
| - }; | |
| - this.invertibleScrollViewProps = { | |
| - inverted: this.props.inverted, | |
| - keyboardShouldPersistTaps: this.props.keyboardShouldPersistTaps, | |
| - onKeyboardWillShow: this.onKeyboardWillShow, | |
| - onKeyboardWillHide: this.onKeyboardWillHide, | |
| - onKeyboardDidShow: this.onKeyboardDidShow, | |
| - onKeyboardDidHide: this.onKeyboardDidHide, | |
| - }; | |
| - } | |
| - static append(currentMessages = [], messages, inverted = true) { | |
| - if (!Array.isArray(messages)) { | |
| - messages = [messages]; | |
| - } | |
| - return inverted | |
| - ? messages.concat(currentMessages) | |
| - : currentMessages.concat(messages); | |
| - } | |
| - static prepend(currentMessages = [], messages, inverted = true) { | |
| - if (!Array.isArray(messages)) { | |
| - messages = [messages]; | |
| - } | |
| - return inverted | |
| - ? currentMessages.concat(messages) | |
| - : messages.concat(currentMessages); | |
| - } | |
| - getChildContext() { | |
| - return { | |
| - actionSheet: () => this._actionSheetRef, | |
| - getLocale: this.getLocale, | |
| - }; | |
| - } | |
| - componentWillMount() { | |
| - const { messages, text } = this.props; | |
| - this.setIsMounted(true); | |
| - this.initLocale(); | |
| - this.setMessages(messages || []); | |
| - this.setTextFromProp(text); | |
| - } | |
| - componentWillUnmount() { | |
| - this.setIsMounted(false); | |
| - } | |
| - componentWillReceiveProps(nextProps = {}) { | |
| - const { messages, text } = nextProps; | |
| - this.setMessages(messages || []); | |
| - this.setTextFromProp(text); | |
| - } | |
| - initLocale() { | |
| - if (this.props.locale === null || | |
| - moment.locales().indexOf(this.props.locale || 'en') === -1) { | |
| - this.setLocale('en'); | |
| - } | |
| - else { | |
| - this.setLocale(this.props.locale || 'en'); | |
| - } | |
| - } | |
| - setLocale(locale) { | |
| - this._locale = locale; | |
| - } | |
| - setTextFromProp(textProp) { | |
| - // Text prop takes precedence over state. | |
| - if (textProp !== undefined && textProp !== this.state.text) { | |
| - this.setState({ text: textProp }); | |
| - } | |
| - } | |
| - getTextFromProp(fallback) { | |
| - if (this.props.text === undefined) { | |
| - return fallback; | |
| - } | |
| - return this.props.text; | |
| - } | |
| - setMessages(messages) { | |
| - this._messages = messages; | |
| - } | |
| - getMessages() { | |
| - return this._messages; | |
| - } | |
| - setMaxHeight(height) { | |
| - this._maxHeight = height; | |
| - } | |
| - getMaxHeight() { | |
| - return this._maxHeight; | |
| - } | |
| - setKeyboardHeight(height) { | |
| - this._keyboardHeight = height; | |
| - } | |
| - getKeyboardHeight() { | |
| - if (Platform.OS === 'android' && !this.props.forceGetKeyboardHeight) { | |
| - // For android: on-screen keyboard resized main container and has own height. | |
| - // @see https://developer.android.com/training/keyboard-input/visibility.html | |
| - // So for calculate the messages container height ignore keyboard height. | |
| - return 0; | |
| - } | |
| - return this._keyboardHeight; | |
| - } | |
| - setBottomOffset(value) { | |
| - this._bottomOffset = value; | |
| - } | |
| - getBottomOffset() { | |
| - return this._bottomOffset; | |
| - } | |
| - setIsFirstLayout(value) { | |
| - this._isFirstLayout = value; | |
| - } | |
| - getIsFirstLayout() { | |
| - return this._isFirstLayout; | |
| - } | |
| - setIsTypingDisabled(value) { | |
| + constructor(props) { | |
| + super(props); | |
| + this._isMounted = false; | |
| + this._keyboardHeight = 0; | |
| + this._bottomOffset = 0; | |
| + this._maxHeight = undefined; | |
| + this._isFirstLayout = true; | |
| + this._locale = 'en'; | |
| + this._messages = []; | |
| + this.invertibleScrollViewProps = undefined; | |
| + this._actionSheetRef = undefined; | |
| + this._messageContainerRef = React.createRef(); | |
| + this.state = { | |
| + isInitialized: false, | |
| + composerHeight: this.props.minComposerHeight, | |
| + messagesContainerHeight: undefined, | |
| + typingDisabled: false, | |
| + text: undefined, | |
| + }; | |
| + this.getLocale = () => this._locale; | |
| + this.safeAreaIphoneX = (bottomOffset) => { | |
| + if (isIphoneX()) { | |
| + return bottomOffset === this._bottomOffset ? 33 : bottomOffset; | |
| + } | |
| + return bottomOffset; | |
| + }; | |
| + this.onKeyboardWillShow = (e) => { | |
| + this.setIsTypingDisabled(true); | |
| + this.setKeyboardHeight( | |
| + e.endCoordinates ? e.endCoordinates.height : e.end.height, | |
| + ); | |
| + this.setBottomOffset(this.safeAreaIphoneX(this.props.bottomOffset)); | |
| + const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(); | |
| + if (this.props.isAnimated === true) { | |
| + Animated.timing(this.state.messagesContainerHeight, { | |
| + toValue: newMessagesContainerHeight, | |
| + duration: 210, | |
| + }).start(); | |
| + } else { | |
| this.setState({ | |
| - typingDisabled: value, | |
| + messagesContainerHeight: newMessagesContainerHeight, | |
| }); | |
| - } | |
| - getIsTypingDisabled() { | |
| - return this.state.typingDisabled; | |
| - } | |
| - setIsMounted(value) { | |
| - this._isMounted = value; | |
| - } | |
| - getIsMounted() { | |
| - return this._isMounted; | |
| - } | |
| - getMinInputToolbarHeight() { | |
| - return this.props.renderAccessory | |
| - ? this.props.minInputToolbarHeight * 2 | |
| - : this.props.minInputToolbarHeight; | |
| - } | |
| - calculateInputToolbarHeight(composerHeight) { | |
| - return (composerHeight + | |
| - (this.getMinInputToolbarHeight() - this.props.minComposerHeight)); | |
| - } | |
| - /** | |
| - * Returns the height, based on current window size, without taking the keyboard into account. | |
| - */ | |
| - getBasicMessagesContainerHeight(composerHeight = this.state.composerHeight) { | |
| - return (this.getMaxHeight() - this.calculateInputToolbarHeight(composerHeight)); | |
| - } | |
| - /** | |
| - * Returns the height, based on current window size, taking the keyboard into account. | |
| - */ | |
| - getMessagesContainerHeightWithKeyboard(composerHeight = this.state.composerHeight) { | |
| - return (this.getBasicMessagesContainerHeight(composerHeight) - | |
| - this.getKeyboardHeight() + | |
| - this.getBottomOffset()); | |
| - } | |
| - prepareMessagesContainerHeight(value) { | |
| - if (this.props.isAnimated === true) { | |
| - return new Animated.Value(value); | |
| - } | |
| - return value; | |
| - } | |
| - scrollToBottom(animated = true) { | |
| - if (this._messageContainerRef && this._messageContainerRef.current) { | |
| - this._messageContainerRef.current.scrollTo({ offset: 0, animated }); | |
| - } | |
| - } | |
| - renderMessages() { | |
| - const AnimatedView = this.props.isAnimated === true ? Animated.View : View; | |
| - return (<AnimatedView style={{ | |
| - height: this.state.messagesContainerHeight, | |
| - }}> | |
| - <MessageContainer {...this.props} invertibleScrollViewProps={this.invertibleScrollViewProps} messages={this.getMessages()} ref={this._messageContainerRef}/> | |
| - {this.renderChatFooter()} | |
| - </AnimatedView>); | |
| - } | |
| - resetInputToolbar() { | |
| - if (this.textInput) { | |
| - this.textInput.clear(); | |
| - } | |
| - this.notifyInputTextReset(); | |
| - const newComposerHeight = this.props.minComposerHeight; | |
| - const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(newComposerHeight); | |
| + } | |
| + }; | |
| + this.onKeyboardWillHide = (_e) => { | |
| + this.setIsTypingDisabled(true); | |
| + this.setKeyboardHeight(0); | |
| + this.setBottomOffset(0); | |
| + const newMessagesContainerHeight = this.getBasicMessagesContainerHeight(); | |
| + if (this.props.isAnimated === true) { | |
| + Animated.timing(this.state.messagesContainerHeight, { | |
| + toValue: newMessagesContainerHeight, | |
| + duration: 210, | |
| + }).start(); | |
| + } else { | |
| this.setState({ | |
| - text: this.getTextFromProp(''), | |
| - composerHeight: newComposerHeight, | |
| - messagesContainerHeight: this.prepareMessagesContainerHeight(newMessagesContainerHeight), | |
| + messagesContainerHeight: newMessagesContainerHeight, | |
| }); | |
| - } | |
| - focusTextInput() { | |
| - if (this.textInput) { | |
| - this.textInput.focus(); | |
| - } | |
| - } | |
| - notifyInputTextReset() { | |
| - if (this.props.onInputTextChanged) { | |
| - this.props.onInputTextChanged(''); | |
| - } | |
| - } | |
| - renderInputToolbar() { | |
| - const inputToolbarProps = { | |
| - ...this.props, | |
| - text: this.getTextFromProp(this.state.text), | |
| - composerHeight: Math.max(this.props.minComposerHeight, this.state.composerHeight), | |
| - onSend: this.onSend, | |
| - onInputSizeChanged: this.onInputSizeChanged, | |
| - onTextChanged: this.onInputTextChanged, | |
| - textInputProps: { | |
| - ...this.props.textInputProps, | |
| - ref: (textInput) => (this.textInput = textInput), | |
| - maxLength: this.getIsTypingDisabled() ? 0 : this.props.maxInputLength, | |
| - }, | |
| - }; | |
| - if (this.props.renderInputToolbar) { | |
| - return this.props.renderInputToolbar(inputToolbarProps); | |
| - } | |
| - return <InputToolbar {...inputToolbarProps}/>; | |
| - } | |
| - renderChatFooter() { | |
| - if (this.props.renderChatFooter) { | |
| - return this.props.renderChatFooter(); | |
| - } | |
| - return null; | |
| - } | |
| - renderLoading() { | |
| - if (this.props.renderLoading) { | |
| - return this.props.renderLoading(); | |
| - } | |
| - return null; | |
| - } | |
| - render() { | |
| - if (this.state.isInitialized === true) { | |
| - return (<SafeAreaView style={styles.safeArea}> | |
| - <GiftedActionSheet ref={(component) => (this._actionSheetRef = component)}> | |
| - <View style={styles.container} onLayout={this.onMainViewLayout}> | |
| - {this.renderMessages()} | |
| - {this.renderInputToolbar()} | |
| - </View> | |
| - </GiftedActionSheet> | |
| - </SafeAreaView>); | |
| - } | |
| - return (<View style={styles.container} onLayout={this.onInitialLayoutViewLayout}> | |
| - {this.renderLoading()} | |
| - </View>); | |
| - } | |
| + } | |
| + }; | |
| + this.onKeyboardDidShow = (e) => { | |
| + if (Platform.OS === 'android') { | |
| + this.onKeyboardWillShow(e); | |
| + } | |
| + this.setIsTypingDisabled(false); | |
| + }; | |
| + this.onKeyboardDidHide = (e) => { | |
| + if (Platform.OS === 'android') { | |
| + this.onKeyboardWillHide(e); | |
| + } | |
| + this.setIsTypingDisabled(false); | |
| + }; | |
| + this.onSend = (messages = [], shouldResetInputToolbar = false) => { | |
| + if (!Array.isArray(messages)) { | |
| + messages = [messages]; | |
| + } | |
| + const newMessages = messages.map(message => ({ | |
| + ...message, | |
| + user: this.props.user, | |
| + createdAt: new Date(), | |
| + _id: this.props.messageIdGenerator && this.props.messageIdGenerator(), | |
| + })); | |
| + if (shouldResetInputToolbar === true) { | |
| + this.setIsTypingDisabled(true); | |
| + this.resetInputToolbar(); | |
| + } | |
| + if (this.props.onSend) { | |
| + this.props.onSend(newMessages); | |
| + } | |
| + this.scrollToBottom(); | |
| + if (shouldResetInputToolbar === true) { | |
| + setTimeout(() => { | |
| + if (this.getIsMounted() === true) { | |
| + this.setIsTypingDisabled(false); | |
| + } | |
| + }, 100); | |
| + } | |
| + }; | |
| + this.onInputSizeChanged = (size) => { | |
| + const newComposerHeight = Math.max( | |
| + this.props.minComposerHeight, | |
| + Math.min(this.props.maxComposerHeight, size.height), | |
| + ); | |
| + const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard( | |
| + newComposerHeight, | |
| + ); | |
| + this.setState({ | |
| + composerHeight: newComposerHeight, | |
| + messagesContainerHeight: this.prepareMessagesContainerHeight( | |
| + newMessagesContainerHeight, | |
| + ), | |
| + }); | |
| + }; | |
| + this.onInputTextChanged = (text) => { | |
| + if (this.getIsTypingDisabled()) { | |
| + return; | |
| + } | |
| + if (this.props.onInputTextChanged) { | |
| + this.props.onInputTextChanged(text); | |
| + } | |
| + // Only set state if it's not being overridden by a prop. | |
| + if (this.props.text === undefined) { | |
| + this.setState({ text }); | |
| + } | |
| + }; | |
| + this.onInitialLayoutViewLayout = (e) => { | |
| + const { layout } = e.nativeEvent; | |
| + if (layout.height <= 0) { | |
| + return; | |
| + } | |
| + this.notifyInputTextReset(); | |
| + this.setMaxHeight(layout.height); | |
| + const newComposerHeight = this.props.minComposerHeight; | |
| + const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard( | |
| + newComposerHeight, | |
| + ); | |
| + const initialText = this.props.initialText || ''; | |
| + this.setState({ | |
| + isInitialized: true, | |
| + text: this.getTextFromProp(initialText), | |
| + composerHeight: newComposerHeight, | |
| + messagesContainerHeight: this.prepareMessagesContainerHeight( | |
| + newMessagesContainerHeight, | |
| + ), | |
| + }); | |
| + }; | |
| + this.onMainViewLayout = (e) => { | |
| + // fix an issue when keyboard is dismissing during the initialization | |
| + const { layout } = e.nativeEvent; | |
| + if ( | |
| + this.getMaxHeight() !== layout.height | |
| + || this.getIsFirstLayout() === true | |
| + ) { | |
| + this.setMaxHeight(layout.height); | |
| + this.setState({ | |
| + messagesContainerHeight: this.prepareMessagesContainerHeight( | |
| + this.getBasicMessagesContainerHeight(), | |
| + ), | |
| + }); | |
| + } | |
| + if (this.getIsFirstLayout() === true) { | |
| + this.setIsFirstLayout(false); | |
| + } | |
| + }; | |
| + this.invertibleScrollViewProps = { | |
| + inverted: this.props.inverted, | |
| + keyboardShouldPersistTaps: this.props.keyboardShouldPersistTaps, | |
| + onKeyboardWillShow: this.onKeyboardWillShow, | |
| + onKeyboardWillHide: this.onKeyboardWillHide, | |
| + onKeyboardDidShow: this.onKeyboardDidShow, | |
| + onKeyboardDidHide: this.onKeyboardDidHide, | |
| + }; | |
| + } | |
| + | |
| + static append(currentMessages = [], messages, inverted = true) { | |
| + if (!Array.isArray(messages)) { | |
| + messages = [messages]; | |
| + } | |
| + return inverted | |
| + ? messages.concat(currentMessages) | |
| + : currentMessages.concat(messages); | |
| + } | |
| + | |
| + static prepend(currentMessages = [], messages, inverted = true) { | |
| + if (!Array.isArray(messages)) { | |
| + messages = [messages]; | |
| + } | |
| + return inverted | |
| + ? currentMessages.concat(messages) | |
| + : messages.concat(currentMessages); | |
| + } | |
| + | |
| + getChildContext() { | |
| + return { | |
| + actionSheet: () => this._actionSheetRef, | |
| + getLocale: this.getLocale, | |
| + }; | |
| + } | |
| + | |
| + componentWillMount() { | |
| + const { messages, text } = this.props; | |
| + this.setIsMounted(true); | |
| + this.initLocale(); | |
| + this.setMessages(messages || []); | |
| + this.setTextFromProp(text); | |
| + } | |
| + | |
| + componentWillUnmount() { | |
| + this.setIsMounted(false); | |
| + } | |
| + | |
| + componentWillReceiveProps(nextProps = {}) { | |
| + const { messages, text } = nextProps; | |
| + this.setMessages(messages || []); | |
| + this.setTextFromProp(text); | |
| + } | |
| + | |
| + initLocale() { | |
| + if ( | |
| + this.props.locale === null | |
| + || moment.locales().indexOf(this.props.locale || 'en') === -1 | |
| + ) { | |
| + this.setLocale('en'); | |
| + } else { | |
| + this.setLocale(this.props.locale || 'en'); | |
| + } | |
| + } | |
| + | |
| + setLocale(locale) { | |
| + this._locale = locale; | |
| + } | |
| + | |
| + setTextFromProp(textProp) { | |
| + // Text prop takes precedence over state. | |
| + if (textProp !== undefined && textProp !== this.state.text) { | |
| + this.setState({ text: textProp }); | |
| + } | |
| + } | |
| + | |
| + getTextFromProp(fallback) { | |
| + if (this.props.text === undefined) { | |
| + return fallback; | |
| + } | |
| + return this.props.text; | |
| + } | |
| + | |
| + setMessages(messages) { | |
| + this._messages = messages; | |
| + } | |
| + | |
| + getMessages() { | |
| + return this._messages; | |
| + } | |
| + | |
| + setMaxHeight(height) { | |
| + this._maxHeight = height; | |
| + } | |
| + | |
| + getMaxHeight() { | |
| + return this._maxHeight; | |
| + } | |
| + | |
| + setKeyboardHeight(height) { | |
| + this._keyboardHeight = height; | |
| + } | |
| + | |
| + getKeyboardHeight() { | |
| + if (Platform.OS === 'android' && !this.props.forceGetKeyboardHeight) { | |
| + // For android: on-screen keyboard resized main container and has own height. | |
| + // @see https://developer.android.com/training/keyboard-input/visibility.html | |
| + // So for calculate the messages container height ignore keyboard height. | |
| + return 0; | |
| + } | |
| + return this._keyboardHeight; | |
| + } | |
| + | |
| + setBottomOffset(value) { | |
| + this._bottomOffset = value; | |
| + } | |
| + | |
| + getBottomOffset() { | |
| + return this._bottomOffset; | |
| + } | |
| + | |
| + setIsFirstLayout(value) { | |
| + this._isFirstLayout = value; | |
| + } | |
| + | |
| + getIsFirstLayout() { | |
| + return this._isFirstLayout; | |
| + } | |
| + | |
| + setIsTypingDisabled(value) { | |
| + this.setState({ | |
| + typingDisabled: value, | |
| + }); | |
| + } | |
| + | |
| + getIsTypingDisabled() { | |
| + return this.state.typingDisabled; | |
| + } | |
| + | |
| + setIsMounted(value) { | |
| + this._isMounted = value; | |
| + } | |
| + | |
| + getIsMounted() { | |
| + return this._isMounted; | |
| + } | |
| + | |
| + getMinInputToolbarHeight() { | |
| + return this.props.renderAccessory | |
| + ? this.props.minInputToolbarHeight * 2 | |
| + : this.props.minInputToolbarHeight; | |
| + } | |
| + | |
| + calculateInputToolbarHeight(composerHeight) { | |
| + return ( | |
| + composerHeight | |
| + + (this.getMinInputToolbarHeight() - this.props.minComposerHeight) | |
| + ); | |
| + } | |
| + | |
| + /** | |
| + * Returns the height, based on current window size, without taking the keyboard into account. | |
| + */ | |
| + getBasicMessagesContainerHeight(composerHeight = this.state.composerHeight) { | |
| + return ( | |
| + this.getMaxHeight() - this.calculateInputToolbarHeight(composerHeight) | |
| + ); | |
| + } | |
| + | |
| + /** | |
| + * Returns the height, based on current window size, taking the keyboard into account. | |
| + */ | |
| + getMessagesContainerHeightWithKeyboard( | |
| + composerHeight = this.state.composerHeight, | |
| + ) { | |
| + return ( | |
| + this.getBasicMessagesContainerHeight(composerHeight) | |
| + - this.getKeyboardHeight() | |
| + + this.getBottomOffset() | |
| + ); | |
| + } | |
| + | |
| + prepareMessagesContainerHeight(value) { | |
| + if (this.props.isAnimated === true) { | |
| + return new Animated.Value(value); | |
| + } | |
| + return value; | |
| + } | |
| + | |
| + scrollToBottom(animated = true) { | |
| + if (this._messageContainerRef && this._messageContainerRef.current) { | |
| + this._messageContainerRef.current.scrollTo({ offset: 0, animated }); | |
| + } | |
| + } | |
| + | |
| + renderMessages() { | |
| + const AnimatedView = this.props.isAnimated === true ? Animated.View : View; | |
| + return ( | |
| + <AnimatedView | |
| + style={{ | |
| + flex: 1, | |
| + // height: this.state.messagesContainerHeight, | |
| + }} | |
| + > | |
| + <MessageContainer | |
| + {...this.props} | |
| + invertibleScrollViewProps={this.invertibleScrollViewProps} | |
| + messages={this.getMessages()} | |
| + ref={this._messageContainerRef} | |
| + /> | |
| + {this.renderChatFooter()} | |
| + </AnimatedView> | |
| + ); | |
| + } | |
| + | |
| + resetInputToolbar() { | |
| + if (this.textInput) { | |
| + this.textInput.clear(); | |
| + } | |
| + this.notifyInputTextReset(); | |
| + const newComposerHeight = this.props.minComposerHeight; | |
| + const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard( | |
| + newComposerHeight, | |
| + ); | |
| + this.setState({ | |
| + text: this.getTextFromProp(''), | |
| + composerHeight: newComposerHeight, | |
| + messagesContainerHeight: this.prepareMessagesContainerHeight( | |
| + newMessagesContainerHeight, | |
| + ), | |
| + }); | |
| + } | |
| + | |
| + focusTextInput() { | |
| + if (this.textInput) { | |
| + this.textInput.focus(); | |
| + } | |
| + } | |
| + | |
| + notifyInputTextReset() { | |
| + if (this.props.onInputTextChanged) { | |
| + this.props.onInputTextChanged(''); | |
| + } | |
| + } | |
| + | |
| + renderInputToolbar() { | |
| + const inputToolbarProps = { | |
| + ...this.props, | |
| + text: this.getTextFromProp(this.state.text), | |
| + composerHeight: Math.max( | |
| + this.props.minComposerHeight, | |
| + this.state.composerHeight, | |
| + ), | |
| + onSend: this.onSend, | |
| + onInputSizeChanged: this.onInputSizeChanged, | |
| + onTextChanged: this.onInputTextChanged, | |
| + textInputProps: { | |
| + ...this.props.textInputProps, | |
| + ref: textInput => (this.textInput = textInput), | |
| + maxLength: this.getIsTypingDisabled() ? 0 : this.props.maxInputLength, | |
| + }, | |
| + }; | |
| + if (this.props.renderInputToolbar) { | |
| + return this.props.renderInputToolbar(inputToolbarProps); | |
| + } | |
| + return <InputToolbar {...inputToolbarProps} />; | |
| + } | |
| + | |
| + renderChatFooter() { | |
| + if (this.props.renderChatFooter) { | |
| + return this.props.renderChatFooter(); | |
| + } | |
| + return null; | |
| + } | |
| + | |
| + renderLoading() { | |
| + if (this.props.renderLoading) { | |
| + return this.props.renderLoading(); | |
| + } | |
| + return null; | |
| + } | |
| + | |
| + render() { | |
| + // if (this.state.isInitialized === true) { | |
| + return ( | |
| + // <SafeAreaView style={styles.safeArea}> | |
| + <GiftedActionSheet ref={component => (this._actionSheetRef = component)}> | |
| + <View style={styles.container}> | |
| + {this.renderMessages()} | |
| + {this.renderInputToolbar()} | |
| + </View> | |
| + </GiftedActionSheet> | |
| + // </SafeAreaView> | |
| + ); | |
| + // } | |
| + // return ( | |
| + // <View style={styles.container} onLayout={this.onInitialLayoutViewLayout}> | |
| + // {this.renderLoading()} | |
| + // </View> | |
| + // ); | |
| + } | |
| } | |
| GiftedChat.childContextTypes = { | |
| - actionSheet: PropTypes.func, | |
| - getLocale: PropTypes.func, | |
| + actionSheet: PropTypes.func, | |
| + getLocale: PropTypes.func, | |
| }; | |
| GiftedChat.defaultProps = { | |
| - messages: [], | |
| - text: undefined, | |
| - placeholder: DEFAULT_PLACEHOLDER, | |
| - messageIdGenerator: () => uuid.v4(), | |
| - user: {}, | |
| - onSend: () => { }, | |
| - locale: null, | |
| - timeFormat: TIME_FORMAT, | |
| - dateFormat: DATE_FORMAT, | |
| - isAnimated: Platform.select({ | |
| - ios: true, | |
| - android: false, | |
| - }), | |
| - loadEarlier: false, | |
| - onLoadEarlier: () => { }, | |
| - isLoadingEarlier: false, | |
| - renderLoading: null, | |
| - renderLoadEarlier: null, | |
| - renderAvatar: undefined, | |
| - showUserAvatar: false, | |
| - onPressAvatar: null, | |
| - renderUsernameOnMessage: false, | |
| - renderAvatarOnTop: false, | |
| - renderBubble: null, | |
| - renderSystemMessage: null, | |
| - onLongPress: null, | |
| - renderMessage: null, | |
| - renderMessageText: null, | |
| - renderMessageImage: null, | |
| - imageProps: {}, | |
| - videoProps: {}, | |
| - lightboxProps: {}, | |
| - textInputProps: {}, | |
| - listViewProps: {}, | |
| - renderCustomView: null, | |
| - renderDay: null, | |
| - renderTime: null, | |
| - renderFooter: null, | |
| - renderChatFooter: null, | |
| - renderInputToolbar: null, | |
| - renderComposer: null, | |
| - renderActions: null, | |
| - renderSend: null, | |
| - renderAccessory: null, | |
| - onPressActionButton: null, | |
| - bottomOffset: 0, | |
| - minInputToolbarHeight: 44, | |
| - keyboardShouldPersistTaps: Platform.select({ | |
| - ios: 'never', | |
| - android: 'always', | |
| - }), | |
| - onInputTextChanged: null, | |
| - maxInputLength: null, | |
| - forceGetKeyboardHeight: false, | |
| - inverted: true, | |
| - extraData: null, | |
| - minComposerHeight: MIN_COMPOSER_HEIGHT, | |
| - maxComposerHeight: MAX_COMPOSER_HEIGHT, | |
| + messages: [], | |
| + text: undefined, | |
| + placeholder: DEFAULT_PLACEHOLDER, | |
| + messageIdGenerator: () => uuid.v4(), | |
| + user: {}, | |
| + onSend: () => {}, | |
| + locale: null, | |
| + timeFormat: TIME_FORMAT, | |
| + dateFormat: DATE_FORMAT, | |
| + isAnimated: Platform.select({ | |
| + ios: true, | |
| + android: false, | |
| + }), | |
| + loadEarlier: false, | |
| + onLoadEarlier: () => {}, | |
| + isLoadingEarlier: false, | |
| + renderLoading: null, | |
| + renderLoadEarlier: null, | |
| + renderAvatar: undefined, | |
| + showUserAvatar: false, | |
| + onPressAvatar: null, | |
| + renderUsernameOnMessage: false, | |
| + renderAvatarOnTop: false, | |
| + renderBubble: null, | |
| + renderSystemMessage: null, | |
| + onLongPress: null, | |
| + renderMessage: null, | |
| + renderMessageText: null, | |
| + renderMessageImage: null, | |
| + imageProps: {}, | |
| + videoProps: {}, | |
| + lightboxProps: {}, | |
| + textInputProps: {}, | |
| + listViewProps: {}, | |
| + renderCustomView: null, | |
| + renderDay: null, | |
| + renderTime: null, | |
| + renderFooter: null, | |
| + renderChatFooter: null, | |
| + renderInputToolbar: null, | |
| + renderComposer: null, | |
| + renderActions: null, | |
| + renderSend: null, | |
| + renderAccessory: null, | |
| + onPressActionButton: null, | |
| + bottomOffset: 0, | |
| + minInputToolbarHeight: 44, | |
| + keyboardShouldPersistTaps: Platform.select({ | |
| + ios: 'never', | |
| + android: 'always', | |
| + }), | |
| + onInputTextChanged: null, | |
| + maxInputLength: null, | |
| + forceGetKeyboardHeight: false, | |
| + inverted: true, | |
| + extraData: null, | |
| + minComposerHeight: MIN_COMPOSER_HEIGHT, | |
| + maxComposerHeight: MAX_COMPOSER_HEIGHT, | |
| }; | |
| GiftedChat.propTypes = { | |
| - messages: PropTypes.arrayOf(PropTypes.object), | |
| - text: PropTypes.string, | |
| - initialText: PropTypes.string, | |
| - placeholder: PropTypes.string, | |
| - messageIdGenerator: PropTypes.func, | |
| - user: PropTypes.object, | |
| - onSend: PropTypes.func, | |
| - locale: PropTypes.string, | |
| - timeFormat: PropTypes.string, | |
| - dateFormat: PropTypes.string, | |
| - isAnimated: PropTypes.bool, | |
| - loadEarlier: PropTypes.bool, | |
| - onLoadEarlier: PropTypes.func, | |
| - isLoadingEarlier: PropTypes.bool, | |
| - renderLoading: PropTypes.func, | |
| - renderLoadEarlier: PropTypes.func, | |
| - renderAvatar: PropTypes.func, | |
| - showUserAvatar: PropTypes.bool, | |
| - onPressAvatar: PropTypes.func, | |
| - renderUsernameOnMessage: PropTypes.bool, | |
| - renderAvatarOnTop: PropTypes.bool, | |
| - renderBubble: PropTypes.func, | |
| - renderSystemMessage: PropTypes.func, | |
| - onLongPress: PropTypes.func, | |
| - renderMessage: PropTypes.func, | |
| - renderMessageText: PropTypes.func, | |
| - renderMessageImage: PropTypes.func, | |
| - imageProps: PropTypes.object, | |
| - videoProps: PropTypes.object, | |
| - lightboxProps: PropTypes.object, | |
| - renderCustomView: PropTypes.func, | |
| - renderDay: PropTypes.func, | |
| - renderTime: PropTypes.func, | |
| - renderFooter: PropTypes.func, | |
| - renderChatFooter: PropTypes.func, | |
| - renderInputToolbar: PropTypes.func, | |
| - renderComposer: PropTypes.func, | |
| - renderActions: PropTypes.func, | |
| - renderSend: PropTypes.func, | |
| - renderAccessory: PropTypes.func, | |
| - onPressActionButton: PropTypes.func, | |
| - bottomOffset: PropTypes.number, | |
| - minInputToolbarHeight: PropTypes.number, | |
| - listViewProps: PropTypes.object, | |
| - keyboardShouldPersistTaps: PropTypes.oneOf(['always', 'never', 'handled']), | |
| - onInputTextChanged: PropTypes.func, | |
| - maxInputLength: PropTypes.number, | |
| - forceGetKeyboardHeight: PropTypes.bool, | |
| - inverted: PropTypes.bool, | |
| - textInputProps: PropTypes.object, | |
| - extraData: PropTypes.object, | |
| - minComposerHeight: PropTypes.number, | |
| - maxComposerHeight: PropTypes.number, | |
| - alignTop: PropTypes.bool, | |
| + messages: PropTypes.arrayOf(PropTypes.object), | |
| + text: PropTypes.string, | |
| + initialText: PropTypes.string, | |
| + placeholder: PropTypes.string, | |
| + messageIdGenerator: PropTypes.func, | |
| + user: PropTypes.object, | |
| + onSend: PropTypes.func, | |
| + locale: PropTypes.string, | |
| + timeFormat: PropTypes.string, | |
| + dateFormat: PropTypes.string, | |
| + isAnimated: PropTypes.bool, | |
| + loadEarlier: PropTypes.bool, | |
| + onLoadEarlier: PropTypes.func, | |
| + isLoadingEarlier: PropTypes.bool, | |
| + renderLoading: PropTypes.func, | |
| + renderLoadEarlier: PropTypes.func, | |
| + renderAvatar: PropTypes.func, | |
| + showUserAvatar: PropTypes.bool, | |
| + onPressAvatar: PropTypes.func, | |
| + renderUsernameOnMessage: PropTypes.bool, | |
| + renderAvatarOnTop: PropTypes.bool, | |
| + renderBubble: PropTypes.func, | |
| + renderSystemMessage: PropTypes.func, | |
| + onLongPress: PropTypes.func, | |
| + renderMessage: PropTypes.func, | |
| + renderMessageText: PropTypes.func, | |
| + renderMessageImage: PropTypes.func, | |
| + imageProps: PropTypes.object, | |
| + videoProps: PropTypes.object, | |
| + lightboxProps: PropTypes.object, | |
| + renderCustomView: PropTypes.func, | |
| + renderDay: PropTypes.func, | |
| + renderTime: PropTypes.func, | |
| + renderFooter: PropTypes.func, | |
| + renderChatFooter: PropTypes.func, | |
| + renderInputToolbar: PropTypes.func, | |
| + renderComposer: PropTypes.func, | |
| + renderActions: PropTypes.func, | |
| + renderSend: PropTypes.func, | |
| + renderAccessory: PropTypes.func, | |
| + onPressActionButton: PropTypes.func, | |
| + bottomOffset: PropTypes.number, | |
| + minInputToolbarHeight: PropTypes.number, | |
| + listViewProps: PropTypes.object, | |
| + keyboardShouldPersistTaps: PropTypes.oneOf(['always', 'never', 'handled']), | |
| + onInputTextChanged: PropTypes.func, | |
| + maxInputLength: PropTypes.number, | |
| + forceGetKeyboardHeight: PropTypes.bool, | |
| + inverted: PropTypes.bool, | |
| + textInputProps: PropTypes.object, | |
| + extraData: PropTypes.object, | |
| + minComposerHeight: PropTypes.number, | |
| + maxComposerHeight: PropTypes.number, | |
| + alignTop: PropTypes.bool, | |
| }; | |
| const styles = StyleSheet.create({ | |
| - container: { | |
| - flex: 1, | |
| - }, | |
| - safeArea: { | |
| - flex: 1, | |
| - }, | |
| + container: { | |
| + flex: 1, | |
| + }, | |
| + safeArea: { | |
| + flex: 1, | |
| + }, | |
| }); | |
| -export { GiftedChat, Actions, Avatar, Bubble, SystemMessage, MessageImage, MessageText, Composer, Day, InputToolbar, LoadEarlier, Message, MessageContainer, Send, Time, GiftedAvatar, utils, }; | |
| -//# sourceMappingURL=GiftedChat.js.map | |
| \ No newline at end of file | |
| +export { | |
| + GiftedChat, | |
| + Actions, | |
| + Avatar, | |
| + Bubble, | |
| + SystemMessage, | |
| + MessageImage, | |
| + MessageText, | |
| + Composer, | |
| + Day, | |
| + InputToolbar, | |
| + LoadEarlier, | |
| + Message, | |
| + MessageContainer, | |
| + Send, | |
| + Time, | |
| + GiftedAvatar, | |
| + utils, | |
| +}; | |
| +// # sourceMappingURL=GiftedChat.js.map | |
| diff --git a/node_modules/react-native-gifted-chat/lib/InputToolbar.js b/node_modules/react-native-gifted-chat/lib/InputToolbar.js | |
| index d3f75d3..36a6611 100644 | |
| --- a/node_modules/react-native-gifted-chat/lib/InputToolbar.js | |
| +++ b/node_modules/react-native-gifted-chat/lib/InputToolbar.js | |
| @@ -23,28 +23,28 @@ const styles = StyleSheet.create({ | |
| }, | |
| }); | |
| export default class InputToolbar extends React.Component { | |
| - constructor() { | |
| - super(...arguments); | |
| - this.state = { | |
| - position: 'absolute', | |
| - }; | |
| - this.keyboardWillShowListener = undefined; | |
| - this.keyboardWillHideListener = undefined; | |
| - this.keyboardWillShow = () => { | |
| - if (this.state.position !== 'relative') { | |
| - this.setState({ | |
| - position: 'relative', | |
| - }); | |
| - } | |
| - }; | |
| - this.keyboardWillHide = () => { | |
| - if (this.state.position !== 'absolute') { | |
| - this.setState({ | |
| - position: 'absolute', | |
| - }); | |
| - } | |
| - }; | |
| - } | |
| + // constructor() { | |
| + // super(...arguments); | |
| + // this.state = { | |
| + // position: 'absolute', | |
| + // }; | |
| + // this.keyboardWillShowListener = undefined; | |
| + // this.keyboardWillHideListener = undefined; | |
| + // this.keyboardWillShow = () => { | |
| + // if (this.state.position !== 'relative') { | |
| + // this.setState({ | |
| + // position: 'relative', | |
| + // }); | |
| + // } | |
| + // }; | |
| + // this.keyboardWillHide = () => { | |
| + // if (this.state.position !== 'absolute') { | |
| + // this.setState({ | |
| + // position: 'absolute', | |
| + // }); | |
| + // } | |
| + // }; | |
| + // } | |
| componentWillMount() { | |
| this.keyboardWillShowListener = Keyboard.addListener('keyboardWillShow', this.keyboardWillShow); | |
| this.keyboardWillHideListener = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide); | |
| @@ -91,7 +91,7 @@ export default class InputToolbar extends React.Component { | |
| return (<View style={[ | |
| styles.container, | |
| this.props.containerStyle, | |
| - { position: this.state.position }, | |
| + // { position: this.state.position }, | |
| ]}> | |
| <View style={[styles.primary, this.props.primaryStyle]}> | |
| {this.renderActions()} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment