<commit_before>import React, {Component, PropTypes} from 'react';

import ReactNative, {
    View,
    ListView,
    UIManager
} from 'react-native';

import InvertibleScrollView from 'react-native-invertible-scroll-view';

import LoadEarlier from './LoadEarlier';
import Message from './Message';

import md5 from 'md5';

export default class MessageContainer extends Component {
    constructor(props) {
        super(props);

        const dataSource = new ListView.DataSource({
            rowHasChanged: (r1, r2) => r1.hash !== r2.hash
        });
        const messages = props.messages.map(message => ({
            ...message,
            hash: md5(JSON.stringify(message))
        }));

        this.state = {
            containerHeight: 0,
            listViewPaddingTop: 0,
            dataSource: dataSource.cloneWithRows(messages)
        };
        this.renderFooter = this.renderFooter.bind(this);
    }

    componentWillReceiveProps(nextProps) {
        const messages = nextProps.messages.map(message => ({
            ...message,
            hash: md5(JSON.stringify(message))
        }));
        this.setState({
            dataSource: this.state.dataSource.cloneWithRows(messages)
        });
    }

    renderFooter() {
        if (this.props.renderFooter) {
            const footerProps = {
                ...this.props,
            };
            return this.props.renderFooter(footerProps);
        }
        return null;
    }

    renderLoadEarlier() {
        if (this.props.loadEarlier === true) {
            const loadEarlierProps = {
                ...this.props,
            };
            if (this.props.renderLoadEarlier) {
                return this.props.renderLoadEarlier(loadEarlierProps);
            }
            return (
                <LoadEarlier {...loadEarlierProps}/>
            );
        }
        return null;
    }

    scrollTo(options) {
        this._invertibleScrollViewRef.scrollTo(options);
    }

    renderRow(message, sectionId, rowId) {
        if (!message._id) {
            console.warn('GiftedChat: `_id` is missing for message', JSON.stringify(message));
        }
        if (!message.user) {
            console.warn('GiftedChat: `user` is missing for message', JSON.stringify(message));
            message.user = {};
        }

        const index = Number(rowId);

        const messageProps = {
            ...this.props,
            key: message._id,
            currentMessage: message,
            previousMessage: this.props.messages[index + 1] || {},
            nextMessage: this.props.messages[index - 1] || {},
            position: message.user._id === this.props.user._id ? 'right' : 'left',
        };

        if (this.props.renderMessage) {
            return this.props.renderMessage(messageProps);
        }
        return <Message {...messageProps}/>;
    }

    renderScrollComponent(props) {
        const invertibleScrollViewProps = this.props.invertibleScrollViewProps;
        return (
            <InvertibleScrollView
                {...invertibleScrollViewProps}
                contentContainerStyle={{ marginTop: this.state.listViewPaddingTop }}
                ref={component => this._invertibleScrollViewRef = component}
            />
        );
    }

    updateListViewPaddingTop(contentWidth, contentHeight) {
        this.setState({
            listViewPaddingTop: Math.max(this.state.containerHeight - contentHeight, 0)
        });
    }

    onContainerLayout(e) {
        const layout = e.nativeEvent.layout;
        this.setState({
            containerHeight: layout.height
        });
    }

    render() {
        return (
            <View ref='container' style={{flex:1}} onLayout={this.onContainerLayout.bind(this)}>
                <ListView
                    renderScrollComponent={this.renderScrollComponent.bind(this)}
                    enableEmptySections={true}
                    dataSource={this.state.dataSource}
                    renderRow={this.renderRow.bind(this)}
                    renderFooter={this.renderLoadEarlier.bind(this)}
                    renderHeader={this.renderFooter}
                    automaticallyAdjustContentInsets={false}
                    onContentSizeChange={this.updateListViewPaddingTop.bind(this)}
                />
            </View>
        );
    }
}

MessageContainer.defaultProps = {
    messages: [],
    user: {},
    renderFooter: null,
    renderMessage: null,
    onLoadEarlier: () => {
    },
};<commit_msg>* Move md5 hash to message instead of all messages * MessageContainer now renders a ListView with InvertibleListView as its scrollContainer<commit_after>import React, {Component, PropTypes} from 'react';

