Merge pull request #127 from esteemapp/notification-2

Notification 2
This commit is contained in:
Feruz M 2018-11-30 10:46:34 +02:00 committed by GitHub
commit 4d90e42fea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 269 additions and 102 deletions

View File

@ -1,3 +1,4 @@
BACKEND_URL=https://myapi.com
SEARCH_API_URL=https://search.com
SEARCH_API_TOKEN=abcde
ACTIVITY_WEBSOCKET_URL=ws://host.com/path

71
package-lock.json generated
View File

@ -10262,8 +10262,7 @@
"react-is": {
"version": "16.6.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.0.tgz",
"integrity": "sha512-q8U7k0Fi7oxF1HvQgyBjPwDXeMplEsArnKt2iYhuIF86+GBbgLHdAmokL3XUFjTd7Q363OSNG55FOGUdONVn1g==",
"dev": true
"integrity": "sha512-q8U7k0Fi7oxF1HvQgyBjPwDXeMplEsArnKt2iYhuIF86+GBbgLHdAmokL3XUFjTd7Q363OSNG55FOGUdONVn1g=="
},
"react-lifecycles-compat": {
"version": "3.0.4",
@ -10565,9 +10564,9 @@
}
},
"react-native-screens": {
"version": "1.0.0-alpha.14",
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-1.0.0-alpha.14.tgz",
"integrity": "sha512-SXVl5dnN5ZgV7jF2NdqScp91qW3QOZipBPp8f0CpAtb/ucEQkteiQnTGb4BNS5OvpMVi1UNw4BXWhUsKRPqzPw=="
"version": "1.0.0-alpha.16",
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-1.0.0-alpha.16.tgz",
"integrity": "sha512-t+/aq5jQa+Is6afiQHa1P+2UPnwPGY9NT0pSqNr2zQ5llCn8TcPq6GN8xDMuEc08g+y/9R5zWo32hlVStwWn1A=="
},
"react-native-slider": {
"version": "0.11.0",
@ -10601,47 +10600,29 @@
"integrity": "sha512-CcX61kqFyO41WAmqARr/1A7YgTkd1GoQGJl0LYrzl+4CL5uw2CAu68T+1DPapt7RdgvSMLZIPlNvj4TzdJY/hw=="
},
"react-navigation": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-2.17.0.tgz",
"integrity": "sha512-OT3V5ZGA+VOFydjJg5JAo/sh94stWoyEYXOVdAz98Rw4UW3BATUG6Y/4ROMbBSlYl2PvGfc9Q1+RHEhy5Xjp8A==",
"version": "2.18.3",
"resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-2.18.3.tgz",
"integrity": "sha512-/5KGMG1Oj5LN/x/7AKF0MWrpX9Qe29307RxEsMCiRT/A4jCYT0DPY99Bl7ZAGtROxExEy3rwTfTrtvpIT+CU7A==",
"requires": {
"clamp": "1.0.1",
"create-react-context": "0.2.2",
"hoist-non-react-statics": "2.5.5",
"path-to-regexp": "1.7.0",
"query-string": "6.2.0",
"react-is": "16.6.0",
"react-lifecycles-compat": "3.0.4",
"react-native-safe-area-view": "0.11.0",
"react-native-screens": "1.0.0-alpha.14",
"react-native-screens": "1.0.0-alpha.16",
"react-navigation-deprecated-tab-navigator": "1.3.0",
"react-navigation-drawer": "0.5.0",
"react-navigation-stack": "0.7.0",
"react-navigation-tabs": "0.8.2"
"react-navigation-tabs": "0.8.4"
},
"dependencies": {
"hoist-non-react-statics": {
"version": "2.5.5",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
},
"react-native-tab-view": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-1.3.1.tgz",
"integrity": "sha512-QNt6VkEW8SP1UJ7yjD5P4bOTWwHQfoIMD5CqnA06pcubdNwHR1NmjiNZsVnIvp5wAEVbW6yTHjLXOh1fzab4xg==",
"requires": {
"prop-types": "15.6.2"
}
},
"react-navigation-tabs": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/react-navigation-tabs/-/react-navigation-tabs-0.8.2.tgz",
"integrity": "sha512-q2xfY79ERj4XJek3rceveifUny3Qcg7y6bNlN6wQg6c7D/pMFOGZsSALGenF7CuNDhYyEkijlnGTHl1laZgbDw==",
"requires": {
"hoist-non-react-statics": "2.5.5",
"prop-types": "15.6.2",
"react-lifecycles-compat": "3.0.4",
"react-native-tab-view": "1.3.1"
}
}
}
},
@ -10662,9 +10643,9 @@
}
},
"react-navigation-redux-helpers": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/react-navigation-redux-helpers/-/react-navigation-redux-helpers-2.0.6.tgz",
"integrity": "sha512-/goEObr1Det7PDkw75o8Rr1ItzlWyMlwUBGYQMtM6kRAVa3i/E77VqjfrRrZ1a6+KAnnRNUSkS8AS4K7s41/Ng==",
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/react-navigation-redux-helpers/-/react-navigation-redux-helpers-2.0.8.tgz",
"integrity": "sha512-gCxHOGWNbRtt6Se93uuIE3cKqmqln73wlMeyD02aE1vs0cl9fn7BUKXX+UESrBSUOqadeoS1I7AH4arxZAARTQ==",
"requires": {
"invariant": "2.2.4"
}
@ -10674,6 +10655,32 @@
"resolved": "https://registry.npmjs.org/react-navigation-stack/-/react-navigation-stack-0.7.0.tgz",
"integrity": "sha512-3Tbb/SsustBrM9R/qaI6XuOfyqYMVbwkeHFC8NbU890vB0aKZvjAtioWLZ18e/4LgbiOCmoTdp37z3gkGDyNDQ=="
},
"react-navigation-tabs": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/react-navigation-tabs/-/react-navigation-tabs-0.8.4.tgz",
"integrity": "sha512-CbS3xIVJVtpu+AYslv0PMLmjddJFVtU3XAhSJ9XnMrKLUJNmnQdW/L0w/Gp5qcBEF9h6bgsY3CoTtp7I6bqyOQ==",
"requires": {
"hoist-non-react-statics": "2.5.5",
"prop-types": "15.6.2",
"react-lifecycles-compat": "3.0.4",
"react-native-tab-view": "1.3.1"
},
"dependencies": {
"hoist-non-react-statics": {
"version": "2.5.5",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
},
"react-native-tab-view": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-1.3.1.tgz",
"integrity": "sha512-QNt6VkEW8SP1UJ7yjD5P4bOTWwHQfoIMD5CqnA06pcubdNwHR1NmjiNZsVnIvp5wAEVbW6yTHjLXOh1fzab4xg==",
"requires": {
"prop-types": "15.6.2"
}
}
}
},
"react-proxy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-1.1.8.tgz",

