This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community. Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it. https://www.freifunk-altdorf.de
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

169 lines
3.9 KiB

import React, { Component } from 'react';
import {
ActivityIndicator,
Button,
FlatList,
StyleSheet,
Text,
TextInput,
View,
} from 'react-native';
import KeyboardSpacer from '../../components/KeyboardSpacer';
import Backend from '../../lib/Backend';
export default class ChatScreen extends Component {
static navigationOptions = ({ navigation }) => ({
title: `Chat with ${navigation.state.params.name}`,
});
constructor(props) {
super(props);
this.state = {
messages: [],
myMessage: '',
isLoading: true,
};
}
async componentDidMount() {
let chat;
try {
chat = await Backend.fetchChat(this.props.navigation.state.params.name);
} catch (err) {
// Here we would handle the fact the request failed, e.g.
// set state to display "Messages could not be loaded".
// We should also check network connection first before making any
// network requests - maybe we're offline? See React Native's NetInfo
// module.
this.setState({
isLoading: false,
});
return;
}
this.setState((prevState) => ({
messages: chat.messages,
isLoading: false,
}));
}
onAddMessage = async () => {
// Optimistically update the UI
this.addMessageLocal();
// Send the request
try {
await Backend.sendMessage({
name: this.props.navigation.state.params.name,
// TODO Is reading state like this outside of setState OK?
// Can it contain a stale value?
message: this.state.myMessage,
});
} catch (err) {
// Here we would handle the request failure, e.g. call setState
// to display a visual hint showing the message could not be sent.
}
}
addMessageLocal = () => {
this.setState((prevState) => {
if (!prevState.myMessage) {
return prevState;
}
const messages = [
...prevState.messages, {
name: 'Me',
text: prevState.myMessage,
}
];
return {
messages: messages,
myMessage: '',
};
});
this.textInput.clear();
}
onMyMessageChange = (event) => {
this.setState({myMessage: event.nativeEvent.text});
}
renderItem = ({ item }) => (
<View style={styles.bubble}>
<Text style={styles.name}>{item.name}</Text>
<Text>{item.text}</Text>
</View>
)
render() {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.container}>
<FlatList
data={this.state.messages}
renderItem={this.renderItem}
keyExtractor={(item, index) => index}
style={styles.listView}
/>
<View style={styles.composer}>
<TextInput
ref={(textInput) => { this.textInput = textInput; }}
style={styles.textInput}
placeholder="Type a message..."
text={this.state.myMessage}
onSubmitEditing={this.onAddMessage}
onChange={this.onMyMessageChange}
/>
{this.state.myMessage !== '' && (
<Button
title="Send"
onPress={this.onAddMessage}
/>
)}
</View>
<KeyboardSpacer />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 8,
backgroundColor: 'white',
},
listView: {
flex: 1,
alignSelf: 'stretch',
},
bubble: {
alignSelf: 'flex-end',
backgroundColor: '#d6f3fc',
padding: 12,
borderRadius: 4,
marginBottom: 4,
},
name: {
fontWeight: 'bold',
},
composer: {
flexDirection: 'row',
alignItems: 'center',
height: 36,
},
textInput: {
flex: 1,
borderColor: '#ddd',
borderWidth: 1,
padding: 4,
height: 30,
fontSize: 13,
marginRight: 8,
}
});