Authored by 于良

潮流优选 优化 review by 草莓

@@ -33,7 +33,7 @@ export default class LoadingIndicator extends Component { @@ -33,7 +33,7 @@ export default class LoadingIndicator extends Component {
33 color: (Platform.OS === 'ios') ? 'white' : 'gray', 33 color: (Platform.OS === 'ios') ? 'white' : 'gray',
34 text: '加载中...', 34 text: '加载中...',
35 textColor: '#eeeeee', 35 textColor: '#eeeeee',
36 - textFontSize: 14, 36 + textFontSize: 12,
37 }; 37 };
38 38
39 render() { 39 render() {
@@ -8,7 +8,7 @@ const { @@ -8,7 +8,7 @@ const {
8 const Button = (props) => { 8 const Button = (props) => {
9 return <TouchableNativeFeedback 9 return <TouchableNativeFeedback
10 delayPressIn={0} 10 delayPressIn={0}
11 - background={TouchableNativeFeedback.SelectableBackground()} 11 + background={TouchableNativeFeedback.SelectableBackground()} // eslint-disable-line new-cap
12 {...props} 12 {...props}
13 > 13 >
14 {props.children} 14 {props.children}
@@ -20,6 +20,7 @@ const DefaultTabBar = React.createClass({ @@ -20,6 +20,7 @@ const DefaultTabBar = React.createClass({
20 inactiveTextColor: React.PropTypes.string, 20 inactiveTextColor: React.PropTypes.string,
21 textStyle: Text.propTypes.style, 21 textStyle: Text.propTypes.style,
22 tabStyle: View.propTypes.style, 22 tabStyle: View.propTypes.style,
  23 + renderTabName: React.PropTypes.func,
23 }, 24 },
24 25
25 getDefaultProps() { 26 getDefaultProps() {
@@ -29,29 +30,35 @@ const DefaultTabBar = React.createClass({ @@ -29,29 +30,35 @@ const DefaultTabBar = React.createClass({
29 underlineColor: 'navy', 30 underlineColor: 'navy',
30 backgroundColor: null, 31 backgroundColor: null,
31 underlineHeight: 4, 32 underlineHeight: 4,
  33 + renderTabName: this.renderTabName,
32 }; 34 };
33 }, 35 },
34 36
35 renderTabOption(name, page) { 37 renderTabOption(name, page) {
36 const isTabActive = this.props.activeTab === page; 38 const isTabActive = this.props.activeTab === page;
37 - const { activeTextColor, inactiveTextColor, textStyle, } = this.props;  
38 - const textColor = isTabActive ? activeTextColor : inactiveTextColor;  
39 - const fontWeight = isTabActive ? 'bold' : 'normal';  
40 39
41 return <Button 40 return <Button
42 - style={{flex: 1}} 41 + style={{flex: 1, }}
43 key={name} 42 key={name}
44 accessible={true} 43 accessible={true}
45 accessibilityLabel={name} 44 accessibilityLabel={name}
46 accessibilityTraits='button' 45 accessibilityTraits='button'
47 onPress={() => this.props.goToPage(page)} 46 onPress={() => this.props.goToPage(page)}
48 > 47 >
49 - <View style={[styles.tab, this.props.tabStyle]}> 48 + {this.renderTabName(name, page, isTabActive)}
  49 + </Button>;
  50 + },
  51 +
  52 + renderTabName(name, page, isTabActive) {
  53 + const { activeTextColor, inactiveTextColor, textStyle, } = this.props;
  54 + const textColor = isTabActive ? activeTextColor : inactiveTextColor;
  55 + const fontWeight = isTabActive ? 'bold' : 'normal';
  56 +
  57 + return <View style={[styles.tab, this.props.tabStyle, ]}>
50 <Text style={[{color: textColor, fontWeight, }, textStyle, ]}> 58 <Text style={[{color: textColor, fontWeight, }, textStyle, ]}>
51 {name} 59 {name}
52 </Text> 60 </Text>
53 - </View>  
54 - </Button>; 61 + </View>;
55 }, 62 },
56 63
57 render() { 64 render() {
@@ -28,6 +28,7 @@ const ScrollableTabBar = React.createClass({ @@ -28,6 +28,7 @@ const ScrollableTabBar = React.createClass({
28 tabStyle: View.propTypes.style, 28 tabStyle: View.propTypes.style,
29 tabsContainerStyle: View.propTypes.style, 29 tabsContainerStyle: View.propTypes.style,
30 textStyle: Text.propTypes.style, 30 textStyle: Text.propTypes.style,
  31 + renderTabName: React.PropTypes.func,
31 }, 32 },
32 33
33 getDefaultProps() { 34 getDefaultProps() {
@@ -41,6 +42,7 @@ const ScrollableTabBar = React.createClass({ @@ -41,6 +42,7 @@ const ScrollableTabBar = React.createClass({
41 style: {}, 42 style: {},
42 tabStyle: {}, 43 tabStyle: {},
43 tabsContainerStyle: {}, 44 tabsContainerStyle: {},
  45 + renderTabName: this.renderTabName,
44 }; 46 };
45 }, 47 },
46 48
@@ -90,7 +92,7 @@ const ScrollableTabBar = React.createClass({ @@ -90,7 +92,7 @@ const ScrollableTabBar = React.createClass({
90 let newScrollX = tabOffset + absolutePageOffset; 92 let newScrollX = tabOffset + absolutePageOffset;
91 93
92 // center tab and smooth tab change (for when tabWidth changes a lot between two tabs) 94 // center tab and smooth tab change (for when tabWidth changes a lot between two tabs)
93 - newScrollX -= (containerWidth - (1 - pageOffset) * tabWidth - pageOffset * nextTabWidth ) / 2 ; 95 + newScrollX -= (containerWidth - (1 - pageOffset) * tabWidth - pageOffset * nextTabWidth) / 2;
94 newScrollX = newScrollX >= 0 ? newScrollX : 0; 96 newScrollX = newScrollX >= 0 ? newScrollX : 0;
95 97
96 if (Platform.OS === 'android') { 98 if (Platform.OS === 'android') {
@@ -124,9 +126,6 @@ const ScrollableTabBar = React.createClass({ @@ -124,9 +126,6 @@ const ScrollableTabBar = React.createClass({
124 126
125 renderTabOption(name, page) { 127 renderTabOption(name, page) {
126 const isTabActive = this.props.activeTab === page; 128 const isTabActive = this.props.activeTab === page;
127 - const { activeTextColor, inactiveTextColor, textStyle, } = this.props;  
128 - const textColor = isTabActive ? activeTextColor : inactiveTextColor;  
129 - const fontWeight = isTabActive ? 'bold' : 'normal';  
130 129
131 return <Button 130 return <Button
132 key={`${name}_${page}`} 131 key={`${name}_${page}`}
@@ -136,12 +135,20 @@ const ScrollableTabBar = React.createClass({ @@ -136,12 +135,20 @@ const ScrollableTabBar = React.createClass({
136 onPress={() => this.props.goToPage(page)} 135 onPress={() => this.props.goToPage(page)}
137 onLayout={this.measureTab.bind(this, page)} 136 onLayout={this.measureTab.bind(this, page)}
138 > 137 >
139 - <View style={[styles.tab, this.props.tabStyle]}> 138 + {this.renderTabName(name, page, isTabActive)}
  139 + </Button>;
  140 + },
  141 +
  142 + renderTabName(name, page, isTabActive) {
  143 + const { activeTextColor, inactiveTextColor, textStyle, } = this.props;
  144 + const textColor = isTabActive ? activeTextColor : inactiveTextColor;
  145 + const fontWeight = isTabActive ? 'bold' : 'normal';
  146 +
  147 + return <View style={[styles.tab, this.props.tabStyle, ]}>
140 <Text style={[{color: textColor, fontWeight, }, textStyle, ]}> 148 <Text style={[{color: textColor, fontWeight, }, textStyle, ]}>
141 {name} 149 {name}
142 </Text> 150 </Text>
143 - </View>  
144 - </Button>; 151 + </View>;
145 }, 152 },
146 153
147 measureTab(page, event) { 154 measureTab(page, event) {
@@ -164,7 +171,7 @@ const ScrollableTabBar = React.createClass({ @@ -164,7 +171,7 @@ const ScrollableTabBar = React.createClass({
164 }; 171 };
165 172
166 return <View 173 return <View
167 - style={[styles.container, {backgroundColor: this.props.backgroundColor, }, this.props.style]} 174 + style={[styles.container, {backgroundColor: this.props.backgroundColor, }, this.props.style, ]}
168 onLayout={this.onContainerLayout} 175 onLayout={this.onContainerLayout}
169 > 176 >
170 <ScrollView 177 <ScrollView
@@ -174,9 +181,10 @@ const ScrollableTabBar = React.createClass({ @@ -174,9 +181,10 @@ const ScrollableTabBar = React.createClass({
174 showsVerticalScrollIndicator={false} 181 showsVerticalScrollIndicator={false}
175 directionalLockEnabled={true} 182 directionalLockEnabled={true}
176 bounces={false} 183 bounces={false}
  184 + scrollsToTop={false}
177 > 185 >
178 <View 186 <View
179 - style={[styles.tabs, {width: this.state._containerWidth, }, this.props.tabsContainerStyle]} 187 + style={[styles.tabs, {width: this.state._containerWidth, }, this.props.tabsContainerStyle, ]}
180 ref={'tabContainer'} 188 ref={'tabContainer'}
181 onLayout={this.onTabContainerLayout} 189 onLayout={this.onTabContainerLayout}
182 > 190 >
@@ -39,7 +39,7 @@ const ScrollableTabView = React.createClass({ @@ -39,7 +39,7 @@ const ScrollableTabView = React.createClass({
39 contentProps: PropTypes.object, 39 contentProps: PropTypes.object,
40 scrollWithoutAnimation: PropTypes.bool, 40 scrollWithoutAnimation: PropTypes.bool,
41 locked: PropTypes.bool, 41 locked: PropTypes.bool,
42 - prerenderingSiblingsNumber: PropTypes.number 42 + prerenderingSiblingsNumber: PropTypes.number,
43 }, 43 },
44 44
45 getDefaultProps() { 45 getDefaultProps() {
@@ -52,7 +52,7 @@ const ScrollableTabView = React.createClass({ @@ -52,7 +52,7 @@ const ScrollableTabView = React.createClass({
52 contentProps: {}, 52 contentProps: {},
53 scrollWithoutAnimation: false, 53 scrollWithoutAnimation: false,
54 locked: false, 54 locked: false,
55 - prerenderingSiblingsNumber: 0 55 + prerenderingSiblingsNumber: 0,
56 }; 56 };
57 }, 57 },
58 58
@@ -67,13 +67,13 @@ const ScrollableTabView = React.createClass({ @@ -67,13 +67,13 @@ const ScrollableTabView = React.createClass({
67 }, 67 },
68 68
69 componentWillReceiveProps(props) { 69 componentWillReceiveProps(props) {
70 - if (props.page >= 0 && props.page !== this.state.currentPage) {  
71 - this.goToPage(props.page);  
72 - }  
73 -  
74 if (props.children !== this.props.children) { 70 if (props.children !== this.props.children) {
75 this.updateSceneKeys({ page: this.state.currentPage, children: props.children, }); 71 this.updateSceneKeys({ page: this.state.currentPage, children: props.children, });
76 } 72 }
  73 +
  74 + if (props.page >= 0 && props.page !== this.state.currentPage) {
  75 + this.goToPage(props.page);
  76 + }
77 }, 77 },
78 78
79 goToPage(pageNumber) { 79 goToPage(pageNumber) {
@@ -167,20 +167,8 @@ const ScrollableTabView = React.createClass({ @@ -167,20 +167,8 @@ const ScrollableTabView = React.createClass({
167 const offsetX = e.nativeEvent.contentOffset.x; 167 const offsetX = e.nativeEvent.contentOffset.x;
168 this._updateScrollValue(offsetX / this.state.containerWidth); 168 this._updateScrollValue(offsetX / this.state.containerWidth);
169 }} 169 }}
170 - onMomentumScrollBegin={(e) => {  
171 - const offsetX = e.nativeEvent.contentOffset.x;  
172 - const page = Math.round(offsetX / this.state.containerWidth);  
173 - if (this.state.currentPage !== page) {  
174 - this._updateSelectedPage(page);  
175 - }  
176 - }}  
177 - onMomentumScrollEnd={(e) => {  
178 - const offsetX = e.nativeEvent.contentOffset.x;  
179 - const page = Math.round(offsetX / this.state.containerWidth);  
180 - if (this.state.currentPage !== page) {  
181 - this._updateSelectedPage(page);  
182 - }  
183 - }} 170 + onMomentumScrollBegin={this._onMomentumScrollBeginAndEnd}
  171 + onMomentumScrollEnd={this._onMomentumScrollBeginAndEnd}
184 scrollEventThrottle={16} 172 scrollEventThrottle={16}
185 scrollsToTop={false} 173 scrollsToTop={false}
186 showsHorizontalScrollIndicator={false} 174 showsHorizontalScrollIndicator={false}
@@ -226,6 +214,14 @@ const ScrollableTabView = React.createClass({ @@ -226,6 +214,14 @@ const ScrollableTabView = React.createClass({
226 }); 214 });
227 }, 215 },
228 216
  217 + _onMomentumScrollBeginAndEnd(e) {
  218 + const offsetX = e.nativeEvent.contentOffset.x;
  219 + const page = Math.round(offsetX / this.state.containerWidth);
  220 + if (this.state.currentPage !== page) {
  221 + this._updateSelectedPage(page);
  222 + }
  223 + },
  224 +
229 _updateSelectedPage(nextPage) { 225 _updateSelectedPage(nextPage) {
230 let localNextPage = nextPage; 226 let localNextPage = nextPage;
231 if (typeof localNextPage === 'object') { 227 if (typeof localNextPage === 'object') {
@@ -245,7 +241,6 @@ const ScrollableTabView = React.createClass({ @@ -245,7 +241,6 @@ const ScrollableTabView = React.createClass({
245 ref: this._children()[currentPage], 241 ref: this._children()[currentPage],
246 from: prevPage, 242 from: prevPage,
247 }); 243 });
248 -  
249 }, 244 },
250 245
251 _updateScrollValue(value) { 246 _updateScrollValue(value) {
1 { 1 {
2 - "_args": [  
3 - [  
4 - "react-native-scrollable-tab-view@0.5.3",  
5 - "/Users/yl3016/Desktop/workspace/YH_RNComponent"  
6 - ]  
7 - ],  
8 - "_cnpm_publish_time": 1468347268973,  
9 - "_from": "react-native-scrollable-tab-view@0.5.3",  
10 - "_id": "react-native-scrollable-tab-view@0.5.3",  
11 - "_inCache": true,  
12 - "_installable": true,  
13 - "_location": "/react-native-scrollable-tab-view",  
14 - "_nodeVersion": "4.1.1",  
15 - "_npmOperationalInternal": {  
16 - "host": "packages-12-west.internal.npmjs.com",  
17 - "tmp": "tmp/react-native-scrollable-tab-view-0.5.3.tgz_1468347266619_0.6885842669289559"  
18 - },  
19 - "_npmUser": {  
20 - "email": "skv-headless@yandex.ru",  
21 - "name": "headless"  
22 - },  
23 - "_npmVersion": "2.14.4",  
24 - "_phantomChildren": {},  
25 - "_requested": {  
26 "name": "react-native-scrollable-tab-view", 2 "name": "react-native-scrollable-tab-view",
27 - "raw": "react-native-scrollable-tab-view@0.5.3",  
28 - "rawSpec": "0.5.3",  
29 - "scope": null,  
30 - "spec": "0.5.3",  
31 - "type": "version"  
32 - },  
33 - "_requiredBy": [  
34 - "/"  
35 - ],  
36 - "_resolved": "http://registry.cnpmjs.org/react-native-scrollable-tab-view/download/react-native-scrollable-tab-view-0.5.3.tgz",  
37 - "_shasum": "fe8c905eacbe28e7ef91ab89925891db6e125c39",  
38 - "_shrinkwrap": null,  
39 - "_spec": "react-native-scrollable-tab-view@0.5.3",  
40 - "_where": "/Users/yl3016/Desktop/workspace/YH_RNComponent",  
41 - "author": {  
42 - "name": "Brent Vatne"  
43 - },  
44 - "bugs": {  
45 - "url": "https://github.com/brentvatne/react-native-scrollable-tab-view/issues"  
46 - },  
47 - "dependencies": {  
48 - "react-static-container": "^1.0.1",  
49 - "react-timer-mixin": "^0.13.3" 3 + "version": "0.5.5",
  4 + "description": "",
  5 + "main": "index.js",
  6 + "scripts": {
  7 + "lint": "eslint -c .eslintrc .",
  8 + "test": "echo \"Error: no test specified\" && exit 1"
50 }, 9 },
51 - "description": "[![npm version](https://badge.fury.io/js/react-native-scrollable-tab-view.svg)](https://badge.fury.io/js/react-native-scrollable-tab-view)",  
52 - "devDependencies": {},  
53 - "directories": {},  
54 - "dist": {  
55 - "noattachment": false,  
56 - "shasum": "fe8c905eacbe28e7ef91ab89925891db6e125c39",  
57 - "size": 9131,  
58 - "tarball": "http://registry.cnpmjs.org/react-native-scrollable-tab-view/download/react-native-scrollable-tab-view-0.5.3.tgz" 10 + "repository": {
  11 + "type": "git",
  12 + "url": "git+https://github.com/brentvatne/react-native-scrollable-tab-view.git"
59 }, 13 },
60 - "gitHead": "a66720150307c4f1352a215151aadcdd28e25b37",  
61 - "homepage": "https://github.com/brentvatne/react-native-scrollable-tab-view#readme",  
62 "keywords": [ 14 "keywords": [
63 "react-native-component", 15 "react-native-component",
64 "react-component", 16 "react-component",
@@ -67,31 +19,21 @@ @@ -67,31 +19,21 @@
67 "tab", 19 "tab",
68 "scrollable" 20 "scrollable"
69 ], 21 ],
  22 + "author": "Brent Vatne",
70 "license": "MIT", 23 "license": "MIT",
71 - "main": "index.js",  
72 - "maintainers": [  
73 - {  
74 - "email": "brentvatne@gmail.com",  
75 - "name": "brentvatne" 24 + "bugs": {
  25 + "url": "https://github.com/brentvatne/react-native-scrollable-tab-view/issues"
76 }, 26 },
77 - {  
78 - "email": "skv-headless@yandex.ru",  
79 - "name": "headless"  
80 - }  
81 - ],  
82 - "name": "react-native-scrollable-tab-view",  
83 - "optionalDependencies": {},  
84 "peerDependencies": { 27 "peerDependencies": {
85 "react-native": ">=0.20.0" 28 "react-native": ">=0.20.0"
86 }, 29 },
87 - "publish_time": 1468347268973,  
88 - "readme": "ERROR: No README data found!",  
89 - "repository": {  
90 - "type": "git",  
91 - "url": "git+https://github.com/brentvatne/react-native-scrollable-tab-view.git"  
92 - },  
93 - "scripts": {  
94 - "test": "echo \"Error: no test specified\" && exit 1" 30 + "homepage": "https://github.com/brentvatne/react-native-scrollable-tab-view#readme",
  31 + "dependencies": {
  32 + "react-static-container": "^1.0.1",
  33 + "react-timer-mixin": "^0.13.3"
95 }, 34 },
96 - "version": "0.5.3" 35 + "devDependencies": {
  36 + "babel-eslint": "^6.1.2",
  37 + "eslint": "^3.1.1"
  38 + }
97 } 39 }
@@ -14,15 +14,15 @@ export default class Request { @@ -14,15 +14,15 @@ export default class Request {
14 constructor(baseURL) { 14 constructor(baseURL) {
15 if (baseURL) { 15 if (baseURL) {
16 this.baseUrl= baseURL; 16 this.baseUrl= baseURL;
  17 + this.timeout = 30000;
17 } else { 18 } else {
18 this.config = process.env.NODE_ENV === `development` ? CONFIG.dev : CONFIG.prd; 19 this.config = process.env.NODE_ENV === `development` ? CONFIG.dev : CONFIG.prd;
19 20
20 this.baseUrl= this.config.baseUrl; 21 this.baseUrl= this.config.baseUrl;
  22 + this.timeout = this.config.HTTPTimeout;
21 } 23 }
22 24
23 this.privateKey = RNNativeConfig.getPrivateKey(); 25 this.privateKey = RNNativeConfig.getPrivateKey();
24 -  
25 - this.timeout = this.config.HTTPTimeout;  
26 } 26 }
27 27
28 28
@@ -29,6 +29,7 @@ import { @@ -29,6 +29,7 @@ import {
29 29
30 import { 30 import {
31 setSegment, 31 setSegment,
  32 + setGender,
32 } from './reducers/plustar/plustarActions'; 33 } from './reducers/plustar/plustarActions';
33 34
34 function getInitialState() { 35 function getInitialState() {
@@ -77,8 +78,13 @@ export default function native(platform) { @@ -77,8 +78,13 @@ export default function native(platform) {
77 render() { 78 render() {
78 const store = configureStore(getInitialState()); 79 const store = configureStore(getInitialState());
79 store.dispatch(setPlatform(platform)); 80 store.dispatch(setPlatform(platform));
80 - let segment = getInitSegment(this.props.segmentType); 81 + let segment = getInitSegment(this.props.initType);
81 store.dispatch(setSegment(segment)); 82 store.dispatch(setSegment(segment));
  83 + if (this.props.initType == 0) {
  84 + let gender = this.props.genderType;
  85 + store.dispatch(setGender(gender));
  86 + }
  87 +
82 88
83 return ( 89 return (
84 <Provider store={store}> 90 <Provider store={store}>
1 -import React from 'react-native';  
2 -import { Provider } from 'react-redux/native';  
3 -import configureStore from '../store/configureStore';  
4 -import PlustarContainer from '../containers/PlustarContainer';  
5 -  
6 -class PlustarComponent extends React.Component {  
7 -  
8 - constructor(props) {  
9 - super(props);  
10 -  
11 - let leftSegment, rightSegment;  
12 -  
13 - if(this.props.initType == 1) {  
14 - //潮流优选  
15 - leftSegment = {  
16 - title:'设计新潮',  
17 - type:4  
18 - };  
19 - rightSegment = {  
20 - title:'潮流经典',  
21 - type:1  
22 - };  
23 - } else if(this.props.initType == 2) {  
24 - //明星原创  
25 - leftSegment = {  
26 - title:'明星潮品',  
27 - type:2  
28 - };  
29 - rightSegment = {  
30 - title:'原创潮牌',  
31 - type:3  
32 - };  
33 - }  
34 -  
35 - let initialState = {  
36 - plustar: {  
37 - payload: {  
38 - left: {  
39 - segment: leftSegment,  
40 - },  
41 - right: {  
42 - segment: rightSegment,  
43 - },  
44 - selectedIndex: 0,  
45 - genderType: this.props.genderType,  
46 - }  
47 - },  
48 - };  
49 -  
50 - this.store = configureStore(initialState);  
51 - }  
52 -  
53 - render () {  
54 - return (  
55 - <Provider store={this.store}>  
56 - {() => <PlustarContainer />}  
57 - </Provider>  
58 - );  
59 - }  
60 -}  
61 -  
62 -export default PlustarComponent;  
63 -   
  1 +'use strict';
  2 +
  3 +import React from 'react';
  4 +import ReactNative from 'react-native';
  5 +import Swiper from 'react-native-swiper';
  6 +import ImmutablePropTypes from 'react-immutable-proptypes';
  7 +import SlicedImage from '../../../common/components/SlicedImage';
  8 +
  9 +const {
  10 + View,
  11 + Image,
  12 + TouchableOpacity,
  13 + StyleSheet,
  14 + Dimensions,
  15 +} = ReactNative;
  16 +
  17 +export default class Banner extends React.Component {
  18 +
  19 + static propTypes = {
  20 + data: ImmutablePropTypes.listOf(
  21 + ImmutablePropTypes.contains({
  22 + src: React.PropTypes.string.isRequired,
  23 + url: React.PropTypes.string.isRequired,
  24 + })
  25 + ),
  26 + duration: React.PropTypes.number,
  27 + width: React.PropTypes.number.isRequired,
  28 + height: React.PropTypes.number.isRequired,
  29 + onPress: React.PropTypes.func,
  30 + };
  31 +
  32 + constructor(props) {
  33 + super (props);
  34 +
  35 + this.dot = <View
  36 + style={{
  37 + backgroundColor:'rgba(0,0,0,.2)',
  38 + width: 6,
  39 + height: 6,
  40 + borderRadius: 3,
  41 + marginLeft: 3,
  42 + marginRight: 3,
  43 + marginTop: 3,
  44 + marginBottom: 3,
  45 + }}
  46 + />;
  47 + this.activeDot = <View
  48 + style={{
  49 + backgroundColor:'white',
  50 + width: 6,
  51 + height: 6,
  52 + borderRadius: 3,
  53 + marginLeft: 3,
  54 + marginRight: 3,
  55 + marginTop: 3,
  56 + marginBottom: 3,
  57 + }}
  58 + />;
  59 + }
  60 +
  61 + render() {
  62 + let width = this.props.width;
  63 + let height = this.props.height;
  64 + let data = this.props.data.toArray();
  65 +
  66 + return (
  67 + <Swiper
  68 + style={styles.banner}
  69 + showsButtons={false}
  70 + loop={true}
  71 + autoplay={false}
  72 + autoplayTimeout={this.props.duration}
  73 + paginationStyle={{bottom: 8}}
  74 + dot={this.dot}
  75 + activeDot={this.activeDot}
  76 + height={height}
  77 + >
  78 + {data.map((item, i) => {
  79 + return (
  80 + <TouchableOpacity
  81 + key={i}
  82 + activeOpacity={1}
  83 + onPress={() => {
  84 + this.props.onPress && this.props.onPress(item.get('url'));
  85 + }}
  86 + >
  87 + <SlicedImage source={{uri: item.get('src')}} style={{width, height}}/>
  88 + </TouchableOpacity>
  89 + );
  90 + })}
  91 + </Swiper>
  92 + );
  93 + }
  94 +}
  95 +
  96 +let styles = StyleSheet.create({
  97 + banner: {
  98 +
  99 + },
  100 +});
@@ -14,101 +14,66 @@ import ReactNative, { @@ -14,101 +14,66 @@ import ReactNative, {
14 } from 'react-native'; 14 } from 'react-native';
15 15
16 import ScrollableTabView from 'react-native-scrollable-tab-view'; 16 import ScrollableTabView from 'react-native-scrollable-tab-view';
17 -import PlustarGenderSelector from './PlustarGenderSelector';  
18 import PlustarSegment from './PlustarSegment'; 17 import PlustarSegment from './PlustarSegment';
19 import PlustarList from './PlustarList'; 18 import PlustarList from './PlustarList';
20 -  
21 -import {swithSegment, switchGender, fetchPlustarIfNeeded, plustarRouter, popViewController} from '../../reducers/plustar/plustarActions'; 19 +import LoadingIndicator from '../../../common/components/LoadingIndicator';
22 20
23 export default class Plustar extends Component { 21 export default class Plustar extends Component {
24 22
25 constructor(props) { 23 constructor(props) {
26 super(props); 24 super(props);
27 25
28 - this._onPressSegment = this._onPressSegment.bind(this);  
29 - this._onChangeTab = this._onChangeTab.bind(this);  
30 - this._onScroll = this._onScroll.bind(this);  
31 this._onPressRow = this._onPressRow.bind(this); 26 this._onPressRow = this._onPressRow.bind(this);
32 -  
33 - this.subscription = null;  
34 - }  
35 -  
36 - componentWillMount() {  
37 -  
38 - this.subscription = NativeAppEventEmitter.addListener(  
39 - "onChangeGender",  
40 - (reminder) => {  
41 - this.props.dispatch(switchGender(reminder.genderType));  
42 - }  
43 - );  
44 } 27 }
45 28
46 componentDidMount() { 29 componentDidMount() {
47 - this.props.dispatch(fetchPlustarIfNeeded(0));  
48 - this.props.dispatch(fetchPlustarIfNeeded(1)); 30 +
49 } 31 }
50 32
51 - componentWillUnmount() {  
52 - this.subscription.remove(); 33 + _onPressRow(url) {
  34 + this.props.onPressRow && this.props.onPressRow(url);
53 } 35 }
54 36
55 render() { 37 render() {
56 -  
57 - let {left, right, selectedIndex} = this.props;  
58 - let segment = [left.segment, right.segment]; 38 + let {segment, activeTab, left, right, isCurrentTabFetching} = this.props;
59 39
60 return ( 40 return (
61 <View style={styles.container}> 41 <View style={styles.container}>
62 <PlustarSegment 42 <PlustarSegment
63 content={segment} 43 content={segment}
64 - selectedIndex={selectedIndex}  
65 - onPressSegment={this._onPressSegment} />  
66 - 44 + selectedIndex={activeTab}
  45 + onPressSegment={(index) => {
  46 + this._scrollView.goToPage(index);
  47 + this.props.onChangeTab && this.props.onChangeTab(index);
  48 + }}
  49 + />
67 <ScrollableTabView 50 <ScrollableTabView
68 ref={(c) => {this._scrollView = c}} 51 ref={(c) => {this._scrollView = c}}
69 renderTabBar={false} 52 renderTabBar={false}
70 - onChangeTab={this._onChangeTab}  
71 - onScroll={this._onScroll} >  
72 - 53 + onChangeTab={(tab) => {
  54 + this.props.onChangeTab && this.props.onChangeTab(tab.i);
  55 + }}
  56 + >
73 <PlustarList 57 <PlustarList
74 - dataSource={left.data} 58 + list={left.list}
75 head={left.head} 59 head={left.head}
76 foot={left.foot} 60 foot={left.foot}
77 - onPressRow={this._onPressRow} /> 61 + onPressRow={this._onPressRow}
  62 + />
78 <PlustarList 63 <PlustarList
79 - dataSource={right.data} 64 + list={right.list}
80 head={right.head} 65 head={right.head}
81 foot={right.foot} 66 foot={right.foot}
82 - onPressRow={this._onPressRow} />  
83 - 67 + onPressRow={this._onPressRow}
  68 + />
84 </ScrollableTabView> 69 </ScrollableTabView>
85 70
86 - {/*<PlustarGenderSelector visible={true} />*/} 71 + <LoadingIndicator
  72 + isVisible={isCurrentTabFetching}
  73 + />
87 </View> 74 </View>
88 -  
89 ); 75 );
90 } 76 }
91 -  
92 - _onPressSegment(index) {  
93 - this._scrollView.goToPage(index);  
94 - }  
95 -  
96 - _onChangeTab(tab, ref) {  
97 - if (this.props.selectedIndex != tab.i) {  
98 - this.props.dispatch(swithSegment(tab.i));  
99 - this.props.dispatch(fetchPlustarIfNeeded(tab.i));  
100 - }  
101 - }  
102 -  
103 - _onScroll(value) {  
104 - if(value < -0.12) {  
105 - this.props.dispatch(popViewController())  
106 - }  
107 - }  
108 -  
109 - _onPressRow(url) {  
110 - this.props.dispatch(plustarRouter(url))  
111 - }  
112 } 77 }
113 78
114 let styles = StyleSheet.create({ 79 let styles = StyleSheet.create({
@@ -116,9 +81,4 @@ let styles = StyleSheet.create({ @@ -116,9 +81,4 @@ let styles = StyleSheet.create({
116 flex: 1, 81 flex: 1,
117 backgroundColor: '#f0f0f0', 82 backgroundColor: '#f0f0f0',
118 }, 83 },
119 - centering: {  
120 - flex: 1,  
121 - alignItems: 'center',  
122 - justifyContent: 'center',  
123 - },  
124 }); 84 });
1 -/*  
2 - * 潮流优选性别选择框  
3 - */  
4 -  
5 -'use strict'  
6 -  
7 -import React, {Component} from 'react';  
8 -  
9 -import {  
10 - View,  
11 - Text,  
12 - Image,  
13 - ListView,  
14 - Modal,  
15 - TouchableWithoutFeedback,  
16 - StyleSheet,  
17 - Dimensions,  
18 - Animated  
19 -} from 'react-native';  
20 -  
21 -import uiUtil from '../../utils/UIUtil';  
22 -  
23 -import Button from '../common/Button';  
24 -  
25 -export default class PlustarGenderSelector extends Component {  
26 -  
27 - constructor(props) {  
28 - super(props);  
29 -  
30 - this._setModalVisible = this._setModalVisible.bind(this);  
31 - this._renderRow = this._renderRow.bind(this);  
32 - this._selectGender = this._selectGender.bind(this);  
33 -  
34 - const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});  
35 - const data = [{id:0, name:"All"}, {id:1, name:"Boy"}, {id:2, name:"Girl"}];  
36 - this.dataSource = ds.cloneWithRows(data);  
37 -  
38 - this.state = {  
39 - visible: this.props.visible  
40 - };  
41 - }  
42 -  
43 - render() {  
44 -  
45 - return (  
46 - <Modal visible={this.state.visible} transparent={false}>  
47 - <TouchableWithoutFeedback onPress={()=>{this._setModalVisible()}} >  
48 - <View style={styles.container} >  
49 - <Image style={styles.listContainer} source={{uri:"tc", isStatic:true}} >  
50 - <ListView  
51 - dataSource={this.dataSource}  
52 - renderRow={this._renderRow}  
53 - />  
54 - </Image>  
55 - </View>  
56 - </TouchableWithoutFeedback>  
57 - </Modal>  
58 - );  
59 -  
60 - }  
61 -  
62 - _renderRow(rowData: object, sectionID: number, rowID: number) {  
63 - return (  
64 - <TouchableWithoutFeedback onPress={this._selectGender(rowData.id)} >  
65 - <View style={styles.rowContainer}>  
66 -  
67 -  
68 - <Text style={styles.title} numberOfLines={1} >  
69 - {rowData.name}  
70 - </Text>  
71 -  
72 - <View style={styles.seprator} />  
73 -  
74 -  
75 - </View>  
76 - </TouchableWithoutFeedback>  
77 - );  
78 -  
79 - }  
80 -  
81 - _setModalVisible() {  
82 - this.setState({  
83 - visible: false,  
84 - });  
85 - }  
86 -  
87 - _pressRow(url) {  
88 - if (!this.props.onPressRow) {  
89 - return;  
90 - }  
91 -  
92 - this.props.onPressRow(url);  
93 - }  
94 -  
95 - _selectGender(id) {  
96 - if (!this.props.selectGender) {  
97 - return;  
98 - }  
99 -  
100 - this.props.selectGender(url);  
101 - }  
102 -  
103 -};  
104 -  
105 -PlustarGenderSelector.propTypes = {  
106 -  
107 -};  
108 -  
109 -let deviceWidth = uiUtil.screen().width;  
110 -let deviceHeight = uiUtil.screen().height;  
111 -let width = uiUtil.sizeOnScreenScale(120, 320);  
112 -let rowHeight = uiUtil.sizeOnScreenScale(44, 320);  
113 -let height = rowHeight * 3;  
114 -  
115 -let styles = StyleSheet.create({  
116 - container: {  
117 - width: deviceWidth,  
118 - height: deviceHeight,  
119 - backgroundColor: 'red'  
120 -  
121 - },  
122 - bgImage: {  
123 - width: width,  
124 - height: height,  
125 -  
126 - },  
127 - listContainer: {  
128 - width: width,  
129 - height: height,  
130 -  
131 - position:'absolute',  
132 - left: deviceWidth - width - 10,  
133 - top: 64  
134 - },  
135 - rowContainer: {  
136 - width: width,  
137 - height: rowHeight,  
138 - backgroundColor: 'transparent',  
139 - justifyContent: 'center',  
140 - alignItems: 'center',  
141 -  
142 - },  
143 - title: {  
144 -  
145 - alignItems: 'center',  
146 - alignSelf: 'center',  
147 - justifyContent: 'center',  
148 - width: width,  
149 - height: rowHeight - 1,  
150 - color: 'white',  
151 - fontSize: 15,  
152 - textAlign: 'center',  
153 - textAlignVertical: 'center',  
154 - backgroundColor: 'green',  
155 - position:'absolute',  
156 - // top: 0,  
157 - },  
158 - seprator: {  
159 - flex: 1,  
160 - width: width - 20,  
161 - height: 1,  
162 - backgroundColor: 'white',  
163 - }  
164 -});  
@@ -16,7 +16,10 @@ import ReactNative, { @@ -16,7 +16,10 @@ import ReactNative, {
16 StyleSheet, 16 StyleSheet,
17 } from 'react-native'; 17 } from 'react-native';
18 18
  19 +import ImmutablePropTypes from 'react-immutable-proptypes';
  20 +
19 import uiUtil from '../../utils/UIUtil'; 21 import uiUtil from '../../utils/UIUtil';
  22 +import Banner from './Banner';
20 import BannerView from '../common/BannerView'; 23 import BannerView from '../common/BannerView';
21 24
22 25
@@ -29,54 +32,35 @@ export default class PlustarList extends Component { @@ -29,54 +32,35 @@ export default class PlustarList extends Component {
29 this._renderHeader = this._renderHeader.bind(this); 32 this._renderHeader = this._renderHeader.bind(this);
30 this._renderFooter = this._renderFooter.bind(this); 33 this._renderFooter = this._renderFooter.bind(this);
31 this._pressRow = this._pressRow.bind(this); 34 this._pressRow = this._pressRow.bind(this);
32 - }  
33 -  
34 - render() {  
35 35
36 - if(!this.props.dataSource) {  
37 - return (  
38 - <View style={styles.listContainer} />  
39 - );  
40 - }  
41 -  
42 - const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1.id !== r2.id});  
43 - let dataSource = ds.cloneWithRows(this.props.dataSource);  
44 -  
45 - return (  
46 - <ListView  
47 - style={styles.listContainer}  
48 - dataSource={dataSource}  
49 - renderRow={this._renderRow}  
50 - renderHeader={this._renderHeader}  
51 - renderFooter={this._renderFooter}  
52 - initialListSize={3}  
53 - />  
54 - ); 36 + this.dataSource = new ListView.DataSource({
  37 + rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
  38 + });
55 } 39 }
56 40
57 _renderHeader() { 41 _renderHeader() {
58 let data = this.props.head; 42 let data = this.props.head;
59 43
60 - if(!data || data.length == 0) { 44 + if(!data || data.size == 0) {
61 return null; 45 return null;
62 } 46 }
63 47
64 return ( 48 return (
65 <View style={styles.rowContainer}> 49 <View style={styles.rowContainer}>
66 - <BannerView style={styles.bannerView} items={data} autoLooping={true} onSelectBanner={this._pressRow} /> 50 + <BannerView style={styles.bannerView} items={data.toJS()} autoLooping={true} onSelectBanner={this._pressRow} />
67 </View> 51 </View>
68 ); 52 );
69 } 53 }
70 54
71 _renderFooter() { 55 _renderFooter() {
72 let data = this.props.foot; 56 let data = this.props.foot;
73 - if(!data || data.length == 0) { 57 + if(!data || data.size == 0) {
74 return null; 58 return null;
75 } 59 }
76 60
77 return ( 61 return (
78 <View style={styles.rowContainer}> 62 <View style={styles.rowContainer}>
79 - <BannerView style={styles.bannerView} items={data} autoLooping={true} onSelectBanner={this._pressRow} /> 63 + <BannerView style={styles.bannerView} items={data.toJS()} autoLooping={true} onSelectBanner={this._pressRow} />
80 </View> 64 </View>
81 ); 65 );
82 } 66 }
@@ -97,9 +81,9 @@ export default class PlustarList extends Component { @@ -97,9 +81,9 @@ export default class PlustarList extends Component {
97 return ( 81 return (
98 <View style={styles.rowContainer}> 82 <View style={styles.rowContainer}>
99 83
100 - <BannerView style={styles.bannerView} items={rowData.data} onSelectBanner={this._pressRow} /> 84 + <BannerView style={styles.bannerView} items={rowData.get('data').toJS()} onSelectBanner={this._pressRow} />
101 85
102 - {text(rowData.brand_title)} 86 + {text(rowData.get('brand_title'))}
103 87
104 </View> 88 </View>
105 ); 89 );
@@ -107,36 +91,46 @@ export default class PlustarList extends Component { @@ -107,36 +91,46 @@ export default class PlustarList extends Component {
107 } 91 }
108 92
109 _pressRow(url: string) { 93 _pressRow(url: string) {
110 - if (!this.props.onPressRow) {  
111 - return; 94 + this.props.onPressRow && this.props.onPressRow(url);
112 } 95 }
113 96
114 - this.props.onPressRow(url); 97 + render() {
  98 + let data = this.props.list.toArray();
  99 + return (
  100 + <ListView
  101 + style={styles.listContainer}
  102 + enableEmptySections={true}
  103 + dataSource={this.dataSource.cloneWithRows(data)}
  104 + renderRow={this._renderRow}
  105 + renderHeader={this._renderHeader}
  106 + renderFooter={this._renderFooter}
  107 + />
  108 + );
115 } 109 }
116 110
117 } 111 }
118 112
119 PlustarList.propTypes = { 113 PlustarList.propTypes = {
120 - dataSource: React.PropTypes.arrayOf(  
121 - React.PropTypes.shape({ 114 + list: ImmutablePropTypes.listOf(
  115 + ImmutablePropTypes.contains({
122 id: React.PropTypes.string.isRequired, 116 id: React.PropTypes.string.isRequired,
123 brand_title: React.PropTypes.string.isRequired, 117 brand_title: React.PropTypes.string.isRequired,
124 - data: React.PropTypes.arrayOf(  
125 - React.PropTypes.shape({ 118 + data: ImmutablePropTypes.listOf(
  119 + ImmutablePropTypes.contains({
126 src: React.PropTypes.string.isRequired, 120 src: React.PropTypes.string.isRequired,
127 url: React.PropTypes.string.isRequired, 121 url: React.PropTypes.string.isRequired,
128 }) 122 })
129 ) 123 )
130 }) 124 })
131 ), 125 ),
132 - head: React.PropTypes.arrayOf(  
133 - React.PropTypes.shape({ 126 + head: ImmutablePropTypes.listOf(
  127 + ImmutablePropTypes.contains({
134 src: React.PropTypes.string.isRequired, 128 src: React.PropTypes.string.isRequired,
135 url: React.PropTypes.string.isRequired, 129 url: React.PropTypes.string.isRequired,
136 }) 130 })
137 ), 131 ),
138 - foot: React.PropTypes.arrayOf(  
139 - React.PropTypes.shape({ 132 + foot: ImmutablePropTypes.listOf(
  133 + ImmutablePropTypes.contains({
140 src: React.PropTypes.string.isRequired, 134 src: React.PropTypes.string.isRequired,
141 url: React.PropTypes.string.isRequired, 135 url: React.PropTypes.string.isRequired,
142 }) 136 })
@@ -16,6 +16,8 @@ import { @@ -16,6 +16,8 @@ import {
16 Animated 16 Animated
17 } from 'react-native'; 17 } from 'react-native';
18 18
  19 +import ImmutablePropTypes from 'react-immutable-proptypes';
  20 +
19 import uiUtil from '../../utils/UIUtil'; 21 import uiUtil from '../../utils/UIUtil';
20 22
21 import Button from '../common/Button'; 23 import Button from '../common/Button';
@@ -79,12 +81,16 @@ export default class PlustarSegment extends Component { @@ -79,12 +81,16 @@ export default class PlustarSegment extends Component {
79 }; 81 };
80 82
81 PlustarSegment.propTypes = { 83 PlustarSegment.propTypes = {
82 - content: React.PropTypes.arrayOf(  
83 - React.PropTypes.shape({ 84 + content: ImmutablePropTypes.contains({
  85 + 0: ImmutablePropTypes.contains({
  86 + title: React.PropTypes.string.isRequired,
  87 + type: React.PropTypes.number,
  88 + }),
  89 + 1: ImmutablePropTypes.contains({
84 title: React.PropTypes.string.isRequired, 90 title: React.PropTypes.string.isRequired,
85 - type: React.PropTypes.number.isRequired, 91 + type: React.PropTypes.number,
86 }) 92 })
87 - ), 93 + }),
88 selectedIndex: React.PropTypes.oneOf([0, 1]), 94 selectedIndex: React.PropTypes.oneOf([0, 1]),
89 onPressSegment: React.PropTypes.func, 95 onPressSegment: React.PropTypes.func,
90 }; 96 };
@@ -5,16 +5,15 @@ export default keyMirror({ @@ -5,16 +5,15 @@ export default keyMirror({
5 SET_PLATFORM: null, 5 SET_PLATFORM: null,
6 SET_CHANNEL: null, 6 SET_CHANNEL: null,
7 SET_SEGMENT: null, 7 SET_SEGMENT: null,
  8 + SET_GENDER: null,
8 9
9 PLUSTAR_LIST_REQUEST: null, 10 PLUSTAR_LIST_REQUEST: null,
10 PLUSTAR_LIST_SUCCESS: null, 11 PLUSTAR_LIST_SUCCESS: null,
11 PLUSTAR_LIST_FAILURE: null, 12 PLUSTAR_LIST_FAILURE: null,
12 13
13 -}); 14 + SWITCH_SEGMENT: null,
  15 + SWITCH_GENDER: null,
  16 +
  17 + JUMP_WITH_URL: null,
14 18
15 -export const ROUTE_PLUSATAR = 'ROUTE_PLUSATAR';  
16 -export const ROUTE_POP_VIEW_CONTROLLER = 'ROUTE_POP_VIEW_CONTROLLER';  
17 -export const REQUEST_PLASTAR_DATA = 'REQUEST_PLASTAR_DATA';  
18 -export const RECEIVE_PLASTAR_DATA = 'RECEIVE_PLASTAR_DATA';  
19 -export const SWITCH_SEGMENT = 'SWITCH_SEGMENT';  
20 -export const SWITCH_GENDER = 'SWITCH_GENDER'; 19 +});
@@ -8,6 +8,7 @@ import { @@ -8,6 +8,7 @@ import {
8 View, 8 View,
9 NativeModules, 9 NativeModules,
10 InteractionManager, 10 InteractionManager,
  11 + NativeAppEventEmitter,
11 } from 'react-native' 12 } from 'react-native'
12 13
13 import {bindActionCreators} from 'redux'; 14 import {bindActionCreators} from 'redux';
@@ -21,15 +22,8 @@ const actions = [ @@ -21,15 +22,8 @@ const actions = [
21 ]; 22 ];
22 23
23 function mapStateToProps(state) { 24 function mapStateToProps(state) {
24 - let { plustar } = state;  
25 - let {left, right, segment, activeTab, genderType} = plustar;  
26 -  
27 return { 25 return {
28 - left,  
29 - right,  
30 - segment,  
31 - activeTab,  
32 - genderType, 26 + ...state
33 }; 27 };
34 } 28 }
35 29
@@ -50,7 +44,6 @@ class PlustarContainer extends Component { @@ -50,7 +44,6 @@ class PlustarContainer extends Component {
50 constructor(props) { 44 constructor(props) {
51 super(props); 45 super(props);
52 46
53 - this._onPressSegment = this._onPressSegment.bind(this);  
54 this._onChangeTab = this._onChangeTab.bind(this); 47 this._onChangeTab = this._onChangeTab.bind(this);
55 this._onPressRow = this._onPressRow.bind(this); 48 this._onPressRow = this._onPressRow.bind(this);
56 49
@@ -59,53 +52,56 @@ class PlustarContainer extends Component { @@ -59,53 +52,56 @@ class PlustarContainer extends Component {
59 52
60 componentDidMount() { 53 componentDidMount() {
61 this.subscription = NativeAppEventEmitter.addListener( 54 this.subscription = NativeAppEventEmitter.addListener(
62 - "onChangeGender", 55 + "GenderChangeReminder",
63 (reminder) => { 56 (reminder) => {
64 - this.props.dispatch(switchGender(reminder.genderType)); 57 + this.props.actions.switchGender(reminder.genderType);
  58 + this.props.actions.plustarList(0, true);
  59 + this.props.actions.plustarList(1, true);
65 } 60 }
66 ); 61 );
67 62
68 - this.props.dispatch(plustarList(0));  
69 - this.props.dispatch(plustarList(1)); 63 + this.props.actions.plustarList(0);
  64 + this.props.actions.plustarList(1);
70 } 65 }
71 66
72 componentWillUnmount() { 67 componentWillUnmount() {
73 this.subscription && this.subscription.remove(); 68 this.subscription && this.subscription.remove();
74 } 69 }
75 70
76 - _onPressSegment(index) {  
77 - this._scrollView.goToPage(index);  
78 - }  
79 -  
80 - _onChangeTab(tab, ref) {  
81 - if (this.props.selectedIndex != tab.i) {  
82 - this.props.dispatch(swithSegment(tab.i));  
83 - this.props.dispatch(fetchPlustarIfNeeded(tab.i)); 71 + _onChangeTab(i) {
  72 + if (this.props.activeTab != i) {
  73 + this.props.actions.swithSegment(i);
  74 + this.props.actions.plustarList(i);
84 } 75 }
85 } 76 }
86 77
87 _onPressRow(url) { 78 _onPressRow(url) {
88 - this.props.dispatch(plustarRouter(url)) 79 + this.props.actions.jumpWithUrl(url);
89 } 80 }
90 81
91 render() { 82 render() {
92 -  
93 - 83 + let {plustar} = this.props;
  84 + let {segment, activeTab} = plustar;
  85 + let key = activeTab + '';
  86 + let isCurrentTabFetching = plustar.get(key).isFetching;
94 return ( 87 return (
95 <View style={styles.container}> 88 <View style={styles.container}>
96 - 89 + <Plustar
  90 + segment={segment}
  91 + activeTab={activeTab}
  92 + left={plustar.get('0')}
  93 + right={plustar.get('1')}
  94 + isCurrentTabFetching={isCurrentTabFetching}
  95 + onChangeTab={this._onChangeTab}
  96 + onPressRow={this._onPressRow}
  97 + />
97 </View> 98 </View>
98 ); 99 );
99 } 100 }
100 } 101 }
101 102
102 -let {width, height} = Dimensions.get('window');  
103 -let navbarHeight = (Platform.OS === 'android') ? 50 : 64;  
104 -  
105 let styles = StyleSheet.create({ 103 let styles = StyleSheet.create({
106 container: { 104 container: {
107 - top: navbarHeight,  
108 - marginBottom: navbarHeight,  
109 flex: 1, 105 flex: 1,
110 }, 106 },
111 107
1 'use strict'; 1 'use strict';
2 2
  3 +import ReactNative from 'react-native';
3 import PlustarService from '../../services/PlustarService'; 4 import PlustarService from '../../services/PlustarService';
4 5
5 const { 6 const {
6 SET_SEGMENT, 7 SET_SEGMENT,
  8 + SET_GENDER,
7 PLUSTAR_LIST_REQUEST, 9 PLUSTAR_LIST_REQUEST,
8 PLUSTAR_LIST_SUCCESS, 10 PLUSTAR_LIST_SUCCESS,
9 PLUSTAR_LIST_FAILURE, 11 PLUSTAR_LIST_FAILURE,
  12 + SWITCH_SEGMENT,
  13 + SWITCH_GENDER,
  14 + JUMP_WITH_URL,
10 } = require('../../constants/actionTypes').default; 15 } = require('../../constants/actionTypes').default;
11 16
12 -export function setSegment(segmentType) { 17 +export function setSegment(segment) {
13 return { 18 return {
14 type: SET_SEGMENT, 19 type: SET_SEGMENT,
15 - payload: segmentType, 20 + payload: segment,
16 }; 21 };
17 } 22 }
18 23
19 -export function plustarListRequest() { 24 +export function setGender(gender) {
  25 + return {
  26 + type: SET_GENDER,
  27 + payload: gender,
  28 + };
  29 +}
  30 +
  31 +export function swithSegment(activeTab) {
  32 + return (dispatch, getState) => {
  33 +
  34 + const {plustar} = getState();
  35 + if(activeTab == plustar.activeTab) {
  36 + return;
  37 + }
  38 +
  39 + dispatch({
  40 + type: SWITCH_SEGMENT,
  41 + payload: activeTab
  42 + });
  43 + };
  44 +}
  45 +
  46 +export function switchGender(genderType) {
  47 + return (dispatch, getState) => {
  48 +
  49 + const {plustar} = getState();
  50 + if(genderType == plustar.genderType) {
  51 + return;
  52 + }
  53 +
  54 + dispatch({
  55 + type: SWITCH_GENDER,
  56 + payload: genderType
  57 + });
  58 + };
  59 +}
  60 +
  61 +export function plustarListRequest(key) {
20 return { 62 return {
21 type: PLUSTAR_LIST_REQUEST, 63 type: PLUSTAR_LIST_REQUEST,
  64 + payload: key
22 }; 65 };
23 } 66 }
24 67
25 -export function plustarListSuccess(json) { 68 +export function plustarListSuccess(json, key) {
26 return { 69 return {
27 type: PLUSTAR_LIST_SUCCESS, 70 type: PLUSTAR_LIST_SUCCESS,
28 - payload: json 71 + payload: {...json, key}
29 }; 72 };
30 } 73 }
31 74
32 -export function plustarListFailure(error) { 75 +export function plustarListFailure(error, key) {
33 return { 76 return {
34 type: PLUSTAR_LIST_FAILURE, 77 type: PLUSTAR_LIST_FAILURE,
35 - payload: error 78 + payload: {error, key}
36 }; 79 };
37 } 80 }
38 81
39 -export function plustarList(activeTab, gender) { 82 +/*
  83 + * index number 请求数据的index
  84 + * reload bool 是否需要强制重新请求数据,
  85 + */
  86 +export function plustarList(index, reload = false) {
40 return (dispatch, getState) => { 87 return (dispatch, getState) => {
41 let {app, plustar} = getState(); 88 let {app, plustar} = getState();
42 - let {activeTab, segment} = plustar;  
43 - let item = plustar.get(activeTab);  
44 - if (item.isFetching) { 89 + let key = index + '';
  90 + let item = plustar.get(key);
  91 + if (reload) {
  92 + // 强制刷新数据
  93 +
  94 + } else {
  95 + if (item.isFetching || item.list.size > 0) {
45 return; 96 return;
46 } 97 }
  98 + }
47 99
48 - dispatch(plustarListRequest()); 100 + dispatch(plustarListRequest(key));
49 101
50 - let brandType = segment.get(activeTab).type;  
51 - let gender = item.genderType;  
52 - return new PlustarService().fetchList(brandType, gender) 102 + let {segment, gender} = plustar;
  103 + let brandType = segment.get(key).type;
  104 + let options = {};
  105 + // 如果gender>0,接口请求需要区分男女,需要传递gender参数
  106 + if (gender > 0) {
  107 + options = {gender};
  108 + }
  109 + return new PlustarService().fetchList(brandType, options)
53 .then(json => { 110 .then(json => {
54 let payload = parsePlustarList(json); 111 let payload = parsePlustarList(json);
55 - dispatch(plustarListSuccess(payload)); 112 + dispatch(plustarListSuccess(payload, key));
56 }) 113 })
57 .catch(error => { 114 .catch(error => {
58 - dispatch(plustarListFailure(error)); 115 + dispatch(plustarListFailure(error, key));
59 }); 116 });
60 }; 117 };
61 } 118 }
62 119
63 function parsePlustarList(json) { 120 function parsePlustarList(json) {
  121 + let {brand_type, brand_type_name, data} = json;
  122 +
64 let parseListData = (list) => { 123 let parseListData = (list) => {
  124 + if (!Array.isArray(list) || list.length == 0) {
  125 + return [];
  126 + }
  127 +
65 let allData = []; 128 let allData = [];
66 - let length = list.length;  
67 - for(let i = 0; i < length; i++) {  
68 - let data = list[i].data; 129 + list.map((item, i) => {
  130 + let {data} = item;
  131 + if (data && data.length > 0) {
69 allData = [...allData, ...data]; 132 allData = [...allData, ...data];
70 } 133 }
  134 + });
  135 +
71 return allData; 136 return allData;
72 } 137 }
73 138
74 - let header = parseListData(json.head);  
75 - let footer = parseListData(json.foot);  
76 - let list = parseListData(json.list); 139 + let head = parseListData(data.head);
  140 + let foot = parseListData(data.foot);
  141 + let list = parseListData(data.list);
77 142
78 return { 143 return {
79 - header,  
80 - footer, 144 + head,
  145 + foot,
81 list, 146 list,
82 }; 147 };
83 } 148 }
84 149
85 -export function plustarRouter(url) {  
86 -  
87 - RouterManager.jumpWithUrl(url, null); 150 +export function jumpWithUrl(url) {
  151 + ReactNative.NativeModules.YH_PlustarHelper.jumpWithUrl(url);
88 return { 152 return {
89 - type: types.ROUTE_PLUSATAR,  
90 - };  
91 -}  
92 -  
93 -export function popViewController() {  
94 -  
95 - RouterManager.popViewController();  
96 - return {  
97 - type: types.ROUTE_POP_VIEW_CONTROLLER,  
98 - };  
99 -}  
100 -  
101 -export function switchGender(genderType) {  
102 - return (dispatch, getState) => {  
103 -  
104 - const {plustar} = getState();  
105 - if(genderType == plustar.payload.genderType) {  
106 - return;  
107 - }  
108 -  
109 - dispatch({  
110 - type: types.SWITCH_GENDER,  
111 - payload: {  
112 - genderType,  
113 - }  
114 - });  
115 -  
116 - dispatch(fetchPlustarIfNeeded(0, genderType));  
117 - dispatch(fetchPlustarIfNeeded(1, genderType)); 153 + type: JUMP_WITH_URL,
  154 + payload: url
118 }; 155 };
119 } 156 }
120 157
121 -export function swithSegment(selectedIndex) {  
122 158
123 - return (dispatch, getState) => {  
124 -  
125 - const {plustar} = getState();  
126 - if(selectedIndex == plustar.payload.selectedIndex) {  
127 - return;  
128 - }  
129 -  
130 - dispatch({  
131 - type: types.SWITCH_SEGMENT,  
132 - payload: {  
133 - selectedIndex,  
134 - }  
135 - });  
136 - };  
137 -}  
138 159
139 export function fetchPlustarIfNeeded(index, gender=null) { 160 export function fetchPlustarIfNeeded(index, gender=null) {
140 161
@@ -4,19 +4,19 @@ import {Record, List, Map} from 'immutable'; @@ -4,19 +4,19 @@ import {Record, List, Map} from 'immutable';
4 4
5 let InitialState = Record({ 5 let InitialState = Record({
6 activeTab: 0, 6 activeTab: 0,
7 - genderType: 0, 7 + gender: -1,
8 0: new (Record({ 8 0: new (Record({
9 isFetching: false, 9 isFetching: false,
10 error: null, 10 error: null,
11 - header: List(),  
12 - footer: List(), 11 + head: List(),
  12 + foot: List(),
13 list: List(), 13 list: List(),
14 })), 14 })),
15 1: new (Record({ 15 1: new (Record({
16 isFetching: false, 16 isFetching: false,
17 error: null, 17 error: null,
18 - header: List(),  
19 - footer: List(), 18 + head: List(),
  19 + foot: List(),
20 list: List(), 20 list: List(),
21 })), 21 })),
22 segment: null, 22 segment: null,
1 'use strict'; 1 'use strict';
2 2
3 import InitialState from './plustarInitialState'; 3 import InitialState from './plustarInitialState';
  4 +import Immutable, {Map} from 'immutable';
4 5
5 const { 6 const {
6 SET_SEGMENT, 7 SET_SEGMENT,
  8 + SET_GENDER,
7 PLUSTAR_LIST_REQUEST, 9 PLUSTAR_LIST_REQUEST,
8 PLUSTAR_LIST_SUCCESS, 10 PLUSTAR_LIST_SUCCESS,
9 PLUSTAR_LIST_FAILURE, 11 PLUSTAR_LIST_FAILURE,
  12 + SWITCH_SEGMENT,
  13 + SWITCH_GENDER,
10 } = require('../../constants/actionTypes').default; 14 } = require('../../constants/actionTypes').default;
11 15
12 const initialState = new InitialState; 16 const initialState = new InitialState;
@@ -18,41 +22,38 @@ export default function plustarReducer(state=initialState, action) { @@ -18,41 +22,38 @@ export default function plustarReducer(state=initialState, action) {
18 } 22 }
19 23
20 case PLUSTAR_LIST_REQUEST: { 24 case PLUSTAR_LIST_REQUEST: {
21 - let key = getKeyFromActiveTab(state.activeTab); 25 + let key = action.payload;
22 26
23 return state.setIn([key, 'isFetching'], true) 27 return state.setIn([key, 'isFetching'], true)
24 .setIn([key, 'error'], null); 28 .setIn([key, 'error'], null);
25 } 29 }
26 30
27 case PLUSTAR_LIST_SUCCESS: { 31 case PLUSTAR_LIST_SUCCESS: {
28 - let {header, footer, list} = action.payload;  
29 - let key = getKeyFromActiveTab(state.activeTab); 32 + let {head, foot, list, key} = action.payload;
30 33
31 - return state.setIn([key, 'isFetching'], true) 34 + return state.setIn([key, 'isFetching'], false)
32 .setIn([key, 'error'], null) 35 .setIn([key, 'error'], null)
33 - .setIn([key, 'header'], header)  
34 - .setIn([key, 'footer'], footer)  
35 - .setIn([key, 'list'], list); 36 + .setIn([key, 'head'], Immutable.fromJS(head))
  37 + .setIn([key, 'foot'], Immutable.fromJS(foot))
  38 + .setIn([key, 'list'], Immutable.fromJS(list));
36 } 39 }
37 40
38 case PLUSTAR_LIST_FAILURE: { 41 case PLUSTAR_LIST_FAILURE: {
39 - let key = getKeyFromActiveTab(state.activeTab); 42 + let {error, key} = action.payload;
40 43
41 - return state.setIn([key, 'isFetching'], true)  
42 - .setIn([key, 'error'], action.payload);  
43 - } 44 + return state.setIn([key, 'isFetching'], false)
  45 + .setIn([key, 'error'], error);
44 } 46 }
45 47
46 - return state;  
47 -} 48 + case SWITCH_SEGMENT: {
  49 + return state.set('activeTab', action.payload);
  50 + }
48 51
49 -function getKeyFromActiveTab(activeTab) {  
50 - let key = 'left';  
51 - if (activeTab == 0) {  
52 - key = '0';  
53 - } else if (activeTab == 1) {  
54 - key = '1'; 52 + case SET_GENDER:
  53 + case SWITCH_GENDER: {
  54 + return state.set('gender', action.payload);
  55 + }
55 } 56 }
56 57
57 - return key; 58 + return state;
58 } 59 }
@@ -9,12 +9,12 @@ export default class PlustarService { @@ -9,12 +9,12 @@ export default class PlustarService {
9 this.api = new Request(baseURL); 9 this.api = new Request(baseURL);
10 } 10 }
11 11
12 - async fetchList(brand_type, gender) { 12 + async fetchList(brand_type, options) {
13 return await this.api.get({ 13 return await this.api.get({
14 url: '/guang/api/v3/plustar/getlist', 14 url: '/guang/api/v3/plustar/getlist',
15 body: { 15 body: {
16 brand_type, 16 brand_type,
17 - gender, 17 + ...options,
18 } 18 }
19 }) 19 })
20 .then((json) => { 20 .then((json) => {
@@ -13,8 +13,8 @@ @@ -13,8 +13,8 @@
13 "moment": "^2.13.0", 13 "moment": "^2.13.0",
14 "object-assign": "^4.1.0", 14 "object-assign": "^4.1.0",
15 "query-string": "^4.2.2", 15 "query-string": "^4.2.2",
16 - "react": "15.3.0",  
17 - "react-immutable-proptypes": "^1.7.1", 16 + "react": "^15.3.1",
  17 + "react-immutable-proptypes": "^2.1.0",
18 "react-native": "0.32.0", 18 "react-native": "0.32.0",
19 "react-native-device-info": "^0.9.3", 19 "react-native-device-info": "^0.9.3",
20 "react-native-fabric": "0.2.2", 20 "react-native-fabric": "0.2.2",
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 "react-native-router-flux": "^3.32.0", 22 "react-native-router-flux": "^3.32.0",
23 "react-native-scrollable-mixin": "^1.0.1", 23 "react-native-scrollable-mixin": "^1.0.1",
24 "react-native-simple-store": "^1.0.1", 24 "react-native-simple-store": "^1.0.1",
25 - "react-native-swiper": "^1.4.7", 25 + "react-native-swiper": "^1.4.11",
26 "react-redux": "^4.4.5", 26 "react-redux": "^4.4.5",
27 "react-static-container": "^1.0.1", 27 "react-static-container": "^1.0.1",
28 "react-timer-mixin": "^0.13.3", 28 "react-timer-mixin": "^0.13.3",