View File

@ -51,8 +51,8 @@
"react-native-slider": "^0.11.0",
"react-native-vector-icons": "^6.0.2",
"react-native-view-overflow": "0.0.3",
"react-navigation": "^2.17.0",
"react-navigation-redux-helpers": "^2.0.6",
"react-navigation": "^2.18.3",
"react-navigation-redux-helpers": "^2.0.8",
"react-redux": "^5.0.7",
"realm": "2.16.0",
"redux": "^4.0.0",

View File

@ -1,8 +1,11 @@
import React, { Component } from 'react';
import { TouchableWithoutFeedback } from 'react-native';
import { connect } from 'react-redux';
import ViewOverflow from 'react-native-view-overflow';
// Services and Actions
import { updateActiveBottomTab } from '../../../redux/actions/uiAction';
// Constants
// Components
@ -22,6 +25,16 @@ class BottomTabBarView extends Component {
}
// Component Life Cycles
componentWillUpdate(nextProps) {
const {
navigation: {
state: { index, routes },
},
dispatch,
} = nextProps;
dispatch(updateActiveBottomTab(routes[index].routeName));
}
// Component Functions
@ -61,4 +74,4 @@ class BottomTabBarView extends Component {
}
}
export default BottomTabBarView;
export default connect()(BottomTabBarView);

