Skip to content

Instantly share code, notes, and snippets.

@bogoslavskiy
Last active November 23, 2018 23:42
Show Gist options
  • Save bogoslavskiy/73edbdc494b164c003963a823713abaf to your computer and use it in GitHub Desktop.
Save bogoslavskiy/73edbdc494b164c003963a823713abaf to your computer and use it in GitHub Desktop.
import React from 'react';
import {
View,
Text,
StyleSheet,
TextInput,
Button,
FlatList,
Keyboard,
ActivityIndicator,
} from 'react-native';
import API from '../api';
import { Notifications } from 'expo';
import { Viewport } from '../utils';
import { KeyboardAccessoryView } from 'react-native-keyboard-accessory';
class Message extends React.PureComponent {
render() {
let isOwner = this.props.isOwner ? styles.messageOwner : {};
let isOwnerText = this.props.isOwner ? styles.messageTextOwner : {};
return (
<View style={[styles.message, isOwner]}>
<Text style={[styles.messageText, isOwnerText]}>{this.props.message}</Text>
</View>
);
}
}
export default class InputAccessoryViewExample extends React.PureComponent {
static navigationOptions = {
title: 'Messanger'
}
state = {
messages: [],
text: '',
notification: {},
loading: true,
};
componentDidMount() {
this.get();
this._notificationSubscription = Notifications.addListener(this._handleNotification);
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow);
}
componentWillUnmount() {
this.keyboardDidShowListener.remove();
}
_keyboardDidShow = () => this.isVisibleKeyboard = true;
_handleNotification = async (notification) => {
let newMessage = await API('test.create', {
text: notification.data.text,
from_id: 2,
peer_id: 1
});
this.setState({
notification: notification,
messages: [
newMessage,
...this.state.messages,
]
});
setTimeout(() => {
this.scroll.scrollToOffset({offset: 0});
}, 50)
};
get = async () => {
this.setState({ loading: true, opacityMessages: true });
let messages = await API('test.get', {});
this.setState({
messages: messages.reverse(),
loading: false
});
};
send = async () => {
if(this.state.text == '') {
return;
}
let newMessage = await API('test.create', {
text: this.state.text,
from_id: 1,
peer_id: 2
});
this.setState({
text: '',
messages: [
{...newMessage, owner: true},
...this.state.messages,
]
});
setTimeout(() => {
this.scroll.scrollToOffset({offset: 0});
}, 50)
};
dismissKeyboardWhenScrollUp = (ev) => {
let curPositionScroll = Math.max(ev.nativeEvent.contentOffset.y, 0);
if(!this.isVisibleKeyboard || this._momentumScroll) {
this._lastPositionScroll = curPositionScroll;
return;
}
if(this._lastPositionScroll < curPositionScroll) {
Keyboard.dismiss();
this.isVisibleKeyboard = false;
}
this._lastPositionScroll = curPositionScroll;
};
render() {
let { messages, loading } = this.state;
return (
<View style={styles.container}>
{loading &&
<View style={styles.loadingWrapper}>
<ActivityIndicator size="large"/>
</View>
}
<FlatList
contentContainerStyle={styles.flatList}
onScroll={this.dismissKeyboardWhenScrollUp}
onMomentumScrollBegin={() => {
this._momentumScroll = true;
}}
onMomentumScrollEnd={() => {
this._momentumScroll = false;
}}
ref={(r) => this.scroll = r}
inverted={true}
data={messages}
keyExtractor={(item) => item._id}
renderItem={({ item }) => (
<Message message={item.text} isOwner={item.from_id == 1} />
)}
/>
<KeyboardAccessoryView
style={styles.accssoryView}
alwaysVisible={true}
avoidKeyboard={true}
bumperHeight={30}
hideBorder={true}
>
<View style={[styles.textInputContainer]}>
<TextInput
multiline
style={styles.textInput}
onChangeText={(text) => {
this.setState({ text });
}}
value={this.state.text}
placeholder={'Type a message...'}
/>
<Button
onPress={this.send}
title="Send"
/>
</View>
</KeyboardAccessoryView>
</View>
);
}
}
const styles = StyleSheet.create({
loadingWrapper: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
container: {
flex: 1,
},
accssoryView: {
backgroundColor: '#fff'
},
textInputContainer: {
flexDirection: 'row',
paddingVertical: 10,
},
textInput: {
flex: 1,
paddingLeft: 10,
},
flatList: {
paddingVertical: 5
},
message: {
backgroundColor: 'grey',
borderRadius: 20,
margin: 10,
marginBottom: 5,
marginTop: 5,
alignSelf: 'flex-start'
},
messageOwner: {
backgroundColor: '#fff',
alignSelf: 'flex-end'
},
messageTextOwner: {
color: '#000',
},
messageText: {
color: '#fff',
padding: 15,
fontSize: 18
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment