Authored by 王钱钧

添加社区个人中心代码。code review by 于良

... ... @@ -7,6 +7,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import UserCenterTop from './user/UserCenterTop';
import CommunityList from './CommonComp/CommunityList';
import ReplyList from './user/ReplyList';
import ParallaxView from './CommonComp/ParallaxView';
... ... @@ -18,6 +19,7 @@ const {
Dimensions,
StyleSheet,
PanResponder,
ActionSheetIOS,
} = ReactNative;
export default class User extends React.Component {
... ... @@ -86,8 +88,8 @@ export default class User extends React.Component {
blocks: ImmutablePropTypes.listOf(
ImmutablePropTypes.contains({
commentId: React.PropTypes.string,
orderBy: React.PropTypes.string,
commentId: React.PropTypes.number,
orderBy: React.PropTypes.number,
content: React.PropTypes.string,
templateKey: React.PropTypes.string.isRequired,
})
... ... @@ -95,20 +97,20 @@ export default class User extends React.Component {
reply: ImmutablePropTypes.contains({
headIcon: React.PropTypes.string,
uid: React.PropTypes.string,
uid: React.PropTypes.number,
name: React.PropTypes.string,
}),
replyTo: ImmutablePropTypes.contains({
headIcon: React.PropTypes.string,
uid: React.PropTypes.string,
uid: React.PropTypes.number,
name: React.PropTypes.string,
}),
id: React.PropTypes.string,
postId: React.PropTypes.string,
createTime: React.PropTypes.string.isRequired,
authorUid: React.PropTypes.string,
id: React.PropTypes.number,
postId: React.PropTypes.number,
createTime: React.PropTypes.number.isRequired,
authorUid: React.PropTypes.number,
}),
... ... @@ -117,9 +119,12 @@ export default class User extends React.Component {
}),
onPressAvatar: React.PropTypes.func,
onPressUserAvatar: React.PropTypes.func,
onPressComment: React.PropTypes.func,
onPressLike: React.PropTypes.func,
onPressPosts: React.PropTypes.func,
};
... ... @@ -127,12 +132,25 @@ export default class User extends React.Component {
super (props);
}
_showModifyUserInfoActionSheet() {
}
_showModifyBackgroundImgActionSheet() {
}
render() {
return (
<View style={styles.container}>
<UserCenterTop/>
<UserCenterTop
userInfo={this.props.dataBlob.userInfo}
onPressUserAvatar={this.props.onPressUserAvatar}
onPressBackgroundImg={this.props.onPressBackgroundImg}
/>
<ScrollableTabView style={styles.bottom}>
<CommunityList
... ... @@ -165,17 +183,17 @@ export default class User extends React.Component {
/>
<CommunityList
<ReplyList
tabLabel="我的回复"
jsonData={this.props.dataBlob.reply}
onPressAvatar={(url) => {
this.props.onPressAvatar && this.props.onPressAvatar(url);
}}
onPressComment={(url) => {
this.props.onPressComment && this.props.onPressComment(url);
onPressReply={(url) => {
this.props.onPressReply && this.props.onPressReply(url);
}}
onPressLike={(url) => {
this.props.onPressLike && this.props.onPressLike(url);
onPressPosts={(url) => {
this.props.onPressPosts && this.props.onPressPosts(url);
}}
/>
... ...
'use strict';
import React from 'react';
import ReactNative from 'react-native';
import ImmutablePropTypes from 'react-immutable-proptypes';
import UserBrief from '../home/UserBrief';
// import Thumbs from './Thumbs';
// import SectionItem from './SectionItem';
// import NumberButton from './NumberButton';
const {
View,
Text,
Image,
TouchableOpacity,
StyleSheet,
Dimensions,
} = ReactNative;
export default class ReplyCell extends React.Component {
static propTypes = {
data: ImmutablePropTypes.contains({
id: React.PropTypes.number,
postId: React.PropTypes.number,
createTime: React.PropTypes.number.isRequired,
authorUid: React.PropTypes.number,
// 帖子
postInfo: ImmutablePropTypes.contains({
title: React.PropTypes.string,
type: React.PropTypes.string.isRequired,
}),
// 回复的内容
blocks: ImmutablePropTypes.listOf(
ImmutablePropTypes.contains({
commentId: React.PropTypes.number,
orderBy: React.PropTypes.number,
content: React.PropTypes.string,
templateKey: React.PropTypes.string.isRequired,
})
),
// 我的信息
reply: ImmutablePropTypes.contains({
headIcon: React.PropTypes.string,
uid: React.PropTypes.number,
name: React.PropTypes.string,
}),
// 被回复者信息
replyTo: ImmutablePropTypes.contains({
headIcon: React.PropTypes.string,
uid: React.PropTypes.number,
name: React.PropTypes.string,
}),
onPressAvatar: React.PropTypes.func,
onPressReply: React.PropTypes.func,
onPressPosts: React.PropTypes.func,
}),
// TODO 添加点击事件
};
constructor(props) {
super(props);
}
render() {
let data = this.props.data.toJS();
let {
id,
postId,
createTime,
authorUid,
postInfo,
blocks,
reply,
replyTo,
} = data;
return (
<View style={styles.container}>
<View style={styles.topContainer}>
<UserBrief
avatar={reply.headIcon}
name={reply.name}
timeago={createTime.toString()}
// isOwner={isOwner}
onPressAvatar={() => {
this.props.onPressAvatar && this.props.onPressAvatar();
}}
/>
</View>
<View style={styles.reply}>
<Text style={[styles.text,{fontSize:14}]}>
回复
<Text style={{color: '#4a90e2', fontSize: 14,}}
onPress={() => {
this.props.onPressReply && this.props.onPressReply();
}}
>
小草莓
</Text>
:如果你无法表单房间诶哦我就佛大发了瓦解偶发的拉萨减肥劳动局撒了附件二范德萨范德萨
</Text>
</View>
<View style={styles.lineInCell}/>
<View style={styles.bottomContainer}>
<Text
style={[styles.text,{margin:15, fontSize: 18}]}
numberOfLines={1}
onPress={() => {
this.props.onPressPosts && this.props.onPressPosts();
}}
>
帖子:港南爱上米彩妆,看叫啥呢我发的是fdsafdsafdsafdasfd剪短发搜富哦为福建省的
</Text>
</View>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
backgroundColor:'white',
flexDirection:'column',
},
topContainer: {
margin: 15,
},
reply: {
// backgroundColor: 'red',
marginLeft: 15,
marginRight: 15,
},
text: {
fontFamily: 'Helvetica Light',
},
bottomContainer: {
backgroundColor:'white'
},
lineInCell: {
height: 1,
marginLeft: 15,
marginTop: 15,
// marginBottom: 15,
backgroundColor: '#e0e0e0',
},
replyTouch: {
backgroundColor: 'red',
// padding: 0,
width:80,
height: 40,
},
});
... ...
'use strict';
import React from 'react';
import ReactNative from 'react-native';
import ReplyCell from './ReplyCell';
const {
View,
Text,
Image,
ListView,
TouchableOpacity,
Platform,
StyleSheet,
Dimensions,
} = ReactNative;
export default class ReplyList extends React.Component {
constructor(props) {
super(props);
this._renderRow = this._renderRow.bind(this);
this._renderSeparator = this._renderSeparator.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
sectionHeaderHasChanged: (s1, s2) => !Immutable.is(s1, s2),
});
}
_renderRow(rowData, sectionID, rowID, highlightRow) {
return (
<ReplyCell
key={sectionID + rowID}
data={rowData}
// onPressPost={(url) => {
// this.props.onPressPost && this.props.onPressPost(url);
// }}
onPressAvatar={(url) => {
this.props.onPressAvatar && this.props.onPressAvatar(url);
}}
onPressReply={(url) => {
this.props.onPressReply && this.props.onPressReply(url);
}}
onPressPosts={(url) => {
this.props.onPressPosts && this.props.onPressPosts(url);
}}
// onPressLike={(url) => {
// this.props.onPressLike && this.props.onPressLike(url);
// }}
/>
);
}
_renderSeparator(sectionID, rowID, adjacentRowHighlighted) {
return (
<View key={'separator' + sectionID + rowID} style={styles.separator}/>
);
}
render() {
return (
<ListView
dataSource={this.dataSource.cloneWithRows(this.props.jsonData)}
renderRow={this._renderRow}
renderSectionHeader={this._renderSectionHeader}
renderSeparator={this._renderSeparator}
enableEmptySections={true}
/>
);
}
}
let styles = StyleSheet.create({
separator: {
height: 0.5,
backgroundColor: '#e0e0e0',
},
});
... ...
... ... @@ -2,6 +2,8 @@
import React from 'react';
import ReactNative from 'react-native';
import ImmutablePropTypes from 'react-immutable-proptypes';
const {
View,
... ... @@ -10,22 +12,75 @@ const {
StyleSheet,
Dimensions,
Platform,
TouchableOpacity,
TouchableHighlight,
} = ReactNative;
export default class UserCenterTop extends React.Component {
render() {
static propTypes = {
backgroundImage: React.PropTypes.string,
avatar: React.PropTypes.string,
name: React.PropTypes.string.isRequired,
sign: React.PropTypes.string,
onPressUserAvatar: React.PropTypes.func,
onPressBackgroundImg: React.PropTypes.func,
};
constructor(props) {
super (props);
}
render() {
console.log('userinfo = ' + this.props.userInfo);
let data = this.props.userInfo;
let {backgroundImage, avatar, name, sign,} = data;
return (
<View style={styles.container}>
<Image style={styles.backgroundImage}
source={require('../../images/user-bg.png')}
<TouchableHighlight
underlayColor={'transparent'}
onPress={() => {
this.props.onPressBackgroundImg && this.props.onPressBackgroundImg();
}}
>
<Image style={styles.avatarImage}
source={require('../../images/avatar-default.png')}
<Image
style={styles.backgroundImage}
source={backgroundImage}
>
<TouchableOpacity
onPress={() => {
this.props.onPressUserAvatar && this.props.onPressUserAvatar();
}}
>
<Image
style={styles.avatarImage}
source={avatar}
>
</Image>
</TouchableOpacity>
<Text
style={styles.name}
>
{name}
</Text>
<Text
style={styles.sign}
>
{sign}
</Text>
</Image>
</Image>
</TouchableHighlight>
</View>
);
... ... @@ -39,20 +94,20 @@ let styles = StyleSheet.create({
container: {
height: 244,
backgroundColor: 'green',
backgroundColor: 'transparent',
},
backgroundImage: {
// top: 0,
// flex: 1,
// flexDirection: 'row',
// justifyContent: 'center',
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
// alignItems: 'center'
},
avatarImage: {
top: 79,
marginTop: 50,
width: 74,
height: 74,
borderRadius: 37,
... ... @@ -61,12 +116,23 @@ let styles = StyleSheet.create({
backgroundColor: 'white'
},
userName: {
name: {
color: 'white',
textAlign: 'center',
margin: 15,
marginBottom:10,
// backgroundColor:'red',
fontSize: 14,
fontFamily: 'Helvetica Light',
},
userSign: {
sign: {
color: 'white',
textAlign: 'center',
// margin: 15,
// backgroundColor:'red',
fontSize: 12,
fontFamily: 'Helvetica Light',
}
});
... ...
... ... @@ -22,6 +22,9 @@ export default keyMirror({
USER_REPLY_SUCCESS: null,
USER_REPLY_FAILURE: null,
USER_GO_TO_SETTING_STATS: null, // 个人中心页面跳转
POSTING_BOARD_REQUEST: null,
POSTING_BOARD_SUCCESS: null,
POSTING_BOARD_FAILURE: null,
... ...
... ... @@ -13,12 +13,31 @@ import User from '../components/User';
import * as userActions from '../reducers/user/userActions';
const {
USER_POSTS_REQUEST,
USER_POSTS_SUCCESS,
USER_POSTS_FAILURE,
USER_LIKE_REQUEST,
USER_LIKE_SUCCESS,
USER_LIKE_FAILURE,
USER_REPLY_REQUEST,
USER_REPLY_SUCCESS,
USER_REPLY_FAILURE,
USER_GO_TO_SETTING_STATS,
} = require('../constants/actionTypes').default;
const {
StatusBar,
ScrollView,
View,
StyleSheet,
Dimensions,
Platform,
ActionSheetIOS,
} = ReactNative;
const actions = [
... ... @@ -46,7 +65,7 @@ function mapDispatchToProps(dispatch) {
class UserContainer extends React.Component {
constructor(props) {
super(props);
this._onPressUserAvatar = this._onPressUserAvatar.bind(this);
}
... ... @@ -59,6 +78,7 @@ class UserContainer extends React.Component {
}
// private method
_onPressAvatar(url) {
console.log('avatar');
}
... ... @@ -71,15 +91,94 @@ class UserContainer extends React.Component {
console.log('like');
}
_onPressReply() {
console.log('reply');
}
_onPressPosts() {
console.log('posts');
}
_onPressUserAvatar() {
const BUTTONS = ['拍照', '从相册选择', '编辑个人资料', '取消'];
ActionSheetIOS.showActionSheetWithOptions({
options: BUTTONS,
cancelButtonIndex: 3,
},
(buttonIndex) => {
// _onPressGotoSettingState(buttonIndex);
// this.setState({ clicked: BUTTONS[buttonIndex] });
this.props.actions.goToStatsPage(USER_GO_TO_SETTING_STATS);
});
}
_onPressGotoSettingState(buttonIndex) {
console.log('go to setting state');
switch (buttonIndex) {
case 0:
{
console.log('拍照');
}
break;
case 1:
{
console.log('从相册中选择');
}
break;
case 2:
{
console.log('编辑个人资料');
console.log('actions = ' + this.actions);
this.actions.goToStatsPage(USER_GO_TO_SETTING_STATS);
}
break;
default:
}
}
_onPressBackgroundImg() {
const BUTTONS = ['拍照', '从相册选择', '取消'];
ActionSheetIOS.showActionSheetWithOptions({
options: BUTTONS,
cancelButtonIndex: 2,
},
(buttonIndex) => {
switch (buttonIndex) {
case 0:
{
console.log('拍照');
}
break;
case 1:
{
console.log('从相册中选择');
}
break;
default:
}
});
}
_fetchData() {
// this.props.actions.userInfo();
// this.props.actions.posts();
}
render() {
let userInfo = {
avatar: require('../images/avatar-default.png'),
userName:'Arthur',
name:'Arthur',
sign:'Hello, Bro',
bgImage: require('../images/user-bg.png'),
backgroundImage: require('../images/user-bg.png'),
};
let posts = [
... ... @@ -160,12 +259,86 @@ class UserContainer extends React.Component {
},
];
let like = [
{
avatar: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
name: 'Arthur',
timeago: '2小时前',
isOwner: false,
isTop: true,
isLike: true,
title: 'Yoho!Buy特邀摄影师大赛开始报名啦!',
desc: 'MADNESS作为“六叔”余文乐的个人品牌,经过几个季度的产品表现,相信大家都知道这并不是玩票性质,而是余文乐在做心中的街头品牌。此番MADNESS正式迎来2016春夏的开季,以Los Angeles作为拍摄地点,延续余文乐一直喜欢的简约风格',
thumbs: [
{
url: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
},
{
url: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
},
{
url: 'https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240',
}
],
section: '永恒的潮流',
commentCount: 123,
likeCount: 45678,
url: 'https://www.baidu.com'
}];
let reply = [
{
"postInfo": {
"title": "害怕抢不到NMD?别担心,至少他们都不是你的对手!",
"type": "text"
},
"createTime": 1467189316,
"authorUid": 0,
"blocks": [
{
"commentId": 52,
"orderBy": 0,
"content": "永远的18岁!!!",
"templateKey": "text"
},
{
"commentId": 52,
"orderBy": 0,
"content": "http://img12.static.yhbimg.com/goodsimg/2016/06/06/05/02e8b4a63c0101b1a1a8f04b53d817b9d4.png",
"templateKey": "image"
},
{
"commentId": 52,
"orderBy": 1,
"content": "http://img12.static.yhbimg.com/goodsimg/2016/06/06/05/02e8b4a63c0101b1a1a8f04b53d817b9d5.png",
"templateKey": "image"
}
],
"replyTo": {
"headIcon": "https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240",
"uid": 8050829,
"name": "petch"
},
"id": 52,
"postId": 80,
"reply": {
"headIcon": "https://img11.static.yhbimg.com/yhb-img01/2016/06/28/11/01f429fffdff555ed0c141a5ec2b4fd421.jpg?imageView2/2/w/640/h/240",
"uid": 8050829,
"name": "petch"
},
"status": 0
}
];
let dataBlob = {
userInfo: Immutable.fromJS(userInfo).toObject(),
// notice: Immutable.fromJS(notice).toObject(),
// section: Immutable.fromJS(section).toObject(),
posts: Immutable.fromJS(posts).toArray(),
like: Immutable.fromJS(like).toArray(),
reply: Immutable.fromJS(reply).toArray(),
};
return (
... ... @@ -179,16 +352,15 @@ class UserContainer extends React.Component {
onPressAvatar={this._onPressAvatar}
onPressComment={this._onPressComment}
onPressLike={this._onPressLike}
onPressReply={this._onPressReply}
onPressPosts={this._onPressPosts}
onPressUserAvatar={this._onPressUserAvatar}
onPressBackgroundImg={this._onPressBackgroundImg}
/>
</View>
);
}
// private method
_fetchData() {
// this.props.actions.userInfo();
// this.props.actions.posts();
}
}
let {width, height} = Dimensions.get('window');
... ...
... ... @@ -18,6 +18,8 @@ const {
USER_REPLY_SUCCESS,
USER_REPLY_FAILURE,
USER_GO_TO_SETTING_STATS,
} = require('../../constants/actionTypes').default;
export function postRequest() {
... ... @@ -135,43 +137,18 @@ export function reply() {
};
}
//测试数据
let postsTestData = {
sum: '100',
currentPage: 1,
pageCount: 1,
list: [
{
name: 'Arthur',
title: '这是一篇文章',
brief: '简介',
topic: '复古市集会',
imgs: ['https://facebook.github.io/react/img/logo_og.png'],
},
{
name: 'Arthur',
title: '这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章',
brief: '简介',
imgs: ['https://facebook.github.io/react/img/logo_og.png', 'https://facebook.github.io/react/img/logo_og.png'],
},
{
name: 'Arthur',
title: '这是一篇文章',
brief: '简介这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章这是一篇文章',
imgs: ['https://facebook.github.io/react/img/logo_og.png','https://facebook.github.io/react/img/logo_og.png', 'https://facebook.github.io/react/img/logo_og.png'],
},
{
name: 'Arthur',
title: '这是一篇文章',
brief: '简介',
imgs: ['https://facebook.github.io/react/img/logo_og.png','https://facebook.github.io/react/img/logo_og.png', 'https://facebook.github.io/react/img/logo_og.png'],
},
// 页面跳转
export function goToStatsPage(type) {
switch (type) {
case USER_GO_TO_SETTING_STATS:
{
name: 'Arthur',
title: '这是一篇文章',
// brief: '简介',
imgs: ['https://facebook.github.io/react/img/logo_og.png','https://facebook.github.io/react/img/logo_og.png', 'https://facebook.github.io/react/img/logo_og.png'],
},
]
Actions.SettingStats();
return {
type: USER_GO_TO_SETTING_STATS,
}
}
break;
default:
}
}
... ...
... ... @@ -19,6 +19,8 @@ const {
USER_REPLY_SUCCESS,
USER_REPLY_FAILURE,
USER_GO_TO_SETTING_STATS,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
... ... @@ -62,6 +64,9 @@ export default function user(state = initialState, action) {
return nextState;
}
case USER_GO_TO_SETTING_STATS:
return state;
default:
}
... ...