Authored by 王钱钧

完善个人中心功能。 code review by 于良

@@ -41,8 +41,10 @@ import HomeContainer from './containers/HomeContainer'; @@ -41,8 +41,10 @@ import HomeContainer from './containers/HomeContainer';
41 import SectionContainer from './containers/SectionContainer'; 41 import SectionContainer from './containers/SectionContainer';
42 import UserContainer from './containers/UserContainer'; 42 import UserContainer from './containers/UserContainer';
43 import UserThatNotMeContainer from './containers/UserThatNotMeContainer'; 43 import UserThatNotMeContainer from './containers/UserThatNotMeContainer';
  44 +import MessageCenterContainer from './containers/MessageCenterContainer';
44 import SubjectPostContainer from './containers/SubjectPostContainer'; 45 import SubjectPostContainer from './containers/SubjectPostContainer';
45 import PostingContainer from './containers/PostingContainer'; 46 import PostingContainer from './containers/PostingContainer';
  47 +import SettingContainer from './containers/UserSettingContainer';
46 48
47 import NavBar from './components/NavBar'; 49 import NavBar from './components/NavBar';
48 50
@@ -201,6 +203,22 @@ export default function community(platform) { @@ -201,6 +203,22 @@ export default function community(platform) {
201 /> 203 />
202 204
203 <Scene 205 <Scene
  206 + key="MessageCenter"
  207 + title="消息"
  208 + hideNavBar={false}
  209 + component={MessageCenterContainer}
  210 + initial={false}
  211 + />
  212 +
  213 + <Scene
  214 + key="Setting"
  215 + title="社区资料"
  216 + hideNavBar={false}
  217 + component={SettingContainer}
  218 + initial={false}
  219 + />
  220 +
  221 + <Scene
204 key="UserThatNotMe" 222 key="UserThatNotMe"
205 title="用户中心" 223 title="用户中心"
206 hideNavBar={true} 224 hideNavBar={true}
@@ -45,6 +45,7 @@ export default class CommunityList extends React.Component { @@ -45,6 +45,7 @@ export default class CommunityList extends React.Component {
45 likeCount: React.PropTypes.number, 45 likeCount: React.PropTypes.number,
46 }), 46 }),
47 ), 47 ),
  48 + onPressPost: React.PropTypes.func,
48 }; 49 };
49 50
50 constructor(props) { 51 constructor(props) {
@@ -63,20 +64,20 @@ export default class CommunityList extends React.Component { @@ -63,20 +64,20 @@ export default class CommunityList extends React.Component {
63 <ListCell 64 <ListCell
64 key={sectionID + rowID} 65 key={sectionID + rowID}
65 data={rowData} 66 data={rowData}
66 - onPressPost={(url) => {  
67 - this.props.onPressPost && this.props.onPressPost(url); 67 + onPressPost={() => {
  68 + this.props.onPressPost && this.props.onPressPost(rowData.get('id'));
68 }} 69 }}
69 onPressAvatar={(url) => { 70 onPressAvatar={(url) => {
70 this.props.onPressAvatar && this.props.onPressAvatar(url); 71 this.props.onPressAvatar && this.props.onPressAvatar(url);
71 }} 72 }}
72 - onPressSectionTag={(url) => {  
73 - this.props.onPressSectionTag && this.props.onPressSectionTag(url); 73 + onPressSectionTag={() => {
  74 + this.props.onPressSectionTag && this.props.onPressSectionTag(rowData.get('section').toJS());
74 }} 75 }}
75 - onPressComment={(url) => {  
76 - this.props.onPressComment && this.props.onPressComment(url); 76 + onPressComment={() => {
  77 + this.props.onPressComment && this.props.onPressComment(rowData.get('id'));
77 }} 78 }}
78 - onPressLike={(url) => {  
79 - this.props.onPressLike && this.props.onPressLike(url); 79 + onPressLike={() => {
  80 + this.props.onPressLike && this.props.onPressLike(rowData);
80 }} 81 }}
81 /> 82 />
82 ); 83 );
@@ -87,22 +87,26 @@ export default class MessageCenter extends React.Component { @@ -87,22 +87,26 @@ export default class MessageCenter extends React.Component {
87 } 87 }
88 } 88 }
89 89
  90 + /*
  91 + <ListView
  92 + dataSource={this.dataSource.cloneWithRowsAndSections(dataSource)}
  93 + renderRow={this._renderRow}
  94 + renderSeparator={this._renderSeparator}
  95 + />
  96 + */
  97 +
