Authored by 盖剑秋

Comment list of post detail page. reviewed by redding.

@@ -317,6 +317,7 @@ export default function community(platform) { @@ -317,6 +317,7 @@ export default function community(platform) {
317 }, 317 },
318 318
319 homeOnRight(state) { 319 homeOnRight(state) {
  320 + // Actions.SubjectPost();
320 state.dispatch(startEditPost(state.getPostingState())); 321 state.dispatch(startEditPost(state.getPostingState()));
321 }, 322 },
322 /* 323 /*
@@ -8,6 +8,8 @@ import { @@ -8,6 +8,8 @@ import {
8 Image, 8 Image,
9 } from 'react-native' 9 } from 'react-native'
10 10
  11 +import SlicedImage from '../../../common/components/SlicedImage';
  12 +
11 export default class SubjectContent extends Component { 13 export default class SubjectContent extends Component {
12 constructor(props) { 14 constructor(props) {
13 super(props); 15 super(props);
@@ -7,10 +7,12 @@ import { @@ -7,10 +7,12 @@ import {
7 ListView, 7 ListView,
8 StyleSheet, 8 StyleSheet,
9 Image, 9 Image,
  10 + Dimensions,
10 } from 'react-native' 11 } from 'react-native'
11 import UserBrief from '../home/UserBrief'; 12 import UserBrief from '../home/UserBrief';
12 13
13 import SubjectContent from './SubjectContent' 14 import SubjectContent from './SubjectContent'
  15 +import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator';
14 16
15 export default class SubjectPost extends Component { 17 export default class SubjectPost extends Component {
16 constructor(props) { 18 constructor(props) {
@@ -31,7 +33,7 @@ export default class SubjectPost extends Component { @@ -31,7 +33,7 @@ export default class SubjectPost extends Component {
31 <UserBrief 33 <UserBrief
32 avatar={rowData.headIcon} 34 avatar={rowData.headIcon}
33 name={rowData.nickName} 35 name={rowData.nickName}
34 - timeago={this.props.timeagoStr} 36 + timeago={rowData.timeago}
35 isOwner={rowData.LZ} 37 isOwner={rowData.LZ}
36 onPressAvatar={() => { 38 onPressAvatar={() => {
37 this.props.onPressAvatar && this.props.onPressAvatar(); 39 this.props.onPressAvatar && this.props.onPressAvatar();
@@ -61,26 +63,42 @@ export default class SubjectPost extends Component { @@ -61,26 +63,42 @@ export default class SubjectPost extends Component {
61 {this.renderLikeAvatar(rowData.praiseUsers)} 63 {this.renderLikeAvatar(rowData.praiseUsers)}
62 <Text style={styles.likeText}>{rowData.praise + '人点赞'}</Text> 64 <Text style={styles.likeText}>{rowData.praise + '人点赞'}</Text>
63 </View> 65 </View>
64 - <View style={styles.rightContainer}> 66 + <View style={styles.rightLikeContainer}>
65 <Text style={styles.browseText}>{rowData.browse + '人看过'}</Text> 67 <Text style={styles.browseText}>{rowData.browse + '人看过'}</Text>
66 </View> 68 </View>
67 </View> 69 </View>
68 ); 70 );
69 break; 71 break;
  72 + case 'comments':
  73 + return (
  74 + <View style={styles.commentContainer}>
  75 + <UserBrief
  76 + avatar={rowData.headIcon}
  77 + name={rowData.nickName}
  78 + timeago={rowData.timeago}
  79 + isOwner={rowData.LZ}
  80 + onPressAvatar={() => {
  81 + this.props.onPressAvatar && this.props.onPressAvatar();
  82 + }}
  83 + />
  84 + <SubjectContent blocks={rowData.blocks}/>
  85 + <View style={styles.commentSeparator}/>
  86 + </View>
  87 + );
  88 + break;
70 default: 89 default:
71 break; 90 break;
72 } 91 }
73 } 92 }
74 93
75 renderLikeAvatar(avatars) { 94 renderLikeAvatar(avatars) {
76 - console.log(avatars);  
77 if (avatars.length) { 95 if (avatars.length) {
78 avatars.reverse(); 96 avatars.reverse();
79 return ( 97 return (
80 <View style={styles.avatarPannel}> 98 <View style={styles.avatarPannel}>
81 {avatars.map((item, i)=> { 99 {avatars.map((item, i)=> {
82 return ( 100 return (
83 - <Image style={[styles.likeAvatar,{right:10*i}]} source={{uri:item.headIcon}}/> 101 + <Image key={i} style={[styles.likeAvatar,{right:10*i}]} source={{uri:item.headIcon}}/>
84 ); 102 );
85 })} 103 })}
86 </View> 104 </View>
@@ -94,11 +112,28 @@ export default class SubjectPost extends Component { @@ -94,11 +112,28 @@ export default class SubjectPost extends Component {
94 dataSource={this.dataSource.cloneWithRowsAndSections(this.props.dataBlob)} 112 dataSource={this.dataSource.cloneWithRowsAndSections(this.props.dataBlob)}
95 renderRow={this.renderRow} 113 renderRow={this.renderRow}
96 enableEmptySections={true} 114 enableEmptySections={true}
  115 + onEndReached={() => {
  116 + this.props.onEndReached && this.props.onEndReached();
  117 + }}
  118 + renderFooter={()=>{
  119 + if (this.props.endReached) {
  120 + return <LoadMoreIndicator
  121 + isVisible={true}
  122 + text={'没有更多啦'}
  123 + />
  124 + } else {
  125 + return <LoadMoreIndicator
  126 + isVisible={true}
  127 + animating={this.props.isFetching}
  128 + />
  129 + }
  130 + }}
97 /> 131 />
98 ); 132 );
99 } 133 }
100 } 134 }
101 135
  136 +let {width, height} = Dimensions.get('window');
102 const styles = StyleSheet.create({ 137 const styles = StyleSheet.create({
103 container: { 138 container: {
104 top: 0, 139 top: 0,
@@ -134,7 +169,7 @@ const styles = StyleSheet.create({ @@ -134,7 +169,7 @@ const styles = StyleSheet.create({
134 flex: 1, 169 flex: 1,
135 flexDirection: 'row', 170 flexDirection: 'row',
136 alignItems: 'center', 171 alignItems: 'center',
137 - justifyContent: 'flex-end' 172 + justifyContent: 'flex-end',
138 }, 173 },
139 likeAvatar: { 174 likeAvatar: {
140 width: 30, 175 width: 30,
@@ -143,7 +178,7 @@ const styles = StyleSheet.create({ @@ -143,7 +178,7 @@ const styles = StyleSheet.create({
143 }, 178 },
144 likeText: { 179 likeText: {
145 fontSize: 14, 180 fontSize: 14,
146 - left: 10, 181 + left: -10,
147 }, 182 },
148 browseText: { 183 browseText: {
149 fontSize: 14, 184 fontSize: 14,
@@ -156,6 +191,17 @@ const styles = StyleSheet.create({ @@ -156,6 +191,17 @@ const styles = StyleSheet.create({
156 backgroundColor: 'white', 191 backgroundColor: 'white',
157 paddingLeft: 15, 192 paddingLeft: 15,
158 }, 193 },
  194 + commentContainer: {
  195 + paddingTop: 10,
  196 + paddingLeft: 15,
  197 + paddingRight: 15,
  198 + backgroundColor: 'white',
  199 + },
  200 + commentSeparator: {
  201 + backgroundColor: '#a0a0a0',
  202 + height: 0.5,
  203 + width: width-30,
  204 + },
159 headerRight: { 205 headerRight: {
160 flex: 1, 206 flex: 1,
161 flexDirection: 'row', 207 flexDirection: 'row',
@@ -75,8 +75,6 @@ class PostingContainer extends Component{ @@ -75,8 +75,6 @@ class PostingContainer extends Component{
75 if (shouldHideTabBar(this.props.navigationState)) { 75 if (shouldHideTabBar(this.props.navigationState)) {
76 NativeModules.YH_CommunityHelper.hideTabBar(); 76 NativeModules.YH_CommunityHelper.hideTabBar();
77 } 77 }
78 -  
79 -  
80 } 78 }
81 79
82 _onGetBordList() { 80 _onGetBordList() {
@@ -52,16 +52,21 @@ function mapDispatchToProps(dispatch) { @@ -52,16 +52,21 @@ function mapDispatchToProps(dispatch) {
52 class SubjectPostContainer extends Component { 52 class SubjectPostContainer extends Component {
53 constructor(props) { 53 constructor(props) {
54 super(props); 54 super(props);
55 - 55 + this.onEndReached = this.onEndReached.bind(this);
56 } 56 }
57 componentDidMount () { 57 componentDidMount () {
58 this.props.actions.requestPostContent(300); 58 this.props.actions.requestPostContent(300);
59 this.props.actions.requestPostComments(300); 59 this.props.actions.requestPostComments(300);
60 } 60 }
  61 + onEndReached() {
  62 + if (this.props.subject.currentPage>=this.props.subject.totalPages) {
  63 + return;
  64 + }
  65 + this.props.actions.requestPostComments(300, this.props.subject.lastedTime);
  66 + }
61 render() { 67 render() {
62 let {headIcon,nickName} = this.props.subject.authorInfo; 68 let {headIcon,nickName} = this.props.subject.authorInfo;
63 let timeagoStr = timeago().format(this.props.subject.createTime, 'zh_CN'); 69 let timeagoStr = timeago().format(this.props.subject.createTime, 'zh_CN');
64 -  
65 let header = { 70 let header = {
66 headIcon, 71 headIcon,
67 nickName, 72 nickName,
@@ -74,6 +79,7 @@ class SubjectPostContainer extends Component { @@ -74,6 +79,7 @@ class SubjectPostContainer extends Component {
74 praise: this.props.subject.praise, 79 praise: this.props.subject.praise,
75 browse: this.props.subject.browse, 80 browse: this.props.subject.browse,
76 } 81 }
  82 +
77 let dataBlob = { 83 let dataBlob = {
78 header : [header], 84 header : [header],
79 // 'title': [this.props.subject.postsTitle], 85 // 'title': [this.props.subject.postsTitle],
@@ -98,18 +104,19 @@ class SubjectPostContainer extends Component { @@ -98,18 +104,19 @@ class SubjectPostContainer extends Component {
98 ],], 104 ],],
99 105
100 like: [likeData], 106 like: [likeData],
  107 + comments: this.props.subject.commentList.toJS(),
101 }; 108 };
102 return ( 109 return (
103 <View style={styles.container}> 110 <View style={styles.container}>
104 <SubjectPost 111 <SubjectPost
105 dataBlob={dataBlob} 112 dataBlob={dataBlob}
  113 + onEndReached={this.onEndReached}
  114 + endReached={this.props.subject.currentPage>=this.props.subject.totalPages}
  115 + isFetching={this.props.subject.isCommentsFetching}
106 /> 116 />
107 </View> 117 </View>
108 ); 118 );
109 } 119 }
110 - constructDataBlob() {  
111 -  
112 - }  
113 } 120 }
114 121
115 let {width, height} = Dimensions.get('window'); 122 let {width, height} = Dimensions.get('window');
@@ -11,6 +11,7 @@ import Immutable, {List, Record} from 'immutable'; @@ -11,6 +11,7 @@ import Immutable, {List, Record} from 'immutable';
11 import { 11 import {
12 NativeModules, 12 NativeModules,
13 } from 'react-native'; 13 } from 'react-native';
  14 +import timeago from 'timeago.js';
14 15
15 const { 16 const {
16 SUBJECT_CONTENT_REQUEST, 17 SUBJECT_CONTENT_REQUEST,
@@ -74,10 +75,12 @@ export function requestPostComments(postsId, lastedTime) { @@ -74,10 +75,12 @@ export function requestPostComments(postsId, lastedTime) {
74 }; 75 };
75 new PostingService().getPostComments(params) 76 new PostingService().getPostComments(params)
76 .then(json => { 77 .then(json => {
  78 + console.log(json);
77 dispatch(commentsRequestSuccess(json)); 79 dispatch(commentsRequestSuccess(json));
78 80
79 }) 81 })
80 .catch(error => { 82 .catch(error => {
  83 + console.log(error);
81 dispatch(commentsRequestFailure(error)); 84 dispatch(commentsRequestFailure(error));
82 }); 85 });
83 } 86 }
@@ -90,6 +93,32 @@ export function doRequestComments() { @@ -90,6 +93,32 @@ export function doRequestComments() {
90 } 93 }
91 94
92 export function commentsRequestSuccess(json) { 95 export function commentsRequestSuccess(json) {
  96 + let {list} = json;
  97 + let newList = [];
  98 + list && list.map((obj,i)=> {
  99 + let {createTime, reply, replyTo, blocks} = obj;
  100 + let timeagoStr = timeago().format(createTime, 'zh_CN');
  101 + let newBlocks = [];
  102 + blocks && blocks.map((blockItem, i) => {
  103 + let {commentId,content,templateKey,orderBy} = blockItem;
  104 + let newItem = {
  105 + "contentData": content,
  106 + "order": orderBy,
  107 + "templateKey": templateKey,
  108 + };
  109 + newBlocks.push(newItem);
  110 + })
  111 + let newObj={
  112 + timeago: timeagoStr,
  113 + headIcon: reply.headIcon,
  114 + nickName: reply.nickName,
  115 + LZ:false,
  116 + blocks: newBlocks,
  117 + }
  118 + newList.push(newObj);
  119 + })
  120 +
  121 + json.list = newList;
93 return { 122 return {
94 type: SUBJECT_COMMENTS_SUCCESS, 123 type: SUBJECT_COMMENTS_SUCCESS,
95 payload: json, 124 payload: json,
1 -/** 1 + /**
2 * # sunbjectPostInitialState.js 2 * # sunbjectPostInitialState.js
3 * 3 *
4 * 4 *
@@ -43,6 +43,9 @@ let InitialState = Record({ @@ -43,6 +43,9 @@ let InitialState = Record({
43 publishTimeString: '', 43 publishTimeString: '',
44 shareProductSkn: 0, 44 shareProductSkn: 0,
45 LZ: false,//楼主 45 LZ: false,//楼主
  46 + lastedTime: 0,
  47 + totalPages: 0,
  48 + currentPage: 0,
46 commentList: List(),// 49 commentList: List(),//
47 }); 50 });
48 51
@@ -94,9 +94,18 @@ export default function postingReducer(state = initialState, action) { @@ -94,9 +94,18 @@ export default function postingReducer(state = initialState, action) {
94 } 94 }
95 break; 95 break;
96 case SUBJECT_COMMENTS_SUCCESS:{ 96 case SUBJECT_COMMENTS_SUCCESS:{
97 - let existedAry = state.commentList.toJS;  
98 - let nextData = [...existedAry,...action.payload];  
99 - let nextState = state.set('commentList',Immutable.fromJS(nextData)); 97 + let {lastedTime, total, list, pageSize} = action.payload;
  98 + let tailCount = (total%pageSize)>0?1:0;
  99 + let totalPages = total/pageSize + tailCount;
  100 +
  101 + let existedAry = state.commentList.toJS();
  102 + let nextData = [...existedAry,...list];
  103 + let page = state.currentPage;
  104 + page++;
  105 + let nextState = state.set('commentList',Immutable.fromJS(nextData))
  106 + .set('lastedTime',lastedTime)
  107 + .set('totalPages',totalPages)
  108 + .set('currentPage',page);
100 return nextState; 109 return nextState;
101 } 110 }
102 break; 111 break;