Authored by 孙凯

add yohoCoin RN UI review by zhanglixia

@@ -2,6 +2,12 @@ @@ -2,6 +2,12 @@
2 2
3 import React, {Component} from 'react'; 3 import React, {Component} from 'react';
4 import Immutable, {Map} from 'immutable'; 4 import Immutable, {Map} from 'immutable';
  5 +import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator';
  6 +import YohoCoinNumHeader from './YohoCoinNumHeader';
  7 +import YohoCoinBanner from './YohoCoinBanner';
  8 +import BrandProductListCell from '../../../common/components/ListCell/ProductListCell';
  9 +import DeviceInfo from 'react-native-device-info';
  10 +import Weixin from '../../../guang/components/detail/Weixin';
5 11
6 import ReactNative, { 12 import ReactNative, {
7 View, 13 View,
@@ -21,6 +27,13 @@ export default class YohoCoin extends Component { @@ -21,6 +27,13 @@ export default class YohoCoin extends Component {
21 27
22 constructor(props) { 28 constructor(props) {
23 super(props); 29 super(props);
  30 + this.renderRow = this.renderRow.bind(this);
  31 + this.renderSectionHeader = this.renderSectionHeader.bind(this);
  32 +
  33 + this.dataSource = new ListView.DataSource({
  34 + rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
  35 + sectionHeaderHasChanged: (s1, s2) => !Immutable.is(s1, s2),
  36 + });
24 } 37 }
25 38
26 shouldComponentUpdate(nextProps){ 39 shouldComponentUpdate(nextProps){
@@ -32,6 +45,50 @@ export default class YohoCoin extends Component { @@ -32,6 +45,50 @@ export default class YohoCoin extends Component {
32 } 45 }
33 } 46 }
34 47
  48 + renderRow(rowData, sectionID, rowID, highlightRow) {
  49 + if (sectionID == 'yohoCoin') {
  50 + return (<YohoCoinNumHeader resource = {rowData} onPressYohoCoinDetail = {this.props.onPressYohoCoinDetail}/>)
  51 + }else if (sectionID == 'banner') {
  52 + return(<YohoCoinBanner resource = {rowData} onPressProduct={this.props.onPressBanner}/>)
  53 + }else if (sectionID == 'weixin') {
  54 + return(<Weixin resource={rowData} onPressWeixin={this.props.onPressWeixin}/>)
  55 + }else if (sectionID == 'favoriteTitle') {
  56 + let listNum = rowData;
  57 + if (listNum == 0) {
  58 + return null;
  59 + }
  60 + let fontFamilyStyle = {};
  61 + if (Platform.OS === 'ios') {
  62 + let systemVersion = DeviceInfo.getSystemVersion();
  63 + systemVersion = parseFloat(systemVersion);
  64 + if (systemVersion >= 9.0) {
  65 + fontFamilyStyle = {fontFamily: 'PingFang SC'};
  66 + }
  67 + }
  68 + return(
  69 + <View style={styles.title}>
  70 + <Text style={[styles.text, fontFamilyStyle]}>你可能喜欢</Text>
  71 + </View>
  72 + );
  73 + }else if (sectionID == 'favorite') {
  74 + let paddingLeft = rowID % 2 == 1 ? rowMarginHorizontal / 2 : rowMarginHorizontal;
  75 + let customStyle = rowID == 0 || rowID == 1 ? {paddingLeft} : {paddingLeft};
  76 + return (
  77 + <BrandProductListCell
  78 + style={[styles.listContainer, customStyle]}
  79 + key={'row' + rowID}
  80 + rowID={rowID}
  81 + data={rowData}
  82 + onPressProduct={this.props.onPressProductCell}/>
  83 + );
  84 + }
  85 + return null;
  86 + }
  87 +
  88 + renderSectionHeader(sectionData, sectionID) {
  89 + return null;
  90 + }
  91 +
35 render() { 92 render() {
36 93
37 let {resource} = this.props; 94 let {resource} = this.props;
@@ -42,18 +99,62 @@ export default class YohoCoin extends Component { @@ -42,18 +99,62 @@ export default class YohoCoin extends Component {
42 favorite, 99 favorite,
43 } = resource; 100 } = resource;
44 101
  102 + let list = favorite?favorite.get('list'):null;
  103 +
  104 + let dataSource = {
  105 + yohoCoin: [yohoCoin],
  106 + banner: [banner],
  107 + weixin: [weixin],
  108 + favoriteTitle: [list?list.size:0],
  109 + favorite: list?list.toArray():[],
  110 + }
  111 +
45 return ( 112 return (
46 <View style={styles.container}> 113 <View style={styles.container}>
47 - <Text>YohoCoin</Text> 114 + <ListView
  115 + ref='YohoCoinList'
  116 + contentContainerStyle={styles.contentContainer}
  117 + enableEmptySections={true}
  118 + dataSource={this.dataSource.cloneWithRowsAndSections(dataSource)}
  119 + renderRow={this.renderRow}
  120 + renderSectionHeader={this.renderSectionHeader}
  121 + onEndReached={() => {
  122 + if (list && list.size > 0) {
  123 + this.props.onEndReached && this.props.onEndReached();
  124 + }
  125 + }}
  126 + />
48 </View> 127 </View>
49 ); 128 );
50 } 129 }
51 } 130 }
52 131
53 let {width, height} = Dimensions.get('window'); 132 let {width, height} = Dimensions.get('window');
  133 +let rowWidth = Math.ceil(137.5 * width / 320);
  134 +let rowMarginHorizontal = (width - rowWidth * 2) / 3;
54 135
55 let styles = StyleSheet.create({ 136 let styles = StyleSheet.create({
56 container: { 137 container: {
57 flex: 1, 138 flex: 1,
58 }, 139 },
  140 + contentContainer:{
  141 + flexDirection: 'row',
  142 + flexWrap: 'wrap',
  143 + },
  144 + listContainer: {
  145 + width: width / 2,
  146 + },
  147 + title: {
  148 + alignItems: 'center',
  149 + justifyContent: 'center',
  150 + height: 40,
  151 + width: width,
  152 + backgroundColor: 'white',
  153 + },
  154 + text: {
  155 + textAlign: 'left',
  156 + fontSize: 17,
  157 + fontWeight: 'bold',
  158 + color: 'rgba(0,0,0,0.3)',
  159 + },
59 }); 160 });
  1 +'use strict';
  2 +
  3 +import React from 'react';
  4 +import ReactNative from 'react-native';
  5 +import Swiper from 'react-native-swiper';
  6 +import YH_Image from '../../../common/components/YH_Image';
  7 +import {getSlicedUrl} from '../../../classify/utils/Utils';
  8 +
  9 +const {
  10 + View,
  11 + TouchableOpacity,
  12 + StyleSheet,
  13 + Dimensions,
  14 + Platform,
  15 +} = ReactNative;
  16 +
  17 +import Immutable, {Map} from 'immutable';
  18 +
  19 +export default class YohoCoinBanner extends React.Component {
  20 +
  21 + constructor(props) {
  22 + super (props);
  23 +
  24 + this.dot = <View
  25 + style={{
  26 + backgroundColor:'rgba(0,0,0,.2)',
  27 + width: 6,
  28 + height: 6,
  29 + borderRadius: 3,
  30 + marginLeft: 3,
  31 + marginRight: 3,
  32 + marginTop: (Platform.OS === 'ios')?3:1,
  33 + marginBottom: 0,
  34 + }}
  35 + />;
  36 + this.activeDot = <View
  37 + style={{
  38 + backgroundColor:'white',
  39 + width: 6,
  40 + height: 6,
  41 + borderRadius: 3,
  42 + marginLeft: 3,
  43 + marginRight: 3,
  44 + marginTop: 3,
  45 + marginBottom: 0,
  46 + }}
  47 + />;
  48 + }
  49 +
  50 + shouldComponentUpdate(nextProps){
  51 + if (Immutable.is(nextProps.resource, this.props.resource)) {
  52 + return false;
  53 + } else {
  54 + return true;
  55 + }
  56 + }
  57 +
  58 + render() {
  59 +
  60 + let resource = this.props.resource?this.props.resource.toJS():null;
  61 +
  62 + if (!resource) {
  63 + return null;
  64 + }
  65 + let error = resource.error;
  66 + let data = resource.list;
  67 + if (error) {
  68 + return null;
  69 + }
  70 +
  71 + if (data.length == 1) {
  72 + let newSrc = getSlicedUrl(data[0].src, width, swiperHeight);
  73 + return (
  74 + <View style={styles.container}>
  75 + <View style={{
  76 + width: width,
  77 + height: 20,
  78 + backgroundColor: 'rgb(240,240,240)',
  79 + }}/>
  80 + <TouchableOpacity
  81 + activeOpacity={1}
  82 + style={{width: width, height: swiperHeight}}
  83 + onPress={() => {
  84 + this.props.onPressProduct && this.props.onPressProduct(data[0].url)
  85 + }}
  86 + >
  87 + <YH_Image
  88 + url={newSrc}
  89 + style={{ width: width, height: swiperHeight}}
  90 + />
  91 + </TouchableOpacity>
  92 + <View style={{
  93 + width: width,
  94 + height: 15,
  95 + backgroundColor: 'rgb(240,240,240)',
  96 + }}/>
  97 + </View>
  98 + );
  99 + } else {
  100 + return (
  101 + <View style={styles.container}>
  102 + <View style={{
  103 + width: width,
  104 + height: 20,
  105 + backgroundColor: '#e0e0e0',
  106 + }}/>
  107 + <Swiper
  108 + style={styles.banner}
  109 + showsButtons={false}
  110 + loop={true}
  111 + autoplay={true}
  112 + autoplayTimeout={2}
  113 + paginationStyle={{bottom: 8}}
  114 + dot={this.dot}
  115 + activeDot={(Platform.OS === 'ios')?this.activeDot:null}
  116 + width={width}
  117 + height={swiperHeight}
  118 + >
  119 + {data.map((item, i) => {
  120 + let newSrc = getSlicedUrl(item.src, width, swiperHeight);
  121 + return (
  122 + <TouchableOpacity
  123 + key={i}
  124 + activeOpacity={1}
  125 + onPress={() => {
  126 + this.props.onPressProduct && this.props.onPressProduct(item.url,row_ID,1,template_name,template_id)
  127 + }}
  128 + >
  129 + <YH_Image
  130 + url={newSrc}
  131 + style={{width: width, height: swiperHeight}}
  132 + />
  133 + </TouchableOpacity>
  134 + );
  135 + })}
  136 + </Swiper>
  137 + <View style={{
  138 + width: width,
  139 + height: 15,
  140 + backgroundColor: '#e0e0e0',
  141 + }}/>
  142 + </View>
  143 + );
  144 + }
  145 + }
  146 +}
  147 +
  148 +let {width, height} = Dimensions.get('window');
  149 +let swiperHeight = Math.ceil((200 / 640) * width);
  150 +
  151 +let styles = StyleSheet.create({
  152 + container: {
  153 + width: width,
  154 + height: swiperHeight + 20 + 15,
  155 + backgroundColor: 'white',
  156 + },
  157 +
  158 +});
  1 +'use strict';
  2 +
  3 +import React from 'react';
  4 +import ReactNative from 'react-native';
  5 +
  6 +const {
  7 + Image,
  8 + View,
  9 + Text,
  10 + StyleSheet,
  11 + Dimensions,
  12 + TouchableOpacity,
  13 +} = ReactNative;
  14 +
  15 +export default class YohoCoinNumHeader extends React.Component {
  16 +
  17 + constructor(props) {
  18 + super (props);
  19 + }
  20 +
  21 + componentDidMount() {
  22 +
  23 + }
  24 +
  25 + render() {
  26 + let resource = this.props.resource?this.props.resource.toJS():null;
  27 + if (!resource) {
  28 + return null;
  29 + }
  30 + let notice = resource.notice;
  31 + let yohocoin_num = resource.yohocoin_num;
  32 + let yohoCoinCode = resource.yohoCoinCode;
  33 +
  34 + let heigth_t = notice == '' ? headerHeight : headerHeight + noticeViewHeight;
  35 + return (
  36 + <View style={{width: width,height: heigth_t,backgroundColor: 'white',}}>
  37 + <View style={{width: width,height: headerHeight,backgroundColor: 'white',}}>
  38 + <View style={styles.numView}>
  39 + <Text style={styles.numText}>{yohocoin_num}</Text>
  40 + </View>
  41 + <View style={styles.numDetailView}>
  42 + <Image style={styles.icon} source={require('../../image/yohocoin_icon.png')}/>
  43 + <Text style={styles.numDetailText}>个有货币</Text>
  44 + </View>
  45 + <View style={styles.button}>
  46 + <TouchableOpacity
  47 + activeOpacity={1}
  48 + style={{width: 100, height: ( 38/154 ) * 100}}
  49 + onPress={() => {
  50 + this.props.onPressYohoCoinDetail && this.props.onPressYohoCoinDetail(yohoCoinCode)
  51 + }}
  52 + >
  53 + <Image style={styles.image} source={require('../../image/check_detail_btn.png')}/>
  54 + </TouchableOpacity>
  55 + </View>
  56 + </View>
  57 + {notice != '' ?
  58 + <View style={styles.notice}>
  59 + <Image style={styles.noticeIcon} source={require('../../image/yohocoin_notice_ic.png')}/>
  60 + <Text style={styles.noticeText}>{notice}</Text>
  61 + </View>
  62 + : null}
  63 + </View>
  64 + )
  65 + }
  66 +};
  67 +
  68 +let {width, height} = Dimensions.get('window');
  69 +let headerHeight = Math.ceil((250 / 640) * width);
  70 +let noticeViewHeight = Math.ceil((70 / 640) * width);
  71 +
  72 +const styles = StyleSheet.create({
  73 + numView: {
  74 + marginTop: 20,
  75 + width: width,
  76 + height: 60,
  77 + backgroundColor: 'white',
  78 + alignItems: 'center',
  79 + justifyContent: 'center',
  80 + },
  81 + numText: {
  82 + width:width,
  83 + backgroundColor: 'white',
  84 + color: 'rgb(206,11,36)',
  85 + fontSize: 60,
  86 + textAlign: 'center',
  87 + },
  88 + numDetailView: {
  89 + width: width,
  90 + height: 25,
  91 + backgroundColor: 'white',
  92 + alignItems: 'center',
  93 + justifyContent: 'center',
  94 + flexDirection: 'row',
  95 + },
  96 + icon: {
  97 + width: 15,
  98 + height: 15,
  99 + },
  100 + numDetailText: {
  101 + backgroundColor: 'white',
  102 + color: 'gray',
  103 + fontSize: 14,
  104 + textAlign: 'center',
  105 + },
  106 + button: {
  107 + marginTop: 7,
  108 + width: width,
  109 + height: 40,
  110 + backgroundColor: 'white',
  111 + alignItems: 'center',
  112 + justifyContent: 'center',
  113 + },
  114 + image: {
  115 + width: 100,
  116 + height: ( 38/154 ) * 100,
  117 + },
  118 + notice: {
  119 + width: width,
  120 + height: noticeViewHeight,
  121 + backgroundColor: 'rgb(217,217,217)',
  122 + flexDirection: 'row',
  123 + alignItems: 'center',
  124 + },
  125 + noticeIcon: {
  126 + width: 15,
  127 + height: 15,
  128 + marginLeft: 15,
  129 + },
  130 + noticeText: {
  131 + backgroundColor: 'transparent',
  132 + color: 'rgb(206,11,36)',
  133 + fontSize: 11,
  134 + marginLeft: 20,
  135 + }
  136 +});
@@ -44,6 +44,11 @@ function mapDispatchToProps(dispatch) { @@ -44,6 +44,11 @@ function mapDispatchToProps(dispatch) {
44 class YohoCoinContainer extends Component { 44 class YohoCoinContainer extends Component {
45 constructor(props) { 45 constructor(props) {
46 super(props); 46 super(props);
  47 + this._onEndReached = this._onEndReached.bind(this);
  48 + this._onPressProductCell = this._onPressProductCell.bind(this);
  49 + this._onPressWeixin = this._onPressWeixin.bind(this);
  50 + this._onPressBanner = this._onPressBanner.bind(this);
  51 + this._onPressYohoCoinDetail = this._onPressYohoCoinDetail.bind(this);
47 } 52 }
48 53
49 componentDidMount() { 54 componentDidMount() {
@@ -57,6 +62,31 @@ class YohoCoinContainer extends Component { @@ -57,6 +62,31 @@ class YohoCoinContainer extends Component {
57 62
58 } 63 }
59 64
  65 + _onPressWeixin(data) {
  66 + ReactNative.NativeModules.YH_CommonHelper.copyWechatIdToClipboard(data);
  67 + }
  68 +
  69 + _onEndReached() {
  70 + this.props.actions.fetchFavoriteList();
  71 + }
  72 +
  73 + _onPressYohoCoinDetail(yohoCoinCode) {
  74 + ReactNative.NativeModules.YH_MyAssetsViewHelper.pushCoinDetail(yohoCoinCode);
  75 + }
  76 +
  77 + _onPressBanner (url){
  78 + ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
  79 + }
  80 +
  81 + _onPressProductCell(product) {
  82 + let productSkn = product && product.get('product_skn', 0);
  83 + if (!productSkn) {
  84 + return;
  85 + }
  86 + let url = `http://m.yohobuy.com?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":"${productSkn}"}}`;
  87 + ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
  88 + }
  89 +
60 render() { 90 render() {
61 let {yohoCoin} = this.props; 91 let {yohoCoin} = this.props;
62 92
@@ -64,6 +94,11 @@ class YohoCoinContainer extends Component { @@ -64,6 +94,11 @@ class YohoCoinContainer extends Component {
64 <View style={styles.container}> 94 <View style={styles.container}>
65 <YohoCoin 95 <YohoCoin
66 resource={yohoCoin} 96 resource={yohoCoin}
  97 + onEndReached={this._onEndReached}
  98 + onPressProductCell= {this._onPressProductCell}
  99 + onPressWeixin={this._onPressWeixin}
  100 + onPressBanner={this._onPressBanner}
  101 + onPressYohoCoinDetail={this._onPressYohoCoinDetail}
67 /> 102 />
68 </View> 103 </View>
69 ); 104 );
@@ -8,6 +8,7 @@ let InitialState = Record({ @@ -8,6 +8,7 @@ let InitialState = Record({
8 notice: '', 8 notice: '',
9 isFetching: false, 9 isFetching: false,
10 error: null, 10 error: null,
  11 + yohoCoinCode: '20151230-102233',
11 })), 12 })),
12 13
13 banner: new (Record({ 14 banner: new (Record({