90 render() { 98 render() {
91 99
92 let {system, like, message,} = this.props; 100 let {system, like, message,} = this.props;
93 - let dataSource = {  
94 - system: this.props.system.toArray(),  
95 - like: this.props.like.toArray(),  
96 - message: this.props.message.toArray(),  
97 - }; 101 + // let dataSource = {
  102 + // system: this.props.system.toArray(),
  103 + // like: this.props.like.toArray(),
  104 + // message: this.props.message.toArray(),
  105 + // };
98 106
99 return ( 107 return (
100 <View style={styles.container}> 108 <View style={styles.container}>
101 - <ListView  
102 - dataSource={this.dataSource.cloneWithRowsAndSections(dataSource)}  
103 - renderRow={this._renderRow}  
104 - renderSeparator={this._renderSeparator}  
105 - /> 109 +
106 110
107 </View> 111 </View>
108 ); 112 );
  1 +'use strict';
  2 +
  3 +import React from 'react';
  4 +import ReactNative from 'react-native';
  5 +import ImmutablePropTypes from 'react-immutable-proptypes';
  6 +// import SlicedImage from '../../../common/components/SlicedImage';
  7 +
  8 +const {
  9 + View,
  10 + Text,
  11 + Image,
  12 + TouchableOpacity,
  13 + StyleSheet,
  14 + Dimensions,
  15 +} = ReactNative;
  16 +
  17 +export default class MessageIcon extends React.Component {
  18 +
  19 + static propTypes = {
  20 + msgCount: React.PropTypes.string,
  21 + iconTap: React.PropTypes.func,
  22 + }
  23 +
  24 + constructor(props) {
  25 + super (props);
  26 + }
  27 +
  28 + renderMsgCount() {
  29 + if (parseInt(this.props.msgCount) !== 0) {
  30 +
  31 + return (
  32 + <View style={styles.textContainer}>
  33 + <Text style={styles.text}>{this.props.msgCount}</Text>
  34 + </View>
  35 + );
  36 + } else {
  37 + return null;
  38 + }
  39 + }
  40 +
  41 + render() {
  42 + return (
  43 + <View style={[styles.container, this.props.extraStyle]}>
  44 + <TouchableOpacity activeOpacity={0.8} onPress={() => {
  45 + this.props.iconTap && this.props.iconTap();
  46 + }}>
  47 +
  48 + <Image
  49 + style={styles.icon}
  50 + source={require('../../images/user/message.png')}
  51 + />
  52 +
  53 + {this.renderMsgCount()}
  54 +
  55 + </TouchableOpacity>
  56 + </View>
  57 + );
  58 + }
  59 +}
  60 +
  61 +
  62 +let styles = StyleSheet.create ({
  63 +
  64 + container: {
  65 + flexDirection: 'row',
  66 + alignItems: 'center',
  67 + justifyContent: 'center',
  68 + backgroundColor: 'transparent',
  69 + width: 32,
  70 + height: 23,
  71 + },
  72 +
  73 + icon: {
  74 +
  75 + },
  76 +
  77 + textContainer: {
  78 + position: 'absolute',
  79 + top: -10,
  80 + right: -8,
  81 + height: 18,
  82 + borderRadius: 9,
  83 + borderColor: 'red',
  84 + borderWidth: 1,
  85 + justifyContent: 'center',
  86 + alignItems: 'center',
  87 + opacity: 0.9,
  88 + backgroundColor: 'white',
  89 + flexDirection:'row',
  90 + },
  91 +
  92 + text: {
  93 + fontSize: 12,
  94 + color: 'red',
  95 + textAlign: 'center',
  96 + marginHorizontal: 6,
  97 + marginVertical: 6,
  98 + backgroundColor: 'transparent',
  99 + },
  100 +});
@@ -17,78 +17,103 @@ const { @@ -17,78 +17,103 @@ const {
17 export default class ReplyCell extends React.Component { 17 export default class ReplyCell extends React.Component {
18 18
19 static propTypes = { 19 static propTypes = {
20 - data: ImmutablePropTypes.contains({  
21 -  
22 - id: React.PropTypes.number,  
23 - postId: React.PropTypes.number,  
24 - createTime: React.PropTypes.number.isRequired,  
25 - authorUid: React.PropTypes.number,  
26 -  
27 - // 帖子  
28 - postInfo: ImmutablePropTypes.contains({  
29 - title: React.PropTypes.string,  
30 - type: React.PropTypes.string.isRequired,  
31 - }),  
32 20
33 - // 回复的内容  
34 - blocks: ImmutablePropTypes.listOf(  
35 - ImmutablePropTypes.contains({  
36 - commentId: React.PropTypes.number,  
37 - orderBy: React.PropTypes.number,  
38 - content: React.PropTypes.string,  
39 - templateKey: React.PropTypes.string.isRequired,  
40 - })  
41 - ),  
42 -  
43 - // 我的信息  
44 - reply: ImmutablePropTypes.contains({  
45 - headIcon: React.PropTypes.string, 21 + data: ImmutablePropTypes.contains({
  22 + self: ImmutablePropTypes.contains({
  23 + avatar: React.PropTypes.string,
46 uid: React.PropTypes.number, 24 uid: React.PropTypes.number,
47 name: React.PropTypes.string, 25 name: React.PropTypes.string,
  26 + backgroundImage: React.PropTypes.string,
48 }), 27 }),
49 28
50 - // 被回复者信息  
51 - replyTo: ImmutablePropTypes.contains({  
52 - headIcon: React.PropTypes.string, 29 + createTime: React.PropTypes.string.isRequired,
  30 +
  31 + replyToUser: ImmutablePropTypes.contains({
  32 + avatar: React.PropTypes.string,
53 uid: React.PropTypes.number, 33 uid: React.PropTypes.number,
54 name: React.PropTypes.string, 34 name: React.PropTypes.string,
  35 + backgroundImage: React.PropTypes.string,
  36 + }),
  37 +
  38 + replyContent: ImmutablePropTypes.contains({
  39 + thumbs: ImmutablePropTypes.listOf(
  40 + ImmutablePropTypes.contains({
  41 + src: React.PropTypes.string,
  42 + })
  43 + ),
  44 + desc: React.PropTypes.string,
  45 + }),
  46 +
  47 + postInfo: ImmutablePropTypes.contains({
  48 + type:React.PropTypes.string.isRequired,
  49 + title:React.PropTypes.string,
  50 + postId:React.PropTypes.string,
55 }), 51 }),
56 52
  53 + }),
  54 +
57 onPressAvatar: React.PropTypes.func, 55 onPressAvatar: React.PropTypes.func,
58 onPressReply: React.PropTypes.func, 56 onPressReply: React.PropTypes.func,
59 onPressPosts: React.PropTypes.func, 57 onPressPosts: React.PropTypes.func,
60 58
61 - }),  
62 -  
63 - // TODO 添加点击事件  
64 59
65 }; 60 };
66 61
67 constructor(props) { 62 constructor(props) {
68 super(props); 63 super(props);
  64 + this._renderReplyContent = this._renderReplyContent.bind(this);
  65 + this._renderPostInfo = this._renderPostInfo.bind(this);
  66 +
69 } 67 }
70 68
  69 + _renderReplyContent(replyContent) {
  70 + if (replyContent.desc === '') {
  71 + return (
  72 + <Image
  73 + source = {require('../../images/user/default-pic.png')}
  74 + />
  75 + );
  76 + } else {
  77 + return (
  78 + <Text>
  79 + {replyContent.desc}
  80 + </Text>
  81 + );
  82 + }
  83 + }
  84 +
  85 + _renderPostInfo(postInfo) {
  86 + if (postInfo.type === 'image') {
  87 + return (
  88 + <Image
  89 + source = {require('../../images/user/default-pic.png')}
  90 + />
  91 + );
  92 + } else {
  93 + return (
  94 + <Text>
  95 + {postInfo.title}
  96 + </Text>
  97 + );
  98 + }
  99 + }
71 render() { 100 render() {
72 let data = this.props.data.toJS(); 101 let data = this.props.data.toJS();
73 let { 102 let {
74 - id,  
75 - postId, 103 + self,
  104 + replyToUser,
  105 + replyContent,
76 createTime, 106 createTime,
77 - authorUid,  
78 postInfo, 107 postInfo,
79 - blocks,  
80 - reply,  
81 - replyTo,  
82 } = data; 108 } = data;
83 109
84 return ( 110 return (
85 <View style={styles.container}> 111 <View style={styles.container}>
86 <View style={styles.topContainer}> 112 <View style={styles.topContainer}>
87 <UserBrief 113 <UserBrief
88 - avatar={reply.headIcon}  
89 - name={reply.name} 114 + avatar={self.avatar}
  115 + name={self.name}
90 timeago={createTime.toString()} 116 timeago={createTime.toString()}
91 - // isOwner={isOwner}  
92 onPressAvatar={() => { 117 onPressAvatar={() => {
93 this.props.onPressAvatar && this.props.onPressAvatar(); 118 this.props.onPressAvatar && this.props.onPressAvatar();
94 }} 119 }}
@@ -105,12 +130,12 @@ export default class ReplyCell extends React.Component { @@ -105,12 +130,12 @@ export default class ReplyCell extends React.Component {
105 this.props.onPressReply && this.props.onPressReply(); 130 this.props.onPressReply && this.props.onPressReply();
106 }} 131 }}
107 > 132 >
108 - 小草莓 133 + {replyToUser.name}
109 </Text> 134 </Text>
110 135
111 136
112 137
113 - :如果你无法表单房间诶哦我就佛大发了瓦解偶发的拉萨减肥劳动局撒了附件二范德萨范德萨 138 + :{this._renderReplyContent(replyContent)}
114 </Text> 139 </Text>
115 </View> 140 </View>
116 141
@@ -124,7 +149,7 @@ export default class ReplyCell extends React.Component { @@ -124,7 +149,7 @@ export default class ReplyCell extends React.Component {
124 this.props.onPressPosts && this.props.onPressPosts(); 149 this.props.onPressPosts && this.props.onPressPosts();
125 }} 150 }}
126 > 151 >
127 - 帖子:港南爱上米彩妆,看叫啥呢我发的是fdsafdsafdsafdasfd剪短发搜富哦为福建省的 152 + 帖子:{this._renderPostInfo(postInfo)}
128 </Text> 153 </Text>
129 </View> 154 </View>
130 155
@@ -35,15 +35,15 @@ export default class ReplyList extends React.Component { @@ -35,15 +35,15 @@ export default class ReplyList extends React.Component {
35 // onPressPost={(url) => { 35 // onPressPost={(url) => {
36 // this.props.onPressPost && this.props.onPressPost(url); 36 // this.props.onPressPost && this.props.onPressPost(url);
37 // }} 37 // }}
38 - onPressAvatar={(url) => {  
39 - this.props.onPressAvatar && this.props.onPressAvatar(url); 38 + onPressAvatar={() => {
  39 + this.props.onPressAvatar && this.props.onPressAvatar();
40 }} 40 }}
41 41
42 - onPressReply={(url) => {  
43 - this.props.onPressReply && this.props.onPressReply(url); 42 + onPressReply={() => {
  43 + this.props.onPressReply && this.props.onPressReply(rowData.get('replyToUser').get('uid'));
44 }} 44 }}
45 - onPressPosts={(url) => {  
46 - this.props.onPressPosts && this.props.onPressPosts(url); 45 + onPressPosts={() => {
  46 + this.props.onPressPosts && this.props.onPressPosts(rowData.get('postInfo').get('postId'));
47 }} 47 }}
48 // onPressLike={(url) => { 48 // onPressLike={(url) => {
49 // this.props.onPressLike && this.props.onPressLike(url); 49 // this.props.onPressLike && this.props.onPressLike(url);
@@ -26,6 +26,10 @@ const { @@ -26,6 +26,10 @@ const {
26 Animated, 26 Animated,
27 } = ReactNative; 27 } = ReactNative;
28 28
  29 +let {width, height} = Dimensions.get('window');
  30 +let navbarHeight = (Platform.OS === 'android') ? 50 : 64;
  31 +let userBgHieght = Math.ceil((490 / 750) * width);
  32 +
29 export default class User extends React.Component { 33 export default class User extends React.Component {
30 34
31 static propTypes = { 35 static propTypes = {
@@ -35,6 +39,7 @@ export default class User extends React.Component { @@ -35,6 +39,7 @@ export default class User extends React.Component {
35 backgroundImage:React.PropTypes.string, 39 backgroundImage:React.PropTypes.string,
36 nickName:React.PropTypes.string.isRequired, 40 nickName:React.PropTypes.string.isRequired,
37 sign: React.PropTypes.string, 41 sign: React.PropTypes.string,
  42 + msgCount:React.PropTypes.number,
38 }), 43 }),
39 44
40 list: ImmutablePropTypes.listOf( 45 list: ImmutablePropTypes.listOf(
@@ -94,23 +99,38 @@ export default class User extends React.Component { @@ -94,23 +99,38 @@ export default class User extends React.Component {
94 99
95 reply: ImmutablePropTypes.listOf( 100 reply: ImmutablePropTypes.listOf(
96 ImmutablePropTypes.contains({ 101 ImmutablePropTypes.contains({
97 - reply: ImmutablePropTypes.contains({  
98 - headIcon: React.PropTypes.string, 102 + self: ImmutablePropTypes.contains({
  103 + avatar: React.PropTypes.string,
99 uid: React.PropTypes.number, 104 uid: React.PropTypes.number,
100 name: React.PropTypes.string, 105 name: React.PropTypes.string,
  106 + backgroundImage: React.PropTypes.string,
101 }), 107 }),
102 108
103 - replyTo: ImmutablePropTypes.contains({  
104 - headIcon: React.PropTypes.string, 109 + createTime: React.PropTypes.string.isRequired,
  110 +
  111 + replyToUser: ImmutablePropTypes.contains({
  112 + avatar: React.PropTypes.string,
105 uid: React.PropTypes.number, 113 uid: React.PropTypes.number,
106 name: React.PropTypes.string, 114 name: React.PropTypes.string,
  115 + backgroundImage: React.PropTypes.string,
107 }), 116 }),
108 117
109 - id: React.PropTypes.number,  
110 - postId: React.PropTypes.number,  
111 - createTime: React.PropTypes.number.isRequired,  
112 - authorUid: React.PropTypes.number,  
113 - }) 118 + replyContent: ImmutablePropTypes.contains({
  119 + thumbs: ImmutablePropTypes.listOf(
  120 + ImmutablePropTypes.contains({
  121 + src: React.PropTypes.string,
  122 + })
  123 + ),
  124 + desc: React.PropTypes.string,
  125 + }),
  126 +
  127 + postInfo: ImmutablePropTypes.contains({
  128 + type:React.PropTypes.string.isRequired,
  129 + title:React.PropTypes.string,
  130 + postId:React.PropTypes.string,
  131 + }),
  132 +
  133 + }),
114 134
115 ), 135 ),
116 136
@@ -122,7 +142,7 @@ export default class User extends React.Component { @@ -122,7 +142,7 @@ export default class User extends React.Component {
122 onPressAvatar: React.PropTypes.func, 142 onPressAvatar: React.PropTypes.func,
123 onPressComment: React.PropTypes.func, 143 onPressComment: React.PropTypes.func,
124 onPressLike: React.PropTypes.func, 144 onPressLike: React.PropTypes.func,
125 - onPressPosts: React.PropTypes.func, 145 + onPressPost: React.PropTypes.func,
126 onEndReached: React.PropTypes.func, 146 onEndReached: React.PropTypes.func,
127 onRefresh: React.PropTypes.func, 147 onRefresh: React.PropTypes.func,
128 }; 148 };
@@ -199,6 +219,7 @@ export default class User extends React.Component { @@ -199,6 +219,7 @@ export default class User extends React.Component {
199 } 219 }
200 220
201 _renderRow(rowData, sectionID, rowID, highlightRow) { 221 _renderRow(rowData, sectionID, rowID, highlightRow) {
  222 +
202 switch (sectionID) { 223 switch (sectionID) {
203 case 'userInfo': 224 case 'userInfo':
204 return ( 225 return (
@@ -248,8 +269,8 @@ export default class User extends React.Component { @@ -248,8 +269,8 @@ export default class User extends React.Component {
248 onPressReply={(url) => { 269 onPressReply={(url) => {
249 this.props.onPressReply && this.props.onPressReply(url); 270 this.props.onPressReply && this.props.onPressReply(url);
250 }} 271 }}
251 - onPressPosts={(url) => {  
252 - this.props.onPressPosts && this.props.onPressPosts(url); 272 + onPressPost={() => {
  273 + this.props.onPressPosts && this.props.onPressPosts();
253 }} 274 }}
254 275
255 /> 276 />
@@ -296,14 +317,23 @@ export default class User extends React.Component { @@ -296,14 +317,23 @@ export default class User extends React.Component {
296 317
297 _updateVerticalScrollValue(offsetY) { 318 _updateVerticalScrollValue(offsetY) {
298 319
299 - this.state.scrollValueV.setValue(offsetY/150);  
300 - this.state.listViewMarginTop.setValue(offsetY/150); 320 + let delta = userBgHieght-navbarHeight;
  321 +
  322 + this.state.scrollValueV.setValue(offsetY/delta);
  323 + // this.state.listViewMarginTop =
  324 + if (offsetY >= delta) {
  325 + this.state.listViewMarginTop.setValue(navbarHeight);
  326 + } else {
  327 + this.state.listViewMarginTop.setValue(offsetY);
  328 + }
  329 +
  330 + // this.state.scrollValueV.setValue(offsetY/150);
  331 + // this.state.listViewMarginTop.setValue(offsetY/150);
301 332
302 } 333 }
303 334
304 render() { 335 render() {
305 let {userInfo, list, user, endReached, isRefreshing, isLoadingMore, isFetching} = this.props; 336 let {userInfo, list, user, endReached, isRefreshing, isLoadingMore, isFetching} = this.props;
306 -  
307 let dataSource = { 337 let dataSource = {
308 userInfo: userInfo.toArray(), 338 userInfo: userInfo.toArray(),
309 list: list.toArray(), 339 list: list.toArray(),
@@ -315,6 +345,7 @@ export default class User extends React.Component { @@ -315,6 +345,7 @@ export default class User extends React.Component {
315 this.animView = c; 345 this.animView = c;
316 }} 346 }}
317 style={{flex:1, backgroundColor: 'transparent', top: this.state.listViewTop}} 347 style={{flex:1, backgroundColor: 'transparent', top: this.state.listViewTop}}
  348 +
318 > 349 >
319 <ListView 350 <ListView
320 ref={(c) => { 351 ref={(c) => {
@@ -353,15 +384,21 @@ export default class User extends React.Component { @@ -353,15 +384,21 @@ export default class User extends React.Component {
353 /> 384 />
354 </Animated.View> 385 </Animated.View>
355 386
356 - <UserNavBar scrollValue={this.state.scrollValueV} channel={this.props.channel}/> 387 + <UserNavBar
  388 + scrollValue={this.state.scrollValueV}
  389 + channel={this.props.channel}
  390 + hasRightButton={true}
  391 + msgCount={this.props.profile.msgCount}
  392 + rightButtonClick={this.props.rightButtonClick}
  393 + />
  394 +
357 </View> 395 </View>
358 ); 396 );
359 } 397 }
360 } 398 }
361 399
362 400
363 -let {width, height} = Dimensions.get('window');  
364 -let navbarHeight = (Platform.OS === 'android') ? 50 : 64; 401 +
365 402
366 let styles = StyleSheet.create({ 403 let styles = StyleSheet.create({
367 container: { 404 container: {
@@ -15,6 +15,7 @@ const { @@ -15,6 +15,7 @@ const {
15 TouchableHighlight, 15 TouchableHighlight,
16 } = ReactNative; 16 } = ReactNative;
17 17
  18 +
18 export default class UserCenterTop extends React.Component { 19 export default class UserCenterTop extends React.Component {
19 20
20 static propTypes = { 21 static propTypes = {
@@ -80,11 +81,11 @@ export default class UserCenterTop extends React.Component { @@ -80,11 +81,11 @@ export default class UserCenterTop extends React.Component {
80 81
81 let {width, height} = Dimensions.get('window'); 82 let {width, height} = Dimensions.get('window');
82 let navbarHeight = (Platform.OS === 'android') ? 50 : 64; 83 let navbarHeight = (Platform.OS === 'android') ? 50 : 64;
83 - 84 +let containerHieght = Math.ceil((490 / 750) * width);
84 let styles = StyleSheet.create({ 85 let styles = StyleSheet.create({
85 container: { 86 container: {
86 87
87 - height: 244, 88 + height: containerHieght,
88 backgroundColor: 'transparent', 89 backgroundColor: 'transparent',
89 }, 90 },
90 91
@@ -16,6 +16,7 @@ import { @@ -16,6 +16,7 @@ import {
16 } from 'react-native'; 16 } from 'react-native';
17 import {Actions} from 'react-native-router-flux'; 17 import {Actions} from 'react-native-router-flux';
18 import _backButtonImage from '../../images/home/menu_back1.png'; 18 import _backButtonImage from '../../images/home/menu_back1.png';
  19 +import MessageIcon from './MessageIcon'
19 20
20 const styles = StyleSheet.create({ 21 const styles = StyleSheet.create({
21 header: { 22 header: {
@@ -35,6 +36,7 @@ const styles = StyleSheet.create({ @@ -35,6 +36,7 @@ const styles = StyleSheet.create({
35 // borderBottomWidth: 0.5, 36 // borderBottomWidth: 0.5,
36 // borderBottomColor: '#828287', 37 // borderBottomColor: '#828287',
37 position: 'absolute', 38 position: 'absolute',
  39 +
38 }, 40 },
39 backButton: { 41 backButton: {
40 width: 60, 42 width: 60,
@@ -61,6 +63,20 @@ const styles = StyleSheet.create({ @@ -61,6 +63,20 @@ const styles = StyleSheet.create({
61 width: Dimensions.get('window').width, 63 width: Dimensions.get('window').width,
62 height: (Platform.OS === 'android') ? 50 : 64, 64 height: (Platform.OS === 'android') ? 50 : 64,
63 }, 65 },
  66 +
  67 + rightButton: {
  68 + position: 'absolute',
  69 + ...Platform.select({
  70 + ios: {
  71 + top: 22+8,
  72 + },
  73 + android: {
  74 + top: 10+8,
  75 + },
  76 + }),
  77 +
  78 + right: 15,
  79 + }
64 }); 80 });
65 81
66 const propTypes = { 82 const propTypes = {
@@ -81,6 +97,7 @@ class UserNavBar extends React.Component { @@ -81,6 +97,7 @@ class UserNavBar extends React.Component {
81 super(props); 97 super(props);
82 98
83 this.renderBackButton = this.renderBackButton.bind(this); 99 this.renderBackButton = this.renderBackButton.bind(this);
  100 + this.renderRightButton = this.renderRightButton.bind(this);
84 this.setAnimationValue = this.setAnimationValue.bind(this); 101 this.setAnimationValue = this.setAnimationValue.bind(this);
85 this.headerColor = this.headerColor.bind(this); 102 this.headerColor = this.headerColor.bind(this);
86 } 103 }
@@ -137,6 +154,19 @@ class UserNavBar extends React.Component { @@ -137,6 +154,19 @@ class UserNavBar extends React.Component {
137 ); 154 );
138 } 155 }
139 156
  157 + renderRightButton() {
  158 + if(this.props.hasRightButton) {
  159 + return (
  160 + <MessageIcon
  161 + extraStyle={styles.rightButton}
  162 + msgCount={this.props.msgCount}
  163 + iconTap={this.props.rightButtonClick}
  164 + />);
  165 + } else {
  166 + return null;
  167 + }
  168 + }
  169 +
140 getNavBarBackgroundImage(channel) { 170 getNavBarBackgroundImage(channel) {
141 let img = require('../../images/nav/boy/navbar_bg.png'); 171 let img = require('../../images/nav/boy/navbar_bg.png');
142 switch (parseInt(channel)) { 172 switch (parseInt(channel)) {
@@ -176,6 +206,7 @@ class UserNavBar extends React.Component { @@ -176,6 +206,7 @@ class UserNavBar extends React.Component {
176 206
177 </Image> 207 </Image>
178 {this.renderBackButton()} 208 {this.renderBackButton()}
  209 + {this.renderRightButton()}
179 </Animated.View> 210 </Animated.View>
180 ); 211 );
181 } 212 }
@@ -21,6 +21,7 @@ export default keyMirror({ @@ -21,6 +21,7 @@ export default keyMirror({
21 GO_TO_LIKE_MESSAGE: null, 21 GO_TO_LIKE_MESSAGE: null,
22 GO_TO_POST: null, 22 GO_TO_POST: null,
23 23
  24 +
24 HOME_BNS_REQUEST: null, 25 HOME_BNS_REQUEST: null,
25 HOME_BNS_SUCCESS: null, 26 HOME_BNS_SUCCESS: null,
26 HOME_BNS_FAILURE: null, 27 HOME_BNS_FAILURE: null,
@@ -67,6 +68,9 @@ export default keyMirror({ @@ -67,6 +68,9 @@ export default keyMirror({
67 USER_REPLY_SUCCESS: null, 68 USER_REPLY_SUCCESS: null,
68 USER_REPLY_FAILURE: null, 69 USER_REPLY_FAILURE: null,
69 70
  71 + USER_UNREAD_REQUEST: null,
  72 + USER_UNREAD_SUCCESS: null,
  73 + USER_UNREAD_FAILURE: null,
70 74
71 USER_INFO_REQUEST: null, 75 USER_INFO_REQUEST: null,
72 USER_INFO_SUCCESS: null, 76 USER_INFO_SUCCESS: null,
@@ -12,6 +12,8 @@ import User from '../components/user/User'; @@ -12,6 +12,8 @@ import User from '../components/user/User';
12 import {Actions} from 'react-native-router-flux'; 12 import {Actions} from 'react-native-router-flux';
13 13
14 import * as userActions from '../reducers/user/userActions'; 14 import * as userActions from '../reducers/user/userActions';
  15 +import * as homeActions from '../reducers/home/homeActions';
  16 +
15 import {shouldShowTabBar, shouldHideTabBar} from '../utils/tabBar'; 17 import {shouldShowTabBar, shouldHideTabBar} from '../utils/tabBar';
16 const { 18 const {
17 19
@@ -59,6 +61,7 @@ let SourceType = { @@ -59,6 +61,7 @@ let SourceType = {
59 61
60 const actions = [ 62 const actions = [
61 userActions, 63 userActions,
  64 + homeActions,
62 ]; 65 ];
63 66
64 function mapStateToProps(state) { 67 function mapStateToProps(state) {
@@ -89,7 +92,10 @@ class UserContainer extends React.Component { @@ -89,7 +92,10 @@ class UserContainer extends React.Component {
89 this._onPressComment = this._onPressComment.bind(this); 92 this._onPressComment = this._onPressComment.bind(this);
90 this._onPressLike = this._onPressLike.bind(this); 93 this._onPressLike = this._onPressLike.bind(this);
91 this._onRefresh = this._onRefresh.bind(this); 94 this._onRefresh = this._onRefresh.bind(this);
  95 + this._onPressPost = this._onPressPost.bind(this);
92 this._onEndReached = this._onEndReached.bind(this); 96 this._onEndReached = this._onEndReached.bind(this);
  97 + this._rightButtonClick = this._rightButtonClick.bind(this);
  98 + this._onPressSectionTag = this._onPressSectionTag.bind(this);
93 } 99 }
94 100
95 componentDidMount() { 101 componentDidMount() {
@@ -126,20 +132,27 @@ class UserContainer extends React.Component { @@ -126,20 +132,27 @@ class UserContainer extends React.Component {
126 console.log('avatar'); 132 console.log('avatar');
127 } 133 }
128 134
129 - _onPressComment(url) { 135 + _onPressComment(id) {
130 console.log('comment'); 136 console.log('comment');
  137 + this.props.actions.goToPost(id);
131 } 138 }
132 139
133 - _onPressLike(url) { 140 + _onPressLike(post) {
134 console.log('like'); 141 console.log('like');
  142 + this.props.actions.likeOperation(post);
135 } 143 }
136 144
137 - _onPressReply() { 145 + _onPressReply(id) {
138 console.log('reply'); 146 console.log('reply');
139 } 147 }
140 148
141 - _onPressPosts() {  
142 - console.log('posts'); 149 + _onPressPost(id) {
  150 + console.log('posts id =' + id);
  151 + this.props.actions.goToPost(id);
  152 + }
  153 +
  154 + _onPressSectionTag(section) {
  155 + this.props.actions.goToSection(section, this.props.navigationState.name);
143 } 156 }
144 157
145 _onPressUserAvatar() { 158 _onPressUserAvatar() {
@@ -152,9 +165,6 @@ class UserContainer extends React.Component { @@ -152,9 +165,6 @@ class UserContainer extends React.Component {
152 165
153 (buttonIndex) => { 166 (buttonIndex) => {
154 this._onPressGotoSettingState(buttonIndex); 167 this._onPressGotoSettingState(buttonIndex);
155 - // this.setState({ clicked: BUTTONS[buttonIndex] });  
156 - // this.props.actions.goToStatsPage(USER_GO_TO_SETTING_STATS);  
157 -  
158 }); 168 });
159 169
160 170
@@ -178,7 +188,7 @@ class UserContainer extends React.Component { @@ -178,7 +188,7 @@ class UserContainer extends React.Component {
178 case 2: 188 case 2:
179 { 189 {
180 console.log('编辑个人资料'); 190 console.log('编辑个人资料');
181 - console.log('actions = ' + this.actions); 191 + // console.log('actions = ' + this.actions);
182 this.props.actions.goToStatsPage(GO_TO_SETTING); 192 this.props.actions.goToStatsPage(GO_TO_SETTING);
183 193
184 } 194 }
@@ -219,6 +229,7 @@ class UserContainer extends React.Component { @@ -219,6 +229,7 @@ class UserContainer extends React.Component {
219 this.props.actions.posts(true); 229 this.props.actions.posts(true);
220 this.props.actions.like(true); 230 this.props.actions.like(true);
221 this.props.actions.reply(true); 231 this.props.actions.reply(true);
  232 + this.props.actions.unread();
222 }); 233 });
223 } 234 }
224 235
@@ -238,6 +249,10 @@ class UserContainer extends React.Component { @@ -238,6 +249,10 @@ class UserContainer extends React.Component {
238 }); 249 });
239 } 250 }
240 251
  252 + _rightButtonClick() {
  253 + console.log('message clicked-----------');
  254 + this.props.actions.goToStatsPage(GO_TO_MESSAGE);
  255 + }
241 render() { 256 render() {
242 257
243 let {profile, activeTab, isFetching, ptr, posts: postsData, like: likeData, reply: replyData} = this.props.user; 258 let {profile, activeTab, isFetching, ptr, posts: postsData, like: likeData, reply: replyData} = this.props.user;
@@ -269,12 +284,14 @@ class UserContainer extends React.Component { @@ -269,12 +284,14 @@ class UserContainer extends React.Component {
269 <User 284 <User
270 channel={this.props.app.channel} 285 channel={this.props.app.channel}
271 userInfo={userInfo} 286 userInfo={userInfo}
  287 + profile={profile}
272 list={listData} 288 list={listData}
273 onPressAvatar={this._onPressAvatar} 289 onPressAvatar={this._onPressAvatar}
274 onPressComment={this._onPressComment} 290 onPressComment={this._onPressComment}
275 onPressLike={this._onPressLike} 291 onPressLike={this._onPressLike}
276 onPressReply={this._onPressReply} 292 onPressReply={this._onPressReply}
277 - onPressPosts={this._onPressPosts} 293 + onPressPost={this._onPressPost}
  294 + onPressSectionTag={this._onPressSectionTag}
278 onPressUserAvatar={this._onPressUserAvatar} 295 onPressUserAvatar={this._onPressUserAvatar}
279 onPressBackgroundImg={this._onPressBackgroundImg} 296 onPressBackgroundImg={this._onPressBackgroundImg}
280 onRefresh={this._onRefresh} 297 onRefresh={this._onRefresh}
@@ -284,6 +301,7 @@ class UserContainer extends React.Component { @@ -284,6 +301,7 @@ class UserContainer extends React.Component {
284 isRefreshing={isRefreshing} 301 isRefreshing={isRefreshing}
285 isLoadingMore={isLoadingMore} 302 isLoadingMore={isLoadingMore}
286 onEndReached={this._onEndReached} 303 onEndReached={this._onEndReached}
  304 + rightButtonClick={this._rightButtonClick}
287 /> 305 />
288 </View> 306 </View>
289 ); 307 );
@@ -19,6 +19,7 @@ import user from './user/userReducer'; @@ -19,6 +19,7 @@ import user from './user/userReducer';
19 import userThatNotMe from './userThatNotMe/userThatNotMeReducer'; 19 import userThatNotMe from './userThatNotMe/userThatNotMeReducer';
20 import setting from './setting/settingReducer'; 20 import setting from './setting/settingReducer';
21 import subject from './subject/subjectPostReducer'; 21 import subject from './subject/subjectPostReducer';
  22 +import message from './message/messageReducer';
22 23
23 import { combineReducers } from 'redux'; 24 import { combineReducers } from 'redux';
24 25
@@ -37,6 +38,7 @@ const rootReducer = combineReducers({ @@ -37,6 +38,7 @@ const rootReducer = combineReducers({
37 userThatNotMe, 38 userThatNotMe,
38 setting, 39 setting,
39 subject, 40 subject,
  41 + message,
40 }); 42 });
41 43
42 export default rootReducer; 44 export default rootReducer;
@@ -11,7 +11,7 @@ const { @@ -11,7 +11,7 @@ const {
11 } = require('../../constants/actionTypes').default; 11 } = require('../../constants/actionTypes').default;
12 12
13 const initialState = new InitialState; 13 const initialState = new InitialState;
14 -export default function settingReducer(state = initialState, action) { 14 +export default function message(state = initialState, action) {
15 if (!(state instanceof InitialState)) return initialState.merge(state); 15 if (!(state instanceof InitialState)) return initialState.merge(state);
16 16
17 // switch (action.type) { 17 // switch (action.type) {
@@ -6,7 +6,7 @@ import UserService from '../../services/UserService'; @@ -6,7 +6,7 @@ import UserService from '../../services/UserService';
6 import timeago from '../../utils/timeago'; 6 import timeago from '../../utils/timeago';
7 import {number10KFormater} from '../../utils/numberFormater'; 7 import {number10KFormater} from '../../utils/numberFormater';
8 import PostingService from '../../services/PostingService'; 8 import PostingService from '../../services/PostingService';
9 - 9 +import moment from 'moment';
10 const LIMIT = 10; 10 const LIMIT = 10;
11 11
12 const { 12 const {
@@ -36,6 +36,10 @@ const { @@ -36,6 +36,10 @@ const {
36 USER_INFO_SUCCESS, 36 USER_INFO_SUCCESS,
37 USER_INFO_FAILURE, 37 USER_INFO_FAILURE,
38 38
  39 + USER_UNREAD_REQUEST,
  40 + USER_UNREAD_SUCCESS,
  41 + USER_UNREAD_FAILURE,
  42 +
39 SET_UID, 43 SET_UID,
40 USER_CLEAN, 44 USER_CLEAN,
41 USER_SET_ACTIVE_TAB, 45 USER_SET_ACTIVE_TAB,
@@ -112,17 +116,48 @@ export function replyFailure(error) { @@ -112,17 +116,48 @@ export function replyFailure(error) {
112 }; 116 };
113 } 117 }
114 118
115 -export function userInfo() {  
116 - // return dispatch => {  
117 - // dispatch(postRequest());  
118 - // return new UserService().posts()  
119 - // .then(json => {  
120 - // dispatch(postSuccess(json))  
121 - // })  
122 - // .catch(error => {  
123 - // dispatch(postFailure(error));  
124 - // });  
125 - // }; 119 +export function unreadRequest() {
  120 + return {
  121 + type: USER_UNREAD_REQUEST
  122 + };
  123 +}
  124 +
  125 +export function unreadSuccess(json) {
  126 + return {
  127 + type: USER_UNREAD_SUCCESS,
  128 + payload: json
  129 + };
  130 +}
  131 +
  132 +export function unreadFailure(error) {
  133 + return {
  134 + type: USER_UNREAD_FAILURE,
  135 + payload: error
  136 + };
  137 +}
  138 +
  139 +export function unread() {
  140 + return (dispatch, getState) => {
  141 + let {user} = getState();
  142 +
  143 + dispatch(unreadRequest());
  144 +
  145 + let uid = user.profile.uid;
  146 + return new UserService().unread(uid)
  147 + .then(json => {
  148 +
  149 + let msgCount = json.total ? json.total : 0;
  150 + if (msgCount > 99) {
  151 + msgCount = '99+';
  152 + } else {
  153 + msgCount = msgCount + '';
  154 + }
  155 + dispatch(unreadSuccess(msgCount))
  156 + })
  157 + .catch(error => {
  158 + dispatch(unreadFailure(error));
  159 + });
  160 + };
126 } 161 }
127 162
128 // 获取【我的帖子】数据 163 // 获取【我的帖子】数据
@@ -223,7 +258,7 @@ export function reply(ptr = false) { @@ -223,7 +258,7 @@ export function reply(ptr = false) {
223 return new UserService().reply(uid, lastedTime, limit) 258 return new UserService().reply(uid, lastedTime, limit)
224 .then(json => { 259 .then(json => {
225 260
226 - let payload = parseJson(json); 261 + let payload = parseReply(json);
227 if (!ptr) { 262 if (!ptr) {
228 let oldList = user.reply.list.toJS(); 263 let oldList = user.reply.list.toJS();
229 let list = [...oldList, ...payload.list]; 264 let list = [...oldList, ...payload.list];
@@ -243,7 +278,7 @@ export function goToStatsPage(type) { @@ -243,7 +278,7 @@ export function goToStatsPage(type) {
243 switch (type) { 278 switch (type) {
244 case GO_TO_SETTING: 279 case GO_TO_SETTING:
245 { 280 {
246 - Actions.SettingStats(); 281 + Actions.Setting();
247 return { 282 return {
248 type: GO_TO_SETTING, 283 type: GO_TO_SETTING,
249 } 284 }
@@ -486,6 +521,67 @@ function parseJson(json) { @@ -486,6 +521,67 @@ function parseJson(json) {
486 521
487 export function parseReply(json) { 522 export function parseReply(json) {
488 console.log('========>', json); 523 console.log('========>', json);
  524 + let {lastedTime, list} = json;
  525 + let replies = [];
  526 + list && list.map((item, i) => {
  527 + let {reply, replyTo, blocks, postInfo} = item;
  528 + let desc = '';
  529 + let thumbs = [];
  530 + blocks && blocks.map((item, i) => {
  531 + let contentData = item.contentData ? item.contentData : '';
  532 + if (desc === '' && item.templateKey === 'text') {
  533 + desc = decodeURI(contentData);
  534 + }
  535 +
  536 + if (item.templateKey === 'image') {
  537 + let thumb = {
  538 + src: contentData,
  539 + };
  540 + thumbs.push(thumb);
  541 + }
  542 + });
  543 +
  544 + let self = {
  545 + avatar: reply && reply.headIcon ? reply.headIcon : '',
  546 + backgroundImage: reply && reply.bgPic ? reply.bgPic : '',
  547 + uid: reply && reply.uid ? reply.uid : '',
  548 + name: reply && reply.nickName ? reply.nickName : '',
  549 + signature: reply && reply.signaure ? reply.signature : '',
  550 + };
  551 +
  552 + let replyToUser = {
  553 + avatar: replyTo && replyTo.headIcon ? replyTo.headIcon : '',
  554 + backgroundImage: replyTo && replyTo.bgPic ? replyTo.bgPic : '',
  555 + uid: replyTo && replyTo.uid ? replyTo.uid : '',
  556 + name: replyTo && replyTo.nickName ? replyTo.nickName : '',
  557 + signature: replyTo && replyTo.signaure ? replyTo.signature : '',
  558 + };
  559 +
  560 + let replyContent = {
  561 + thumbs,
  562 + desc,
  563 + }
  564 +
  565 + let createTime = moment(item.createTime, 'x').format('MM.DD.YYYY');
  566 +
  567 + let data = {
  568 + self,
  569 + replyToUser,
  570 + replyContent,
  571 + createTime,
  572 + postInfo,
  573 + }
  574 +
  575 + replies.push(data);
  576 + });
  577 +
  578 + let endReached = replies.length == 0;
  579 +
  580 + return {
  581 + lastedTime,
  582 + list: replies,
  583 + endReached,
  584 + }
489 } 585 }
490 586
491 export function uploadAvatar(assetURL) { 587 export function uploadAvatar(assetURL) {
@@ -19,6 +19,10 @@ const { @@ -19,6 +19,10 @@ const {
19 USER_REPLY_SUCCESS, 19 USER_REPLY_SUCCESS,
20 USER_REPLY_FAILURE, 20 USER_REPLY_FAILURE,
21 21
  22 + USER_UNREAD_REQUEST,
  23 + USER_UNREAD_SUCCESS,
  24 + USER_UNREAD_FAILURE,
  25 +
22 USER_GO_TO_SETTING_STATS, 26 USER_GO_TO_SETTING_STATS,
23 27
24 SYNC_USER_REQUEST, 28 SYNC_USER_REQUEST,
@@ -39,6 +43,9 @@ const { @@ -39,6 +43,9 @@ const {
39 USER_BG_UPLOAD_SUCCESS, 43 USER_BG_UPLOAD_SUCCESS,
40 USER_BG_UPLOAD_FAILURE, 44 USER_BG_UPLOAD_FAILURE,
41 45
  46 + POST_LIKE_REQUEST,
  47 + POST_UNLIKE_REQUEST,
  48 +
42 } = require('../../constants/actionTypes').default; 49 } = require('../../constants/actionTypes').default;
43 50
44 const initialState = new InitialState; 51 const initialState = new InitialState;
@@ -197,8 +204,18 @@ export default function user(state = initialState, action) { @@ -197,8 +204,18 @@ export default function user(state = initialState, action) {
197 break; 204 break;
198 205
199 case USER_CLEAN: 206 case USER_CLEAN:
  207 + {
200 let nextState = initialState.set('profile', state.profile); 208 let nextState = initialState.set('profile', state.profile);
201 return nextState; 209 return nextState;
  210 + }
  211 + break;
  212 +
  213 + case USER_UNREAD_SUCCESS:
  214 + return state.setIn(['profile', 'msgCount'], action.payload);
  215 + break;
  216 +
  217 + case USER_UNREAD_FAILURE:
  218 + return state.setIn(['profile','error'], action.payload);
202 break; 219 break;
203 220
204 case USER_AVATAR_UPLOADING:{ 221 case USER_AVATAR_UPLOADING:{
@@ -236,7 +253,60 @@ export default function user(state = initialState, action) { @@ -236,7 +253,60 @@ export default function user(state = initialState, action) {
236 } 253 }
237 254
238 break; 255 break;
  256 +
  257 + case POST_LIKE_REQUEST: {
  258 + return userCenterNewLikeState(state, action.payload, true);
  259 + }
  260 +
  261 + case POST_UNLIKE_REQUEST: {
  262 + return userCenterNewLikeState(state, action.payload, false);
  263 + }
239 } 264 }
240 265
241 return state; 266 return state;
242 } 267 }
  268 +
  269 +
  270 +function userCenterNewLikeState(state, postId, like) {
  271 +
  272 + let likeState = (list, postId, like) => {
  273 + let index = list.findIndex((item) => {
  274 + return item.get('id') == postId;
  275 + })
  276 + if (index == -1) {
  277 + return list;
  278 + }
  279 +
  280 + let likeCount = 0;
  281 + if (like) {
  282 + likeCount = list.get(index).get('likeCount') + 1;
  283 + } else {
  284 + likeCount = list.get(index).get('likeCount') - 1;
  285 + likeCount = likeCount < 0 ? 0 : likeCount;
  286 + }
  287 +
  288 + let nextList = list.setIn([index, 'isLike'], like)
  289 + .setIn([index, 'likeCount'], likeCount);
  290 + return nextList;
  291 + };
  292 +
  293 + // let nextState = state;
  294 +
  295 + let postsList = likeState(state.posts.list, postId, like);
  296 + let likeList = likeState(state.posts.list, postId, like);
  297 +
  298 + let nextState = state.setIn(['posts', 'list'], postsList)
  299 + .setIn(['like', 'list'], likeList);
  300 +
  301 + return nextState;
  302 + // state.items.map((item, i) => {
  303 + // let hotList = likeState(item.hot.list, postId, like);
  304 + // let newList = likeState(item.new.list, postId, like);
  305 + //
  306 + // item = item.setIn(['hot', 'list'], hotList)
  307 + // .setIn(['new', 'list'], newList);
  308 + // nextState = nextState.setIn(['items', i], item);
  309 + // });
  310 + //
  311 + // return nextState;
  312 +}
@@ -108,4 +108,21 @@ export default class UserService { @@ -108,4 +108,21 @@ export default class UserService {
108 throw(error); 108 throw(error);
109 }); 109 });
110 } 110 }
  111 +
  112 +// 获取未读消息数
  113 + async unread(uid) {
  114 + return await this.api.get({
  115 + url: '',
  116 + body: {
  117 + method: 'app.social.getTotal',
  118 + uid
  119 + }
  120 + })
  121 + .then((json) => {
  122 + return json;
  123 + })
  124 + .catch((error) => {
  125 + throw(error);
  126 + });
  127 + }
111 } 128 }