Authored by 盖剑秋

Comment post owner in post detai. reviewed by redding.

... ... @@ -317,8 +317,8 @@ export default function community(platform) {
},
homeOnRight(state) {
// Actions.SubjectPost();
state.dispatch(startEditPost(state.getPostingState()));
Actions.SubjectPost();
// state.dispatch(startEditPost(state.getPostingState()));
},
/*
* 自定义导航push动画
... ...
... ... @@ -8,11 +8,34 @@ import {
StyleSheet,
Image,
Dimensions,
Keyboard,
TouchableOpacity,
TouchableHighlight,
Animated,
Easing,
Platform,
TextInput,
} from 'react-native'
import UserBrief from '../home/UserBrief';
import SubjectContent from './SubjectContent'
import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator';
import AssertsPicker from '../posting/AssertsPicker';
let dismissKeyboard = require('dismissKeyboard');
let inViewSource = require('../../images/home/unlike.png');
let outViewSource = require('../../images/home/unlike.png');
let ReplyState = {
replyNone: 0,
replyLZ: 1,
replySomeone: 2,
}
let {width, height} = Dimensions.get('window');
let navbarHeight = (Platform.OS === 'android') ? 50 : 64;
export default class SubjectPost extends Component {
constructor(props) {
... ... @@ -23,6 +46,187 @@ export default class SubjectPost extends Component {
});
this.renderRow = this.renderRow.bind(this);
this.renderLikeAvatar = this.renderLikeAvatar.bind(this);
this.state = {
contentInputHeight: new Animated.Value(0),
imageState: 0,
replyState: ReplyState.replyNone,
}
this.currentReplyState = ReplyState.replyLZ;
this.boardInView=false;
this.boardHeight=257;
this.boardSelectionHeight = 257;
this.showImagePannel = this.showImagePannel.bind(this);
this.blurAll = this.blurAll.bind(this);
this.renderToolContainer = this.renderToolContainer.bind(this);
this.someOneToReply = '';
}
componentDidMount(){
this.setState({contentInputHeight: new Animated.Value(height-navbarHeight-0.5),replyState: ReplyState.replyNone});
Keyboard.addListener('keyboardWillChangeFrame',(event)=>{
if (this.boardInView) {
return;
}
let kbdHeight = height - event.endCoordinates.screenY;
this.boardHeight = kbdHeight>0?kbdHeight:250;
this.boardSelectionHeight=kbdHeight;
let targetHeight = height-navbarHeight-0.5- kbdHeight;
this.stretchContentInputToHeight(targetHeight, event.duration);
});
}
stretchContentInputToHeight(newHeight, anmDuration) {
Animated.timing(this.state.contentInputHeight, {
toValue: newHeight,
duration:anmDuration,
easing:Easing.keyboard,
}).start();
}
blurAll() {
this.setState({imageState:0, replyState:ReplyState.replyNone});
this.currentReplyState = ReplyState.replyLZ;
if (this.boardInView) {
this.boardInView = false;
let targetHeight = height-navbarHeight-0.5;
this.stretchContentInputToHeight(targetHeight, 250);
}
dismissKeyboard();
}
showImagePannel() {
this.boardInView= true;
this.setState({boardState:0,imageState:this.boardSelectionHeight});
dismissKeyboard();
let targetHeight = height-navbarHeight-0.5- this.boardHeight;
this.stretchContentInputToHeight(targetHeight, 250);
}
render() {
return(
<View style={styles.container}>
<Animated.View
style={[styles.contentInputContainer,{height:this.state.contentInputHeight}]}
>
<ListView
style={styles.container}
dataSource={this.dataSource.cloneWithRowsAndSections(this.props.dataBlob)}
renderRow={this.renderRow}
enableEmptySections={true}
onEndReached={() => {
this.props.onEndReached && this.props.onEndReached();
}}
renderFooter={()=>{
if (this.props.endReached) {
return <LoadMoreIndicator
isVisible={true}
text={'没有更多啦'}
/>
} else {
return <LoadMoreIndicator
isVisible={true}
animating={this.props.isFetching}
/>
}
}}
/>
{this.renderToolContainer(this.state.replyState)}
</Animated.View>
<AssertsPicker
style={[styles.boardSelectionContainer,{height:this.state.imageState,}]}
opacityToHide={this.state.imageState}
assets={this.props.assets}
assetsSelected={this.props.assetsSelected}
/>
</View>
);
}
renderToolContainer() {
let iconSouce = (this.state.replyState === ReplyState.replyNone)?require('../../images/home/like.png'):require('../../images/pic1.png');
switch (this.state.replyState) {
case ReplyState.replyNone: {
return (
<View style={styles.toolContainer}>
<Image style={styles.imgIcon} source={iconSouce}/>
<TouchableOpacity style={styles.imgButton} onPress={this.showImagePannel}>
</TouchableOpacity>
<View style={styles.rightContainer}>
<TouchableOpacity
style={styles.lzContainer}
onPress={
()=>{
this.setState({replyState: this.currentReplyState})
}
}
>
<Text style={styles.fakePlaceHolder}>回复楼主:</Text>
<Text style={styles.replyCountText}>{'已有'+this.props.commentCount+'条回复'}</Text>
</TouchableOpacity>
</View>
</View>
);
}
break;
case ReplyState.replyLZ: {
return (
<View style={styles.toolContainer}>
<Image style={styles.imgIcon} source={iconSouce}/>
<TouchableOpacity style={styles.imgButton} onPress={this.showImagePannel}>
</TouchableOpacity>
<TouchableOpacity style={styles.keyboardIcon} onPress={this.blurAll}>
<Image source={require('../../images/jianpan1.png')} />
</TouchableOpacity>
<View style={[styles.rightContainer]}>
<TextInput
ref='textInput'
style={styles.replyTextInput}
placeholderTextColor='#b0b0b0'
placeholder='回复楼主'
multiline={true}
autoCapitalize={'none'}
autoCorrect={false}
autoFocus={true}
/>
<Text style={styles.submitText}>发送</Text>
</View>
</View>
);
}
break;
case ReplyState.replySomeone: {
return (
<View style={styles.toolContainer}>
<TouchableOpacity style={styles.imgIcon} onPress={this.showImagePannel}>
<Image source={require('../../images/pic1.png')}/>
</TouchableOpacity>
<TouchableOpacity style={styles.keyboardIcon} onPress={this.blurAll}>
<Image style={styles.keyboardIcon} source={require('../../images/jianpan1.png')} />
</TouchableOpacity>
<View style={styles.rightContainer}>
<Text
style={styles.boardText}
onPress={this.showBoardPannel}
>
{this.props.selectedBoard}
</Text>
</View>
</View>
);
}
break;
default:
break;
}
}
renderRow(rowData, sectionId) {
... ... @@ -71,7 +275,15 @@ export default class SubjectPost extends Component {
break;
case 'comments':
return (
<View style={styles.commentContainer}>
<TouchableHighlight
style={styles.commentContainer}
onPress={
()=> {
this.replySomeone(rowData.nickName);
}
}
>
<View>
<UserBrief
avatar={rowData.headIcon}
name={rowData.nickName}
... ... @@ -84,6 +296,7 @@ export default class SubjectPost extends Component {
<SubjectContent blocks={rowData.blocks}/>
<View style={styles.commentSeparator}/>
</View>
</TouchableHighlight>
);
break;
default:
... ... @@ -91,6 +304,10 @@ export default class SubjectPost extends Component {
}
}
replyToSomeOne(someOne) {
}
renderLikeAvatar(avatars) {
if (avatars.length) {
avatars.reverse();
... ... @@ -105,35 +322,8 @@ export default class SubjectPost extends Component {
);
}
}
render() {
return(
<ListView
style={styles.container}
dataSource={this.dataSource.cloneWithRowsAndSections(this.props.dataBlob)}
renderRow={this.renderRow}
enableEmptySections={true}
onEndReached={() => {
this.props.onEndReached && this.props.onEndReached();
}}
renderFooter={()=>{
if (this.props.endReached) {
return <LoadMoreIndicator
isVisible={true}
text={'没有更多啦'}
/>
} else {
return <LoadMoreIndicator
isVisible={true}
animating={this.props.isFetching}
/>
}
}}
/>
);
}
}
let {width, height} = Dimensions.get('window');
const styles = StyleSheet.create({
container: {
top: 0,
... ... @@ -225,4 +415,100 @@ const styles = StyleSheet.create({
marginRight:15,
fontWeight:'100',
},
toolContainer: {
flexDirection: 'row',
height: 41,
borderColor: '#a0a0a0',
borderBottomWidth:0.5,
borderTopWidth:0.5,
alignItems:'center',
backgroundColor: 'white',
paddingLeft: 15,
paddingRight: 15,
},
imgIcon: {
left:0,
width:19,
height:19,
right: 16,
},
imgButton: {
position:'absolute',
width:19,
height:19,
left: 15,
top: 11,
},
keyboardIcon: {
left: 10,
width:20,
height:20,
right: 8,
},
rightContainer: {
left: 18,
flex: 1,
flexDirection: 'row',
height:41,
alignItems:'center',
paddingRight: 15,
},
replyTextInput: {
flex: 1,
paddingLeft: 10,
paddingRight: 10,
paddingTop: 9,
paddingBottom: 9,
color: 'black',
height: 33,
top: 4,
borderRadius:2,
borderWidth: 0.5,
borderColor: '#a0a0a0',
fontSize: 14,
backgroundColor:'white',
},
submitText: {
borderRadius: 2,
borderWidth: 0.5,
borderColor: '#a0a0a0',
fontSize: 14,
alignItems:'center',
textAlign:'center',
height: 33,
width: 50,
left: 10,
paddingTop: 10,
color: "#b0b0b0"
},
lzContainer: {
flex: 1,
height: 33,
borderRadius:2,
borderWidth: 0.5,
borderColor: '#a0a0a0',
alignItems:'center',
flexDirection: 'row',
paddingLeft: 10,
paddingRight: 10,
},
fakePlaceHolder: {
flex: 1,
fontSize:14,
textAlign: 'left',
paddingTop: 3,
color: '#b0b0b0',
height: 32,
paddingTop: 9,
},
replyCountText: {
flex: 1,
fontSize:14,
textAlign: 'right',
paddingTop: 3,
color: '#b0b0b0',
paddingTop: 9,
height: 32,
}
});
... ...
... ... @@ -105,4 +105,5 @@ export default keyMirror({
SUBJECT_COMMENTS_REQUEST: null,
SUBJECT_COMMENTS_SUCCESS: null,
SUBJECT_COMMENTS_FAILURE: null,
SUBJECT_ASSETS_SELECTED: null,
});
... ...
... ... @@ -6,6 +6,8 @@ import {
StyleSheet,
Dimensions,
Platform,
InteractionManager,
NativeModules,
} from 'react-native';
import {bindActionCreators} from 'redux';
... ... @@ -13,10 +15,12 @@ import {connect} from 'react-redux';
import {Map} from 'immutable';
import timeago from 'timeago.js';
import Immutable, {List, Record} from 'immutable';
import {Actions} from 'react-native-router-flux';
import SubjectPost from '../components/subjectPost/SubjectPost';
import * as subjectPostActions from '../reducers/subject/subjectPostActions';
import {shouldShowTabBar, shouldHideTabBar} from '../utils/tabBar';
const actions = [
... ... @@ -53,17 +57,36 @@ class SubjectPostContainer extends Component {
constructor(props) {
super(props);
this.onEndReached = this.onEndReached.bind(this);
this.assetsSelected = this.assetsSelected.bind(this);
}
componentDidMount () {
componentDidMount() {
InteractionManager.runAfterInteractions(() => {
this.props.actions.requestPostContent(300);
this.props.actions.requestPostComments(300);
});
if (shouldHideTabBar(this.props.navigationState)) {
NativeModules.YH_CommunityHelper.hideTabBar();
}
}
componentWillUnmount() {
if (shouldShowTabBar(this.props.navigationState)) {
Actions.refresh({key: 'Home', showNativeTabBar: true});
}
}
onEndReached() {
if (this.props.subject.currentPage>=this.props.subject.totalPages) {
return;
}
this.props.actions.requestPostComments(300, this.props.subject.lastedTime);
}
assetsSelected(assets) {
this.props.actions.assetsSelected(assets);
}
render() {
let {headIcon,nickName} = this.props.subject.authorInfo;
let timeagoStr = timeago().format(this.props.subject.createTime, 'zh_CN');
... ... @@ -113,6 +136,9 @@ class SubjectPostContainer extends Component {
onEndReached={this.onEndReached}
endReached={this.props.subject.currentPage>=this.props.subject.totalPages}
isFetching={this.props.subject.isCommentsFetching}
assetsSelected={this.assetsSelected}
assets={this.props.subject.assets.toJS()}
commentCount={this.props.subject.commentCount}
/>
</View>
);
... ...
... ... @@ -21,6 +21,7 @@ const {
SUBJECT_COMMENTS_REQUEST,
SUBJECT_COMMENTS_SUCCESS,
SUBJECT_COMMENTS_FAILURE,
SUBJECT_ASSETS_SELECTED,
} = require('../../constants/actionTypes').default;
export function requestPostContent(postsId) {
... ... @@ -131,3 +132,10 @@ export function commentsRequestFailure(error) {
payload: error,
}
}
export function assetsSelected(assets) {
return {
type: SUBJECT_ASSETS_SELECTED,
payload: assets,
}
}
... ...
... ... @@ -46,7 +46,10 @@ let InitialState = Record({
lastedTime: 0,
totalPages: 0,
currentPage: 0,
commentCount: 0,
commentList: List(),//
assets: List(),//回复里面的图片。
});
export default InitialState;
... ...
... ... @@ -20,6 +20,7 @@ const {
SUBJECT_COMMENTS_REQUEST,
SUBJECT_COMMENTS_SUCCESS,
SUBJECT_COMMENTS_FAILURE,
SUBJECT_ASSETS_SELECTED,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
... ... @@ -105,7 +106,8 @@ export default function postingReducer(state = initialState, action) {
let nextState = state.set('commentList',Immutable.fromJS(nextData))
.set('lastedTime',lastedTime)
.set('totalPages',totalPages)
.set('currentPage',page);
.set('currentPage',page)
.set('commentCount',total);
return nextState;
}
break;
... ... @@ -118,6 +120,12 @@ export default function postingReducer(state = initialState, action) {
let nextState = state.set('isCommentsFetching', false).set('commentsError', action.payload);
return nextState;
break;
case SUBJECT_ASSETS_SELECTED: {
let data = action.payload||[];
let nextState = state.set('assets',Immutable.fromJS(data));
return nextState;
}
break;
default:
return initialState;
break;
... ...