View File

@ -48,7 +48,7 @@ class NotificationView extends Component {
};
render() {
const { notifications, intl } = this.props;
const { notifications, intl, navigateToNotificationRoute } = this.props;
const { filters } = this.state;
const today = [];
const yesterday = [];
@ -91,7 +91,12 @@ class NotificationView extends Component {
/>
<FlatList
data={today}
renderItem={({ item }) => <NotificationLine notification={item} />}
renderItem={({ item }) => (
<NotificationLine
notification={item}
handleOnPressNotification={navigateToNotificationRoute}
/>
)}
keyExtractor={item => item.id}
/>
</Fragment>
@ -107,7 +112,12 @@ class NotificationView extends Component {
/>
<FlatList
data={yesterday}
renderItem={({ item }) => <NotificationLine notification={item} />}
renderItem={({ item }) => (
<NotificationLine
notification={item}
handleOnPressNotification={navigateToNotificationRoute}
/>
)}
keyExtractor={item => item.id}
/>
</Fragment>
@ -123,7 +133,12 @@ class NotificationView extends Component {
/>
<FlatList
data={thisWeek}
renderItem={({ item }) => <NotificationLine notification={item} />}
renderItem={({ item }) => (
<NotificationLine
notification={item}
handleOnPressNotification={navigateToNotificationRoute}
/>
)}
keyExtractor={item => item.id}
/>
</Fragment>
@ -139,7 +154,12 @@ class NotificationView extends Component {
/>
<FlatList
data={thisMonth}
renderItem={({ item }) => <NotificationLine notification={item} />}
renderItem={({ item }) => (
<NotificationLine
notification={item}
handleOnPressNotification={navigateToNotificationRoute}
/>
)}
keyExtractor={item => item.id}
/>
</Fragment>
@ -155,7 +175,12 @@ class NotificationView extends Component {
/>
<FlatList
data={olderThenMonth}
renderItem={({ item }) => <NotificationLine notification={item} />}
renderItem={({ item }) => (
<NotificationLine
notification={item}
handleOnPressNotification={navigateToNotificationRoute}
/>
)}
keyExtractor={item => item.id}
/>
</Fragment>

View File

@ -1,5 +1,7 @@
import React, { Component } from 'react';
import { View, Text, Image } from 'react-native';
import {
View, Text, Image, TouchableHighlight,
} from 'react-native';
import { injectIntl } from 'react-intl';
// Constants
@ -29,45 +31,48 @@ class NotificationLineView extends Component {
const {
notification,
intl: { formatMessage },
handleOnPressNotification,
} = this.props;
return (
<View
key={Math.random()}
style={[styles.notificationWrapper, !notification.read && styles.isNewNotification]}
>
<Image
style={[styles.avatar, !notification.avatar && styles.hasNoAvatar]}
source={{
uri: `https://steemitimages.com/u/${notification.source}/avatar/small`,
}}
/>
<View style={styles.body}>
<View style={styles.titleWrapper}>
<Text style={styles.name}>
{notification.source}
{' '}
</Text>
<Text style={styles.title}>
{formatMessage({
id: `notification.${notification.type}`,
})}
</Text>
<TouchableHighlight onPress={() => handleOnPressNotification(notification)}>
<View
key={Math.random()}
style={[styles.notificationWrapper, !notification.read && styles.isNewNotification]}
>
<Image
style={[styles.avatar, !notification.avatar && styles.hasNoAvatar]}
source={{
uri: `https://steemitimages.com/u/${notification.source}/avatar/small`,
}}
/>
<View style={styles.body}>
<View style={styles.titleWrapper}>
<Text style={styles.name}>
{notification.source}
{' '}
</Text>
<Text style={styles.title}>
{formatMessage({
id: `notification.${notification.type}`,
})}
</Text>
</View>
{notification.description && (
<Text numberOfLines={1} style={styles.description}>
{notification.description}
</Text>
)}
</View>
{notification.description && (
<Text numberOfLines={1} style={styles.description}>
{notification.description}
</Text>
{notification.image && (
<Image
style={styles.image}
source={{ uri: notification.image }}
defaultSource={require('../../../assets/no_image.png')}
/>
)}
</View>
{notification.image && (
<Image
style={styles.image}
source={{ uri: notification.image }}
defaultSource={require('../../../assets/no_image.png')}
/>
)}
</View>
</TouchableHighlight>
);
}
}

View File

@ -1,5 +1,6 @@
const SCREEN_SUFFIX = 'Screen';
const DRAWER_SUFFIX = 'Drawer';
const TABBAR_SUFFIX = 'Tabbar';
export default {
SCREENS: {
@ -18,4 +19,11 @@ export default {
DRAWER: {
MAIN: `Main${DRAWER_SUFFIX}`,
},
TABBAR: {
HOME: `Home${TABBAR_SUFFIX}`,
NOTIFICATION: `Notification${TABBAR_SUFFIX}`,
POSTBUTTON: `PostButton${TABBAR_SUFFIX}`,
MESSAGES: `Messages${TABBAR_SUFFIX}`,
PROFILE: `Profile${TABBAR_SUFFIX}`,
},
};

View File

@ -1,18 +1,20 @@
import React from 'react';
import { createBottomTabNavigator } from 'react-navigation';
import { Icon } from '../components/icon';
import { IconContainer } from '../components/icon';
// Constants
import ROUTES from '../constants/routeNames';
// Components
import { Icon, IconContainer } from '../components/icon';
import {
Home, Notification, Profile, RootComponent, Messages,
} from '../screens';
import { PostButton } from '../components/postButton';
import { BottomTabBar } from '../components/bottomTabBar';
// import style from './baseNavigatorStyles';
const BaseNavigator = createBottomTabNavigator(
{
Home: {
[ROUTES.TABBAR.HOME]: {
screen: RootComponent()(Home),
navigationOptions: () => ({
tabBarIcon: ({ tintColor }) => (
@ -26,7 +28,7 @@ const BaseNavigator = createBottomTabNavigator(
),
}),
},
Notification: {
[ROUTES.TABBAR.NOTIFICATION]: {
screen: RootComponent()(Notification),
navigationOptions: () => ({
tabBarIcon: ({ tintColor }) => (
@ -42,13 +44,13 @@ const BaseNavigator = createBottomTabNavigator(
),
}),
},
PostButton: {
[ROUTES.TABBAR.POSTBUTTON]: {
screen: () => null,
navigationOptions: () => ({
tabBarIcon: <PostButton />,
}),
},
Messages: {
[ROUTES.TABBAR.MESSAGES]: {
screen: RootComponent()(Messages),
navigationOptions: () => ({
tabBarIcon: ({ tintColor }) => (
@ -62,7 +64,7 @@ const BaseNavigator = createBottomTabNavigator(
),
}),
},
Profile: {
[ROUTES.TABBAR.PROFILE]: {
screen: RootComponent()(Profile),
navigationOptions: () => ({
tabBarIcon: ({ tintColor }) => (
@ -89,14 +91,4 @@ const BaseNavigator = createBottomTabNavigator(
},
);
const defaultGetStateForAction = BaseNavigator.router.getStateForAction;
// BaseNavigator.router.getStateForAction = (action, state) => {
// if (action.type === NavigationActions.NAVIGATE && action.routeName === 'Adding') {
// return null;
// }
//
// return defaultGetStateForAction(action, state);
// };
export { BaseNavigator };

View File

@ -88,7 +88,18 @@ export const getUnreadActivityCount = data => new Promise((resolve, reject) => {
api
.get(`/activities/${data.user}/unread-count`)
.then((res) => {
resolve(res.data?res.data.count:0);
resolve(res.data ? res.data.count : 0);
})
.catch((error) => {
reject(error);
});
});
export const markActivityAsRead = (user, id = null) => new Promise((resolve, reject) => {
api
.put(`/activities/${user}`, { id })
.then((res) => {
resolve(res.data);
})
.catch((error) => {
reject(error);

View File

@ -4,6 +4,7 @@ import {
FETCHING_ACCOUNT,
ADD_OTHER_ACCOUNT,
UPDATE_CURRENT_ACCOUNT,
UPDATE_UNREAD_ACTIVITY_COUNT,
} from '../constants/constants';
export const fetchAccountFromSteem = (username, password) => (dispatch) => {
@ -31,3 +32,8 @@ export const failedAccount = data => ({
type: FETCH_ACCOUNT_FAIL,
payload: data,
});
export const updateUnreadActivityCount = data => ({
type: UPDATE_UNREAD_ACTIVITY_COUNT,
payload: data,
});

View File

@ -0,0 +1,6 @@
import { UPDATE_ACTIVE_BOTTOM_TAB } from '../constants/constants';
export const updateActiveBottomTab = payload => ({
payload,
type: UPDATE_ACTIVE_BOTTOM_TAB,
});

View File

@ -12,6 +12,7 @@ export const ADD_OTHER_ACCOUNT = 'ADD_OTHER_ACCOUNT';
export const UPDATE_CURRENT_ACCOUNT = 'UPDATE_CURRENT_ACCOUNT';
export const FETCHING_ACCOUNT = 'FETCHING_ACCOUNT';
export const FETCH_ACCOUNT_FAIL = 'FETCH_ACCOUNT_FAIL';
export const UPDATE_UNREAD_ACTIVITY_COUNT = 'UPDATE_UNREAD_ACTIVITY_COUNT';
export const IS_LOGGED_IN = 'IS_LOGGED_IN';
export const OPEN_PIN_CODE_MODAL = 'OPEN_PIN_CODE_MODAL';
@ -24,3 +25,4 @@ export const SET_CURRENCY = 'SET_CURRENCY';
export const IS_NOTIFICATION_OPEN = 'IS_NOTIFICATION_OPEN';
export const IS_DARK_THEME = 'IS_DARK_THEME';
export const UPDATE_ACTIVE_BOTTOM_TAB = 'UPDATE_ACTIVE_BOTTOM_TAB';

View File

@ -3,6 +3,7 @@ import {
FETCHING_ACCOUNT,
ADD_OTHER_ACCOUNT,
UPDATE_CURRENT_ACCOUNT,
UPDATE_UNREAD_ACTIVITY_COUNT,
} from '../constants/constants';
const initialState = {
@ -47,6 +48,17 @@ export default function (state = initialState, action) {
hasError: false,
errorMessage: null,
};
case UPDATE_UNREAD_ACTIVITY_COUNT:
return {
...state,
currentAccount: {
...state.currentAccount,
unread_activity_count: action.payload,
},
isFetching: false,
hasError: false,
errorMessage: null,
};
default:
return state;
}

View File

@ -2,9 +2,11 @@ import { combineReducers } from 'redux';
import accountReducer from './accountReducer';
import applicationReducer from './applicationReducer';
import nav from './nav';
import ui from './uiReducer';
export default combineReducers({
account: accountReducer,
application: applicationReducer,
nav,
ui,
});

View File

@ -0,0 +1,17 @@
import { UPDATE_ACTIVE_BOTTOM_TAB } from '../constants/constants';
const initialState = {
activeBottomTab: 'Home',
};
export default function (state = initialState, action) {
switch (action.type) {
case UPDATE_ACTIVE_BOTTOM_TAB:
return {
...state,
activeBottomTab: action.payload,
};
default:
return state;
}
}

View File

@ -1,6 +1,8 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { addLocaleData } from 'react-intl';
import Config from 'react-native-config';
// Constants
import en from 'react-intl/locale-data/en';
import tr from 'react-intl/locale-data/tr';
@ -9,7 +11,11 @@ import { getUserData, getAuthStatus, getSettings } from '../../../realm/realm';
import { getUser } from '../../../providers/steem/dsteem';
// Actions
import { addOtherAccount, updateCurrentAccount } from '../../../redux/actions/accountAction';
import {
addOtherAccount,
updateCurrentAccount,
updateUnreadActivityCount,
} from '../../../redux/actions/accountAction';
import {
activeApplication,
login,
@ -77,6 +83,7 @@ class ApplicationContainer extends Component {
if (__DEV__ === false) {
dispatch(openPinCodeModal());
}
this._connectNotificationServer(accountData.name);
})
.catch((err) => {
alert(err);
@ -103,6 +110,17 @@ class ApplicationContainer extends Component {
});
};
_connectNotificationServer = (username) => {
const { dispatch, unreadActivityCount } = this.props;
const ws = new WebSocket(`${Config.ACTIVITY_WEBSOCKET_URL}?user=${username}`);
ws.onmessage = (e) => {
// a message was received
console.log('e.data :', e.data);
dispatch(updateUnreadActivityCount(unreadActivityCount + 1));
};
};
render() {
const { selectedLanguage } = this.props;
const { isRenderRequire } = this.state;
@ -122,6 +140,7 @@ class ApplicationContainer extends Component {
const mapStateToProps = state => ({
isDarkTheme: state.application.isDarkTheme,
selectedLanguage: state.application.language,
unreadActivityCount: state.account.currentAccount.unread_activity_count,
});
export default connect(mapStateToProps)(ApplicationContainer);

View File

@ -2,7 +2,11 @@ import React, { Component } from 'react';
import { connect } from 'react-redux';
// Actions and Services
import { getActivities } from '../../../providers/esteem/esteem';
import { getActivities, markActivityAsRead } from '../../../providers/esteem/esteem';
import { updateUnreadActivityCount } from '../../../redux/actions/accountAction';
// Constants
import ROUTES from '../../../constants/routeNames';
// Components
import { NotificationScreen } from '../index';
@ -15,8 +19,10 @@ class NotificationContainer extends Component {
};
}
componentWillMount() {
this._getAvtivities();
componentWillReceiveProps(nextProps) {
if (nextProps.activeBottomTab === ROUTES.TABBAR.NOTIFICATION) {
this._getAvtivities();
}
}
_getAvtivities = (type = null) => {
@ -27,6 +33,33 @@ class NotificationContainer extends Component {
});
};
_navigateToNotificationRoute = (data) => {
const { navigation, username, dispatch } = this.props;
markActivityAsRead(username, data.id).then((result) => {
dispatch(updateUnreadActivityCount(result.unread));
});
if (data.permlink) {
navigation.navigate({
routeName: ROUTES.SCREENS.POST,
params: {
author: data.author,
permlink: data.permlink,
},
key: data.permlink,
});
} else {
navigation.navigate({
routeName: ROUTES.SCREENS.PROFILE,
params: {
username: data.follower,
},
key: data.follower,
});
}
};
render() {
const { notifications } = this.state;
@ -34,6 +67,7 @@ class NotificationContainer extends Component {
<NotificationScreen
getActivities={this._getAvtivities}
notifications={notifications}
navigateToNotificationRoute={this._navigateToNotificationRoute}
{...this.props}
/>
);
@ -42,6 +76,7 @@ class NotificationContainer extends Component {
const mapStateToProps = state => ({
username: state.account.currentAccount.name,
activeBottomTab: state.ui.activeBottomTab,
});
export default connect(mapStateToProps)(NotificationContainer);

View File

@ -22,7 +22,9 @@ class NotificationScreen extends PureComponent {
}
render() {
const { notifications, getActivities, intl } = this.props;
const {
notifications, getActivities, intl, navigateToNotificationRoute,
} = this.props;
return (
<View style={globalStyles.container}>
<Header />
@ -38,7 +40,11 @@ class NotificationScreen extends PureComponent {
})}
style={styles.notificationTab}
>
<Notification getActivities={getActivities} notifications={notifications} />
<Notification
getActivities={getActivities}
notifications={notifications}
navigateToNotificationRoute={navigateToNotificationRoute}
/>
</View>
<View
tabLabel={intl.formatMessage({