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 BACKEND_URL=https://myapi.com
SEARCH_API_URL=https://search.com SEARCH_API_URL=https://search.com
SEARCH_API_TOKEN=abcde SEARCH_API_TOKEN=abcde
ACTIVITY_WEBSOCKET_URL=ws://host.com/path

71
package-lock.json generated
View File

@ -10262,8 +10262,7 @@
"react-is": { "react-is": {
"version": "16.6.0", "version": "16.6.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.0.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.0.tgz",
"integrity": "sha512-q8U7k0Fi7oxF1HvQgyBjPwDXeMplEsArnKt2iYhuIF86+GBbgLHdAmokL3XUFjTd7Q363OSNG55FOGUdONVn1g==", "integrity": "sha512-q8U7k0Fi7oxF1HvQgyBjPwDXeMplEsArnKt2iYhuIF86+GBbgLHdAmokL3XUFjTd7Q363OSNG55FOGUdONVn1g=="
"dev": true
}, },
"react-lifecycles-compat": { "react-lifecycles-compat": {
"version": "3.0.4", "version": "3.0.4",
@ -10565,9 +10564,9 @@
} }
}, },
"react-native-screens": { "react-native-screens": {
"version": "1.0.0-alpha.14", "version": "1.0.0-alpha.16",
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-1.0.0-alpha.14.tgz", "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-1.0.0-alpha.16.tgz",
"integrity": "sha512-SXVl5dnN5ZgV7jF2NdqScp91qW3QOZipBPp8f0CpAtb/ucEQkteiQnTGb4BNS5OvpMVi1UNw4BXWhUsKRPqzPw==" "integrity": "sha512-t+/aq5jQa+Is6afiQHa1P+2UPnwPGY9NT0pSqNr2zQ5llCn8TcPq6GN8xDMuEc08g+y/9R5zWo32hlVStwWn1A=="
}, },
"react-native-slider": { "react-native-slider": {
"version": "0.11.0", "version": "0.11.0",
@ -10601,47 +10600,29 @@
"integrity": "sha512-CcX61kqFyO41WAmqARr/1A7YgTkd1GoQGJl0LYrzl+4CL5uw2CAu68T+1DPapt7RdgvSMLZIPlNvj4TzdJY/hw==" "integrity": "sha512-CcX61kqFyO41WAmqARr/1A7YgTkd1GoQGJl0LYrzl+4CL5uw2CAu68T+1DPapt7RdgvSMLZIPlNvj4TzdJY/hw=="
}, },
"react-navigation": { "react-navigation": {
"version": "2.17.0", "version": "2.18.3",
"resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-2.17.0.tgz", "resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-2.18.3.tgz",
"integrity": "sha512-OT3V5ZGA+VOFydjJg5JAo/sh94stWoyEYXOVdAz98Rw4UW3BATUG6Y/4ROMbBSlYl2PvGfc9Q1+RHEhy5Xjp8A==", "integrity": "sha512-/5KGMG1Oj5LN/x/7AKF0MWrpX9Qe29307RxEsMCiRT/A4jCYT0DPY99Bl7ZAGtROxExEy3rwTfTrtvpIT+CU7A==",
"requires": { "requires": {
"clamp": "1.0.1", "clamp": "1.0.1",
"create-react-context": "0.2.2", "create-react-context": "0.2.2",
"hoist-non-react-statics": "2.5.5", "hoist-non-react-statics": "2.5.5",
"path-to-regexp": "1.7.0", "path-to-regexp": "1.7.0",
"query-string": "6.2.0", "query-string": "6.2.0",
"react-is": "16.6.0",
"react-lifecycles-compat": "3.0.4", "react-lifecycles-compat": "3.0.4",
"react-native-safe-area-view": "0.11.0", "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-deprecated-tab-navigator": "1.3.0",
"react-navigation-drawer": "0.5.0", "react-navigation-drawer": "0.5.0",
"react-navigation-stack": "0.7.0", "react-navigation-stack": "0.7.0",
"react-navigation-tabs": "0.8.2" "react-navigation-tabs": "0.8.4"
}, },
"dependencies": { "dependencies": {
"hoist-non-react-statics": { "hoist-non-react-statics": {
"version": "2.5.5", "version": "2.5.5",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", "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==" "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": { "react-navigation-redux-helpers": {
"version": "2.0.6", "version": "2.0.8",
"resolved": "https://registry.npmjs.org/react-navigation-redux-helpers/-/react-navigation-redux-helpers-2.0.6.tgz", "resolved": "https://registry.npmjs.org/react-navigation-redux-helpers/-/react-navigation-redux-helpers-2.0.8.tgz",
"integrity": "sha512-/goEObr1Det7PDkw75o8Rr1ItzlWyMlwUBGYQMtM6kRAVa3i/E77VqjfrRrZ1a6+KAnnRNUSkS8AS4K7s41/Ng==", "integrity": "sha512-gCxHOGWNbRtt6Se93uuIE3cKqmqln73wlMeyD02aE1vs0cl9fn7BUKXX+UESrBSUOqadeoS1I7AH4arxZAARTQ==",
"requires": { "requires": {
"invariant": "2.2.4" "invariant": "2.2.4"
} }
@ -10674,6 +10655,32 @@
"resolved": "https://registry.npmjs.org/react-navigation-stack/-/react-navigation-stack-0.7.0.tgz", "resolved": "https://registry.npmjs.org/react-navigation-stack/-/react-navigation-stack-0.7.0.tgz",
"integrity": "sha512-3Tbb/SsustBrM9R/qaI6XuOfyqYMVbwkeHFC8NbU890vB0aKZvjAtioWLZ18e/4LgbiOCmoTdp37z3gkGDyNDQ==" "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": { "react-proxy": {
"version": "1.1.8", "version": "1.1.8",
"resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-1.1.8.tgz", "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-slider": "^0.11.0",
"react-native-vector-icons": "^6.0.2", "react-native-vector-icons": "^6.0.2",
"react-native-view-overflow": "0.0.3", "react-native-view-overflow": "0.0.3",
"react-navigation": "^2.17.0", "react-navigation": "^2.18.3",
"react-navigation-redux-helpers": "^2.0.6", "react-navigation-redux-helpers": "^2.0.8",
"react-redux": "^5.0.7", "react-redux": "^5.0.7",
"realm": "2.16.0", "realm": "2.16.0",
"redux": "^4.0.0", "redux": "^4.0.0",

View File

@ -1,8 +1,11 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { TouchableWithoutFeedback } from 'react-native'; import { TouchableWithoutFeedback } from 'react-native';
import { connect } from 'react-redux';
import ViewOverflow from 'react-native-view-overflow'; import ViewOverflow from 'react-native-view-overflow';
// Services and Actions
import { updateActiveBottomTab } from '../../../redux/actions/uiAction';
// Constants // Constants
// Components // Components
@ -22,6 +25,16 @@ class BottomTabBarView extends Component {
} }
// Component Life Cycles // Component Life Cycles
componentWillUpdate(nextProps) {
const {
navigation: {
state: { index, routes },
},
dispatch,
} = nextProps;
dispatch(updateActiveBottomTab(routes[index].routeName));
}
// Component Functions // 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() { render() {
const { notifications, intl } = this.props; const { notifications, intl, navigateToNotificationRoute } = this.props;
const { filters } = this.state; const { filters } = this.state;
const today = []; const today = [];
const yesterday = []; const yesterday = [];
@ -91,7 +91,12 @@ class NotificationView extends Component {
/> />
<FlatList <FlatList
data={today} data={today}
renderItem={({ item }) => <NotificationLine notification={item} />} renderItem={({ item }) => (
<NotificationLine
notification={item}
handleOnPressNotification={navigateToNotificationRoute}
/>
)}
keyExtractor={item => item.id} keyExtractor={item => item.id}
/> />
</Fragment> </Fragment>
@ -107,7 +112,12 @@ class NotificationView extends Component {
/> />
<FlatList <FlatList
data={yesterday} data={yesterday}
renderItem={({ item }) => <NotificationLine notification={item} />} renderItem={({ item }) => (
<NotificationLine
notification={item}
handleOnPressNotification={navigateToNotificationRoute}
/>
)}
keyExtractor={item => item.id} keyExtractor={item => item.id}
/> />
</Fragment> </Fragment>
@ -123,7 +133,12 @@ class NotificationView extends Component {
/> />
<FlatList <FlatList
data={thisWeek} data={thisWeek}
renderItem={({ item }) => <NotificationLine notification={item} />} renderItem={({ item }) => (
<NotificationLine
notification={item}
handleOnPressNotification={navigateToNotificationRoute}
/>
)}
keyExtractor={item => item.id} keyExtractor={item => item.id}
/> />
</Fragment> </Fragment>
@ -139,7 +154,12 @@ class NotificationView extends Component {
/> />
<FlatList <FlatList
data={thisMonth} data={thisMonth}
renderItem={({ item }) => <NotificationLine notification={item} />} renderItem={({ item }) => (
<NotificationLine
notification={item}
handleOnPressNotification={navigateToNotificationRoute}
/>
)}
keyExtractor={item => item.id} keyExtractor={item => item.id}
/> />
</Fragment> </Fragment>
@ -155,7 +175,12 @@ class NotificationView extends Component {
/> />
<FlatList <FlatList
data={olderThenMonth} data={olderThenMonth}
renderItem={({ item }) => <NotificationLine notification={item} />} renderItem={({ item }) => (
<NotificationLine
notification={item}
handleOnPressNotification={navigateToNotificationRoute}
/>
)}
keyExtractor={item => item.id} keyExtractor={item => item.id}
/> />
</Fragment> </Fragment>

View File

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

View File

@ -1,5 +1,6 @@
const SCREEN_SUFFIX = 'Screen'; const SCREEN_SUFFIX = 'Screen';
const DRAWER_SUFFIX = 'Drawer'; const DRAWER_SUFFIX = 'Drawer';
const TABBAR_SUFFIX = 'Tabbar';
export default { export default {
SCREENS: { SCREENS: {
@ -18,4 +19,11 @@ export default {
DRAWER: { DRAWER: {
MAIN: `Main${DRAWER_SUFFIX}`, 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 React from 'react';
import { createBottomTabNavigator } from 'react-navigation'; 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 { import {
Home, Notification, Profile, RootComponent, Messages, Home, Notification, Profile, RootComponent, Messages,
} from '../screens'; } from '../screens';
import { PostButton } from '../components/postButton'; import { PostButton } from '../components/postButton';
import { BottomTabBar } from '../components/bottomTabBar'; import { BottomTabBar } from '../components/bottomTabBar';
// import style from './baseNavigatorStyles';
const BaseNavigator = createBottomTabNavigator( const BaseNavigator = createBottomTabNavigator(
{ {
Home: { [ROUTES.TABBAR.HOME]: {
screen: RootComponent()(Home), screen: RootComponent()(Home),
navigationOptions: () => ({ navigationOptions: () => ({
tabBarIcon: ({ tintColor }) => ( tabBarIcon: ({ tintColor }) => (
@ -26,7 +28,7 @@ const BaseNavigator = createBottomTabNavigator(
), ),
}), }),
}, },
Notification: { [ROUTES.TABBAR.NOTIFICATION]: {
screen: RootComponent()(Notification), screen: RootComponent()(Notification),
navigationOptions: () => ({ navigationOptions: () => ({
tabBarIcon: ({ tintColor }) => ( tabBarIcon: ({ tintColor }) => (
@ -42,13 +44,13 @@ const BaseNavigator = createBottomTabNavigator(
), ),
}), }),
}, },
PostButton: { [ROUTES.TABBAR.POSTBUTTON]: {
screen: () => null, screen: () => null,
navigationOptions: () => ({ navigationOptions: () => ({
tabBarIcon: <PostButton />, tabBarIcon: <PostButton />,
}), }),
}, },
Messages: { [ROUTES.TABBAR.MESSAGES]: {
screen: RootComponent()(Messages), screen: RootComponent()(Messages),
navigationOptions: () => ({ navigationOptions: () => ({
tabBarIcon: ({ tintColor }) => ( tabBarIcon: ({ tintColor }) => (
@ -62,7 +64,7 @@ const BaseNavigator = createBottomTabNavigator(
), ),
}), }),
}, },
Profile: { [ROUTES.TABBAR.PROFILE]: {
screen: RootComponent()(Profile), screen: RootComponent()(Profile),
navigationOptions: () => ({ navigationOptions: () => ({
tabBarIcon: ({ tintColor }) => ( 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 }; export { BaseNavigator };

View File

@ -88,7 +88,18 @@ export const getUnreadActivityCount = data => new Promise((resolve, reject) => {
api api
.get(`/activities/${data.user}/unread-count`) .get(`/activities/${data.user}/unread-count`)
.then((res) => { .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) => { .catch((error) => {
reject(error); reject(error);

View File

@ -4,6 +4,7 @@ import {
FETCHING_ACCOUNT, FETCHING_ACCOUNT,
ADD_OTHER_ACCOUNT, ADD_OTHER_ACCOUNT,
UPDATE_CURRENT_ACCOUNT, UPDATE_CURRENT_ACCOUNT,
UPDATE_UNREAD_ACTIVITY_COUNT,
} from '../constants/constants'; } from '../constants/constants';
export const fetchAccountFromSteem = (username, password) => (dispatch) => { export const fetchAccountFromSteem = (username, password) => (dispatch) => {
@ -31,3 +32,8 @@ export const failedAccount = data => ({
type: FETCH_ACCOUNT_FAIL, type: FETCH_ACCOUNT_FAIL,
payload: data, 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 UPDATE_CURRENT_ACCOUNT = 'UPDATE_CURRENT_ACCOUNT';
export const FETCHING_ACCOUNT = 'FETCHING_ACCOUNT'; export const FETCHING_ACCOUNT = 'FETCHING_ACCOUNT';
export const FETCH_ACCOUNT_FAIL = 'FETCH_ACCOUNT_FAIL'; 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 IS_LOGGED_IN = 'IS_LOGGED_IN';
export const OPEN_PIN_CODE_MODAL = 'OPEN_PIN_CODE_MODAL'; 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_NOTIFICATION_OPEN = 'IS_NOTIFICATION_OPEN';
export const IS_DARK_THEME = 'IS_DARK_THEME'; 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, FETCHING_ACCOUNT,
ADD_OTHER_ACCOUNT, ADD_OTHER_ACCOUNT,
UPDATE_CURRENT_ACCOUNT, UPDATE_CURRENT_ACCOUNT,
UPDATE_UNREAD_ACTIVITY_COUNT,
} from '../constants/constants'; } from '../constants/constants';
const initialState = { const initialState = {
@ -47,6 +48,17 @@ export default function (state = initialState, action) {
hasError: false, hasError: false,
errorMessage: null, errorMessage: null,
}; };
case UPDATE_UNREAD_ACTIVITY_COUNT:
return {
...state,
currentAccount: {
...state.currentAccount,
unread_activity_count: action.payload,
},
isFetching: false,
hasError: false,
errorMessage: null,
};
default: default:
return state; return state;
} }

View File

@ -2,9 +2,11 @@ import { combineReducers } from 'redux';
import accountReducer from './accountReducer'; import accountReducer from './accountReducer';
import applicationReducer from './applicationReducer'; import applicationReducer from './applicationReducer';
import nav from './nav'; import nav from './nav';
import ui from './uiReducer';
export default combineReducers({ export default combineReducers({
account: accountReducer, account: accountReducer,
application: applicationReducer, application: applicationReducer,
nav, 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 React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { addLocaleData } from 'react-intl'; import { addLocaleData } from 'react-intl';
import Config from 'react-native-config';
// Constants // Constants
import en from 'react-intl/locale-data/en'; import en from 'react-intl/locale-data/en';
import tr from 'react-intl/locale-data/tr'; 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'; import { getUser } from '../../../providers/steem/dsteem';
// Actions // Actions
import { addOtherAccount, updateCurrentAccount } from '../../../redux/actions/accountAction'; import {
addOtherAccount,
updateCurrentAccount,
updateUnreadActivityCount,
} from '../../../redux/actions/accountAction';
import { import {
activeApplication, activeApplication,
login, login,
@ -77,6 +83,7 @@ class ApplicationContainer extends Component {
if (__DEV__ === false) { if (__DEV__ === false) {
dispatch(openPinCodeModal()); dispatch(openPinCodeModal());
} }
this._connectNotificationServer(accountData.name);
}) })
.catch((err) => { .catch((err) => {
alert(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() { render() {
const { selectedLanguage } = this.props; const { selectedLanguage } = this.props;
const { isRenderRequire } = this.state; const { isRenderRequire } = this.state;
@ -122,6 +140,7 @@ class ApplicationContainer extends Component {
const mapStateToProps = state => ({ const mapStateToProps = state => ({
isDarkTheme: state.application.isDarkTheme, isDarkTheme: state.application.isDarkTheme,
selectedLanguage: state.application.language, selectedLanguage: state.application.language,
unreadActivityCount: state.account.currentAccount.unread_activity_count,
}); });
export default connect(mapStateToProps)(ApplicationContainer); export default connect(mapStateToProps)(ApplicationContainer);

View File

@ -2,7 +2,11 @@ import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
// Actions and Services // 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 // Components
import { NotificationScreen } from '../index'; import { NotificationScreen } from '../index';
@ -15,8 +19,10 @@ class NotificationContainer extends Component {
}; };
} }
componentWillMount() { componentWillReceiveProps(nextProps) {
this._getAvtivities(); if (nextProps.activeBottomTab === ROUTES.TABBAR.NOTIFICATION) {
this._getAvtivities();
}
} }
_getAvtivities = (type = null) => { _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() { render() {
const { notifications } = this.state; const { notifications } = this.state;
@ -34,6 +67,7 @@ class NotificationContainer extends Component {
<NotificationScreen <NotificationScreen
getActivities={this._getAvtivities} getActivities={this._getAvtivities}
notifications={notifications} notifications={notifications}
navigateToNotificationRoute={this._navigateToNotificationRoute}
{...this.props} {...this.props}
/> />
); );
@ -42,6 +76,7 @@ class NotificationContainer extends Component {
const mapStateToProps = state => ({ const mapStateToProps = state => ({
username: state.account.currentAccount.name, username: state.account.currentAccount.name,
activeBottomTab: state.ui.activeBottomTab,
}); });
export default connect(mapStateToProps)(NotificationContainer); export default connect(mapStateToProps)(NotificationContainer);

View File

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