'use strict' import React, {Component} from 'react'; import { View, Text, ListView, StyleSheet, Image, Dimensions, Keyboard, TouchableOpacity, TouchableHighlight, Animated, Easing, Platform, TextInput, Alert, NativeModules, } from 'react-native' import UserBrief from '../home/UserBrief'; import PostingService from '../../services/PostingService'; import SPHeaderCell from './SPHeaderCell'; import SubjectContent from './SubjectContent'; import SPLikeCell from './SPLikeCell'; import SPShareGoodsCell from './SPShareGoodsCell'; import SPCommentCell from './SPCommentCell'; import LoadingIndicator from '../../../common/components/LoadingIndicator'; import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator'; import AssertsPicker from '../posting/AssertsPicker'; import SlicedImage from '../../../common/components/SlicedImage'; let dismissKeyboard = require('dismissKeyboard'); 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) { super(props); this.dataSource = new ListView.DataSource({ rowHasChanged:(r1,r2)=> r1 != r2, sectionHeaderHasChanged: (s1, s2) => s1 != s2, }); this.renderRow = this.renderRow.bind(this); this.state = { contentInputHeight: new Animated.Value(0), imageState: 0, replyState: ReplyState.replyNone, replyTextColor: '#b0b0b0', } 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 = ''; this.replyToSomeOneElse = this.replyToSomeOneElse.bind(this); this.commentId = ''; this.cidTo = ''; this.replyContent=''; this.commitComment = this.commitComment.bind(this); this.cnameTo = ''; this.onPressComment = this.onPressComment.bind(this); } 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; if (kbdHeight == 0) { this.setState({replyState: ReplyState.replyNone}); } 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() { if (this.props.isContentFetching) { return <LoadingIndicator isVisible={this.props.isContentFetching} /> } 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.dataBlob.comments.length) { return <View style={styles.sofaContainer}> <Image style={styles.sofaImage} source={require('../../images/posting/ic_null_message.png')}/> <Text style={styles.sofaText}>快来抢沙发吧~</Text> </View> } 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 assets={this.props.assets} hidden={this.state.imageState == 0} onSelectedAsset={this.props.assetsSelected} /> </View> ); } renderToolContainer() { let picSource = (this.state.imageState>0?require('../../images/posting/pic1.png') : require('../../images/posting/pic_normal.png')); let iconSouce = (this.state.replyState === ReplyState.replyNone)?require('../../images/home/like.png'):picSource; switch (this.state.replyState) { case ReplyState.replyNone: { if (this.props.likeState == 'Y') { iconSouce=require('../../images/home/like.png'); } else if (this.props.likeState == 'N'){ iconSouce=require('../../images/home/unlike.png'); } return ( <View style={styles.toolContainer}> <SlicedImage style={styles.imgIcon} source={iconSouce}/> <TouchableOpacity style={styles.imgButton} onPress={this.props.onPressLikeOrDislike}> </TouchableOpacity> <View style={styles.rightContainer}> <TouchableOpacity style={styles.lzContainer} onPress={ ()=>{ this.cidTo = this.props.authorUid; this.cnameTo = ''; this.commentId = ''; NativeModules.YH_CommunityHelper.uid() .then(uid => { new PostingService().getPostUser(uid).then(json => { if (json.forbidSpeaking === 'Y') { Alert.alert('抱歉','您暂时被禁言,请等待禁言解除哦~'); } else { this.setState({replyState: this.currentReplyState}); } }).catch(error => { this.setState({replyState: this.currentReplyState}); }) }) .catch(error => { NativeModules.YH_CommunityHelper.login() .then(uid => { new PostingService().getPostUser(uid).then(json => { if (json.forbidSpeaking === 'Y') { Alert.alert('抱歉','您暂时被禁言,请等待禁言解除哦~'); } else { this.setState({replyState: this.currentReplyState}); } }).catch(error => { this.setState({replyState: this.currentReplyState}); }) }); }); } } > <Text style={styles.fakePlaceHolder}>回复楼主:</Text> <Text style={styles.replyCountText}>{'已有'+this.props.commentCount+'条回复'}</Text> </TouchableOpacity> </View> <View style={styles.toolTopLine}/> <View style={styles.toolBottomLine}/> </View> ); } break; case ReplyState.replyLZ: { return ( <View style={styles.toolContainer}> <SlicedImage style={styles.imgIcon} source={iconSouce}/> <TouchableOpacity style={styles.imgButton} onPress={this.showImagePannel}> </TouchableOpacity> <TouchableOpacity style={styles.keyboardIcon} onPress={this.blurAll}> <SlicedImage source={require('../../images/posting/jianpan1.png')} /> </TouchableOpacity> <View style={[styles.rightContainer]}> <TextInput ref='textInput' style={styles.replyTextInput} placeholderTextColor='#b0b0b0' placeholder='回复楼主' multiline={true} autoCapitalize={'none'} autoCorrect={false} selectionColor={'black'} autoFocus={true} maxLength={1000} onChangeText={ (text)=>{ this.replyContent = text; if (text.length) { this.setState({replyTextColor: 'black'}); } else { this.setState({replyTextColor: '#b0b0b0'}); } } } onKeyPress={(event)=>{ if (this.replyContent >= 1000) { NativeModules.YH_CommunityHelper.showText('超出1000字符最长限制'); } }} /> <Text style={[styles.submitText, {color:this.state.replyTextColor}]} onPress={this.commitComment}>发送</Text> </View> <View style={styles.toolTopLine}/> <View style={styles.toolBottomLine}/> </View> ); } break; case ReplyState.replySomeone: { return ( <View style={styles.toolContainer}> <SlicedImage style={styles.imgIcon} source={iconSouce}/> <TouchableOpacity style={styles.imgButton} onPress={this.showImagePannel}> </TouchableOpacity> <TouchableOpacity style={styles.keyboardIcon} onPress={this.blurAll}> <SlicedImage source={require('../../images/posting/jianpan1.png')} /> </TouchableOpacity> <View style={[styles.rightContainer]}> <TextInput ref='textInput' style={styles.replyTextInput} placeholderTextColor='#b0b0b0' placeholder={'回复'+this.someOneToReply+':'} multiline={true} autoCapitalize={'none'} selectionColor={'black'} autoCorrect={false} autoFocus={true} maxLength={1000} onChangeText={ (text)=>{ this.replyContent = text; if (text.length) { this.setState({replyTextColor: 'black'}); } else { this.setState({replyTextColor: '#b0b0b0'}); } } } onKeyPress={(event)=>{ if (this.replyContent >= 1000) { NativeModules.YH_CommunityHelper.showText('超出1000字符最长限制'); } }} /> <Text style={[styles.submitText, {color:this.state.replyTextColor}]} onPress={this.commitComment}>发送</Text> </View> <View style={styles.toolTopLine}/> <View style={styles.toolBottomLine}/> </View> ); } break; default: break; } } commitComment() { if (this.replyContent.length == 0 && !this.props.assets.length) { Alert.alert('抱歉','请先输入内容'); return; } let params = { postId: this.props.postId, commentId: this.commentId, cidFrom: this.props.cidFrom, cidTo: this.cidTo, authorUid: this.props.authorUid, content: this.replyContent, } let blocks = []; let textBlock = { "contentData": this.replyContent, "templateKey": "text", "orderBy": 1, }; blocks.push(textBlock); if (this.props.assets.length) { for (var i = 0; i < this.props.assets.length; i++) { let asset = this.props.assets[i]; let imgBlock = { "contentData": asset.url, "templateKey": "image", "size": asset.width + 'x' + asset.height, }; blocks.push(imgBlock); } } let replyTo; if (this.cnameTo.length) { replyTo = { nickName: this.cnameTo, uid: this.cidTo, } } let fakeComment = { blocks, replyTo, } this.props.commentWithParams(params, fakeComment); this.replyContent = ''; this.blurAll(); } renderRow(rowData, sectionId) { switch (sectionId) { case 'header': return ( <SPHeaderCell avatar={rowData.headIcon} nickName={rowData.nickName} timeago={rowData.timeago} isOwner={rowData.LZ} sectionName={rowData.forumName} showLZ={true} onPressAvatar={() => { this.props.onPressAvatar && this.props.onPressAvatar(rowData.uid); }} onPressSection={() => { this.props.onPressSection && this.props.onPressSection({id: rowData.forumCode, name: rowData.forumName}); }} onPressReportOrDelete={this.props.onPressReportOrDelete} /> ); break; case 'title': return( <Text style={styles.title}>{rowData}</Text> ); break; case 'content': return( <SubjectContent onPressLargeImage={this.props.onPressLargeImage} blocks={rowData}/> ); break; case 'shareGoods': return ( <SPShareGoodsCell data={rowData} onPressShareGoods={this.props.onPressShareGoods} /> ); break; case 'like': return ( <SPLikeCell users={rowData.praiseUsers} like={rowData.praise} browse={rowData.browse} onPressLikeCell={() => { this.props.onPressLikeCell && this.props.onPressLikeCell(rowData.postId, rowData.praise); }} /> ); break; case 'comments': return ( <SPCommentCell data={rowData} cidFrom={this.props.cidFrom} onPressAvatar={this.props.onPressAvatar} onPressComment={() => { this.onPressComment(rowData.cidTo, rowData.nickName, rowData.commentId); }} /> ); break; default: return null; break; } } onPressComment(cidTo, nickName, commentId) { this.cidTo = cidTo; this.cnameTo = nickName; this.commentId = commentId; NativeModules.YH_CommunityHelper.uid() .then(uid => { new PostingService().getPostUser(uid).then(json => { if (json.forbidSpeaking === 'Y') { Alert.alert('抱歉','您暂时被禁言,请等待禁言解除哦~'); } else { this.replyToSomeOneElse(nickName); } }).catch(error => { this.replyToSomeOneElse(nickName); }) }) .catch(error => { NativeModules.YH_CommunityHelper.login() .then(uid => { new PostingService().getPostUser(uid).then(json => { if (json.forbidSpeaking === 'Y') { Alert.alert('抱歉','您暂时被禁言,请等待禁言解除哦~'); } else { this.replyToSomeOneElse(nickName); } }).catch(error => { this.replyToSomeOneElse(nickName); }) }); }); } replyToSomeOneElse(someOne) { this.someOneToReply = someOne; this.currentReplyState = ReplyState.replySomeone; this.setState({replyState: this.currentReplyState}); } } const styles = StyleSheet.create({ container: { top: 0, flex: 1, backgroundColor: 'white', }, header: { flexDirection: 'row', paddingTop: 10, paddingBottom: 10, backgroundColor: 'white', paddingLeft: 15, }, headerRight: { flex: 1, flexDirection: 'row', justifyContent: 'flex-end', }, title: { backgroundColor: 'white', fontSize: 17, lineHeight: 32, paddingLeft: 15, paddingRight: 15, }, boardText: { backgroundColor: '#e0e0e0', height: 21, fontSize:14, textAlign: 'center', paddingLeft: 10, paddingRight:10, paddingTop: 3, marginRight:15, fontWeight:'100', }, toolContainer: { flexDirection: 'row', height: 41, alignItems:'center', backgroundColor: 'white', paddingLeft: 15, paddingRight: 15, }, toolTopLine: { position: 'absolute', left: 0, top: 0, width: width, height: 0.5, backgroundColor: '#e0e0e0', }, toolBottomLine: { position: 'absolute', left: 0, bottom: 0, width: width, height: 0.5, backgroundColor: '#e0e0e0', }, 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: 3, 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', color: '#b0b0b0', height: 32, paddingTop: 9, }, replyCountText: { flex: 1, fontSize:14, textAlign: 'right', color: '#b0b0b0', paddingTop: 9, height: 32, }, shareGoodsContainer: { flexDirection: 'row', paddingLeft: 15, paddingBottom: 10, backgroundColor: 'white', }, shareGoodsImage: { width: 52, height: 70, backgroundColor:'gray', }, shareGoodsRightPannel: { flexDirection: 'column', paddingLeft: 10, paddingTop: 5, }, productNameText: { fontSize: 15, width: width - 52 - 30, }, productPriceText: { top: 10, fontSize: 12, color: '#d0021b', }, sofaContainer: { flexDirection: 'column', height: 190, backgroundColor: 'white', alignItems: 'center', }, sofaImage: { width: 55, height: 57, top: 50, }, sofaText: { top: 57, fontSize: 17, textAlign: 'center', color: '#b0b0b0', } });