Embed the Message Center
Airship’s SDK provides a simple interface for managing the Message Center within your application.
This guide covers creating custom Message Center implementations for React Native applications.
Override Default Display Behavior
To use a custom Message Center implementation instead of the default UI, disable auto-launch and add a listener to handle display events:
// Disable the default UI
Airship.messageCenter.setAutoLaunchDefaultMessageCenter(false);
// Add a listener to handle display events
Airship.addListener(EventType.DisplayMessageCenter, (event) => {
if (event.messageId) {
// Navigate to specific message
} else {
// Navigate to message center
}
});Custom Message Center Implementation
For complete control over Message Center placement and navigation, create a custom implementation using the Message Center components.
Using the MessageView
The MessageView component can be used to display individual messages. It renders both web and native (SceneA mobile app or web experience of one or more screens displayed with fully native UI components in real time, providing immediate, contextual responses to user behaviors. Scenes can be presented in full-screen, modal, or embedded format using the default swipe/click mode or as a story. Scene content can also be displayed in a Message Center message and contain survey questions.) message content automatically:
<MessageView
messageId="message-id"
onLoadStarted={this.startLoading}
onLoadFinished={this.finishLoading}
onLoadError={this.failedLoading}
style={{ flex: 1 }}
/>Example: Custom Message Center Inbox
Here’s an example of a complete Message Center inbox implementation:
import * as React from 'react';
import {
Text,
View,
FlatList,
TouchableHighlight,
RefreshControl,
} from 'react-native';
import Moment from 'moment';
import Airship, { Subscription, EventType, InboxMessage } from '@ua/react-native-airship';
interface MessageCenterScreenProps {
navigation: any;
}
function Item({ message, navigation }: { message: any; navigation: any }) {
return (
<TouchableHighlight
activeOpacity={0.6}
underlayColor="#DDDDDD"
onPress={() =>
navigation.navigate('MessageDetails', {
messageId: message.id,
title: message.title,
})
}
>
<View style={styles.item}>
<Text style={styles.itemTitle}>{message.title}</Text>
<Text style={styles.itemSubtitle}>
{Moment(message.sentDate).format('MM/DD/YYYY')}
</Text>
<View style={styles.itemSeparator} />
</View>
</TouchableHighlight>
);
}
export default class MessageCenterScreen extends React.Component<
MessageCenterScreenProps,
{
messages: InboxMessage[];
refreshing: boolean;
}
> {
private updateSubscription?: Subscription;
constructor(props: MessageCenterScreenProps) {
super(props);
this.state = {
messages: [],
refreshing: true,
};
this.refreshMessageCenter = this.refreshMessageCenter.bind(this);
this.handleUpdateMessageList = this.handleUpdateMessageList.bind(this);
}
componentDidMount(): void {
this.updateSubscription = Airship.addListener(
EventType.MessageCenterUpdated,
this.handleUpdateMessageList
);
this.handleUpdateMessageList();
}
componentWillUnmount(): void {
this.updateSubscription?.remove();
}
handleUpdateMessageList() {
Airship.messageCenter.getMessages().then((data) => {
this.setState({
messages: data,
refreshing: false,
});
});
}
refreshMessageCenter() {
Airship.messageCenter
.refreshMessages()
.then(() => {
this.setState({
refreshing: false,
});
})
.catch((error) => {
console.log('failed to refresh', error);
});
}
render() {
return (
<View style={styles.backgroundContainer}>
<FlatList
data={this.state.messages}
renderItem={({ item }) => (
<Item message={item} navigation={this.props.navigation} />
)}
keyExtractor={(item) => item.id}
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this.refreshMessageCenter}
/>
}
/>
</View>
);
}
}Example: Message Detail Screen
Here’s an example of a message detail screen:
import * as React from 'react';
import { View, ActivityIndicator, Alert } from 'react-native';
import { MessageView } from '@ua/react-native-airship';
interface MessageScreenProps {
navigation: any;
route: any;
}
export default class MessageScreen extends React.Component<
MessageScreenProps,
{
animating: boolean;
}
> {
constructor(props: MessageScreenProps) {
super(props);
this.state = {
animating: true,
};
this.startLoading = this.startLoading.bind(this);
this.finishLoading = this.finishLoading.bind(this);
this.failedLoading = this.failedLoading.bind(this);
}
startLoading() {
this.setState({ animating: true });
}
finishLoading() {
this.setState({ animating: false });
}
failedLoading() {
this.setState({ animating: false });
Alert.alert('Error', 'Unable to load message. Please try again later', [
{ text: 'OK', onPress: () => this.props.navigation.goBack() },
]);
}
render() {
const { params } = this.props.route;
const messageId = params ? params.messageId : '';
return (
<View style={styles.backgroundContainer}>
<MessageView
messageId={messageId}
onLoadStarted={this.startLoading}
onLoadFinished={this.finishLoading}
onLoadError={this.failedLoading}
style={{ flex: 1 }}
/>
{this.state.animating && (
<View style={styles.loadingIndicator}>
<ActivityIndicator size="large" animating={this.state.animating} />
</View>
)}
</View>
);
}
}For more examples, see our sample app.