diff --git a/src/component/notification/notificationList.js b/src/component/notification/notificationList.js index e61cbf8..4f774c7 100644 --- a/src/component/notification/notificationList.js +++ b/src/component/notification/notificationList.js @@ -1,9 +1,11 @@ import React, {Component} from 'react'; -import {StyleSheet, Text, View, FlatList, InteractionManager} from 'react-native'; +import {StyleSheet, Text, View, FlatList, InteractionManager, ActivityIndicator, Platform} from 'react-native'; import {Navigation} from 'react-native-navigation'; import Api from '../../util/api'; import Notification from './notification'; +import Color from "../../style/color"; +import {ListEmptyRefreshable} from "../listEmpty"; export default class NotificationList extends Component { @@ -13,7 +15,8 @@ export default class NotificationList extends Component { this.state = { notifications: [], - refreshing: false + refreshing: false, + error: false }; } @@ -23,42 +26,79 @@ export default class NotificationList extends Component { }); } - refresh() { - this.setState({refreshing: true}); - Api.getMessagesHistory() - .then(notifications => { - if(notifications) { - let reducedNoti = notifications.reduce((ret, v) => { - if(v.type == 1) { - let items = ret.filter(x => x.type === 1 && x.link_id === v.link_id); - if(items.length > 0) { - items[0].list.push(v); + refresh(showRefreshing = true) { + if(showRefreshing) { + this.setState({refreshing: true}); + } - } else { - ret.push({ - type: 1, - link_id: v.link_id, - created: v.created, - list: [v] - }); - } + (async () => { + try { + let notifications = await this.getMessages() + this.notificationsData = notifications; + this.setNotifications(notifications); + } catch (e) { + this.setState({error: true}); + } + this.setState({refreshing: false}); + })(); - } else if (v.type == 2) { - ret.push(v); - } - - return ret; + this.props.onRefresh && this.props.onRefresh(); + } - }, []); + setNotifications(notifications){ + if(notifications) { + let reducedNoti = notifications.reduce((ret, v) => { + if(v.type == 1) { + let items = ret.filter(x => x.type === 1 && x.link_id === v.link_id); + if(items.length > 0) { + items[0].list.push(v); - this.setState({ - notifications: reducedNoti - }); + } else { + ret.push({ + type: 1, + link_id: v.link_id, + created: v.created, + list: [v] + }); + } + + } else if (v.type == 2) { + ret.push(v); } - }).done(() => { - this.setState({refreshing: false}); + return ret; + + }, []); + + this.setState({ + notifications: reducedNoti }); + } + } + + getMessages() { + if(this.props.isHistory) { + return Api.getMessagesHistory(); + } else { + return Api.getMessages(); + } + } + + async _setRead(msg) { + let ids = null; + if (msg.type === 1) { //回复 + ids = msg.list.map(it => it.id); + } else if (msg.type === 2) { //关注 + ids = [msg.id]; + } + + try { + this.notificationsData = this.notificationsData.filter((msg) => ids.indexOf(msg.id) === -1); + this.setNotifications(this.notificationsData); + await Api.deleteMessage(ids); + } catch (err) { + console.log(err); + } } _onCommentPress(msg) { @@ -79,6 +119,10 @@ export default class NotificationList extends Component { } } }); + + if(this.props.isSetRead) { + this._setRead(msg); + } } _onFollowPress(msg) { @@ -99,6 +143,10 @@ export default class NotificationList extends Component { } } }); + + if(this.props.isSetRead) { + this._setRead(msg); + } } render() { @@ -124,13 +172,35 @@ export default class NotificationList extends Component { onRefresh={this.refresh.bind(this)} /> - ) : null; + ) : this.renderEmpty(); + } + + renderEmpty() { + if (this.state.refreshing) { + return ( + + + + ) + } + let text = this.state.error ? '出错了 :(':'没有提醒 :)'; + return ( + + ); } } -const localStyle = StyleSheet.create({ - -}); +// NotificationList.propTypes = { +// isHistory: PropTypes.boolean, +// onRefresh: PropTypes.func, +// isSetRead: PropTypes.boolean +// }; +// +// NotificationList.defaultProps = { +// isHistory: true, +// isSetRead: false, +// }; + diff --git a/src/page/NotificationPage.js b/src/page/NotificationPage.js index ff8d65e..cdf6f65 100644 --- a/src/page/NotificationPage.js +++ b/src/page/NotificationPage.js @@ -1,5 +1,5 @@ import React, {Component} from 'react'; -import {Platform, StyleSheet, Text, View} from 'react-native'; +import {Platform, StyleSheet, Text, View, InteractionManager, DeviceEventEmitter, ListView, ActivityIndicator, RefreshControl} from 'react-native'; import {Button} from 'react-native-elements' import {Navigation} from 'react-native-navigation'; @@ -7,31 +7,47 @@ import Color from '../style/color' import {Icon} from '../style/icon' import {ListEmptyRefreshable} from '../component/listEmpty' +import Push from "../util/push"; +import Api from "../util/api"; +import Event from "../util/event"; +import Notification from "../component/notification/notification"; +import NotificationList from "../component/notification/notificationList"; +const LOOP_TIME_SHORT = 30 * 1000; +const LOOP_TIME_LONG = 60 * 1000; export default class NotificationPage extends Component { - constructor(props) { - super(props); - Navigation.events().bindComponent(this); - } - static options(passProps) { return { topBar: { - title: { - text: '提醒' - }, - rightButtons: [{ - id: 'history', - icon: Icon.navButtonTime, + title: { + text: '提醒' + }, + rightButtons: [{ + id: 'history', + icon: Icon.navButtonTime, - color: Color.primary // android - }] + color: Color.primary // android + }] } }; } + constructor(props) { + super(props); + Navigation.events().bindComponent(this); + + // const ds = new ListView.DataSource({ + // rowHasChanged: (r1, r2) => r1 !== r2 + // }); + // this.state = ({ + // messages: [], + // messagesDataSource: ds, + // refreshing: true, + // }); + } + navigationButtonPressed({buttonId}) { Navigation.push(this.props.componentId, { component: { @@ -40,21 +56,147 @@ export default class NotificationPage extends Component { }); } + loopTime = LOOP_TIME_LONG; + tipTimer = null; + + componentDidMount() { + InteractionManager.runAfterInteractions(() => { + if (Platform.OS === 'android') { + this.initAndroid().done() + } else { + this.initIOS().done() + } + + this.restartTipTimer().done(); + }); + this.loginListener = DeviceEventEmitter.addListener(Event.login, () => { + this.registerUser().done(); + this.restartTipTimer().done(); + }); + this.updatePushInfo().done(); + } + + componentWillUnmount() { + this.loginListener.remove(); + //todo:删除 push 事件注册,删除定时器 + } + + async updatePushInfo() { + let info; + try { + info = await Api.updatePushInfo() + } catch (err) { + console.error(err) + } + // console.log('updatePushInfo', info) + } + + /** + * 更新刷新定时器 + * @returns {Promise} + */ + async restartTipTimer() { + if (this.tipTimer) { + clearTimeout(this.tipTimer); + } + + this.tipTimer = setTimeout(() => { + this.refresh(); + }, this.loopTime) + } + + async initAndroid() { + Push.init((msg) => { + console.log("push init: " + msg); + this.registerUser(); + Push.addReceiveNotificationListener((msg) => { + this.restartTipTimer().done(); + }); + }) + } + + async initIOS() { + Push.init((msg) => { + console.log("push init: " + msg); + this.registerUser(); + Push.addReceiveNotificationListener((msg) => { + this.restartTipTimer().done(); + }); + }) + } + + async registerUser() { + const user = await Api.getSelfInfoByStore(); + if (!user || !user.id) return; + //const settings = await Api.getSettings(); + //const push = settings['pushMessage']; + const push = true; + const alias = push ? user.id.toString() : user.id.toString() + '_close'; + Push.setAccount(alias, success => { + console.log('JPushModule.setAlias ' + alias + ' ' + success); + }); + + // Crashlytics.setUserName(user.name); + // Crashlytics.setUserEmail(user.email); + // Crashlytics.setUserIdentifier(user.id.toString()); + } + + + _onRefresh() { + this.restartTipTimer().done(); + } + + refresh() { + this.list.refresh(false); + } + + _onDeletePress(msg) { + this._setRead(msg).done(); + } + + render() { return ( - + + {this.list = r}} + isHistory={false} + onRefresh={this._onRefresh.bind(this)} + isSetRead={true} + {...this.props}/> + + ) + } + + + renderEmpty() { + if (this.state.refreshing) { + return ( + + + + ) + } + let text = this.state.error ? '出错了 :(':'没有提醒 :)'; + return ( + ); } } -const localStyle = StyleSheet.create({ - container: { - alignItems:'center', - justifyContent: 'center', - height: '100%' +const styles = StyleSheet.create({ + message: { + padding: 20, + borderColor: Color.line, + borderBottomWidth: StyleSheet.hairlineWidth, + flexDirection: 'row' }, - text: { - paddingBottom: 15, - color: Color.text + icon: { + marginRight: 10, + marginTop: 1, + lineHeight: 20, + }, + delete: { + lineHeight: 20, + paddingHorizontal: 8, } -}); +}); \ No newline at end of file diff --git a/src/util/api.js b/src/util/api.js index 1b75aa2..64eb6c0 100644 --- a/src/util/api.js +++ b/src/util/api.js @@ -247,11 +247,18 @@ async function addFollow(user_id) { return call('POST', '/relation/' + user_id); } +async function getMessages() { + return call('GET', '/tip'); +} async function getMessagesHistory() { return call('GET', '/tip/history'); } +async function deleteMessage(ids) { + return call('POST', '/tip/read/' + ids.join(',')) +} + async function getDiary(id) { return call('GET', '/diaries/' + id); } @@ -343,6 +350,10 @@ async function getUpdateInfo() { return callV2('GET', '/updateInfo'); } +export async function updatePushInfo() { + return callV2('POST', '/push'); +} + async function upload(method, api, body) { let token = await Token.getUserToken(); @@ -525,7 +536,9 @@ export default { deleteFollowBy, addFollow, + getMessages, getMessagesHistory, + deleteMessage, updateNotebookCover, createNotebook, @@ -534,5 +547,7 @@ export default { report, feedback, - getUpdateInfo + getUpdateInfo, + + updatePushInfo, } \ No newline at end of file