import ReactNative, {
    View,
    ListView,
    UIManager
} from 'react-native';

import InvertibleScrollView from 'react-native-invertible-scroll-view';

import LoadEarlier from './LoadEarlier';
import Message from './Message';

import md5 from 'md5';

export default class MessageContainer extends Component {
    constructor(props) {
        super(props);

        const dataSource = new ListView.DataSource({
            rowHasChanged: (r1, r2) => r1.hash !== r2.hash
        });
        const messages = props.messages.map(message => ({
            ...message,
            hash: md5(JSON.stringify(message))
        }));

        this.state = {
            containerHeight: 0,
            listViewPaddingTop: 0,
            dataSource: dataSource.cloneWithRows(messages)
        };
    }

    componentWillReceiveProps(nextProps) {
        const messages = nextProps.messages.map(message => ({
            ...message,
            hash: md5(JSON.stringify(message))
        }));
        this.setState({
            dataSource: this.state.dataSource.cloneWithRows(messages)
        });
    }

    renderFooter() {
        if (this.props.renderFooter) {
            const footerProps = {
                ...this.props,
            };
            return this.props.renderFooter(footerProps);
        }
        return null;
    }

    renderLoadEarlier() {
        if (this.props.loadEarlier === true) {
            const loadEarlierProps = {
                ...this.props,
            };
            if (this.props.renderLoadEarlier) {
                return this.props.renderLoadEarlier(loadEarlierProps);
            }
            return (
                <LoadEarlier {...loadEarlierProps}/>
            );
        }
        return null;
    }

    scrollTo(options) {
        this._invertibleScrollViewRef.scrollTo(options);
    }

    renderRow(message, sectionId, rowId) {
        if (!message._id) {
            console.warn('GiftedChat: `_id` is missing for message', JSON.stringify(message));
        }
        if (!message.user) {
            console.warn('GiftedChat: `user` is missing for message', JSON.stringify(message));
            message.user = {};
        }

        const index = Number(rowId);

        const messageProps = {
            ...this.props,
            key: message._id,
            currentMessage: message,
            previousMessage: this.props.messages[index + 1] || {},
            nextMessage: this.props.messages[index - 1] || {},
            position: message.user._id === this.props.user._id ? 'right' : 'left',
        };

        if (this.props.renderMessage) {
            return this.props.renderMessage(messageProps);
        }
        return <Message {...messageProps}/>;
    }

    renderScrollComponent(props) {
        const invertibleScrollViewProps = this.props.invertibleScrollViewProps;
        return (
            <InvertibleScrollView
                {...invertibleScrollViewProps}
                contentContainerStyle={{ marginTop: this.state.listViewPaddingTop }}
                ref={component => this._invertibleScrollViewRef = component}
            />
        );
    }

    updateListViewPaddingTop(contentWidth, contentHeight) {
        this.setState({
            listViewPaddingTop: Math.max(this.state.containerHeight - contentHeight, 0)
        });
    }

    onContainerLayout(e) {
        const layout = e.nativeEvent.layout;
        this.setState({
            containerHeight: layout.height
        });
    }

    render() {
        return (
            <View ref='container' style={{flex:1}} onLayout={this.onContainerLayout.bind(this)}>
                <ListView
                    renderScrollComponent={this.renderScrollComponent.bind(this)}
                    enableEmptySections={true}
                    dataSource={this.state.dataSource}
                    renderRow={this.renderRow.bind(this)}
                    renderFooter={this.renderLoadEarlier.bind(this)}
                    renderHeader={this.renderFooter.bind(this)}
                    automaticallyAdjustContentInsets={false}
                    onContentSizeChange={this.updateListViewPaddingTop.bind(this)}
                />
            </View>
        );
    }
}

MessageContainer.defaultProps = {
    messages: [],
    user: {},
    renderFooter: null,
    renderMessage: null,
    onLoadEarlier: () => {
    },
};
{'fraction_non_alphanumeric': 0.11393939393939394, 'fraction_numerical': 0.0031955922865013774, 'mean_word_length': 1.8648989898989898, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3359592', 'n_tokens_mistral': 2438, 'n_tokens_neox': 2345, 'n_words': 417}