Merge branch '5.4' of http://git.yoho.cn/mobile/YH_RNComponent into local
Showing
34 changed files
with
923 additions
and
501 deletions
@@ -10,6 +10,9 @@ import Classify from './classify/Classify'; | @@ -10,6 +10,9 @@ import Classify from './classify/Classify'; | ||
10 | import Seckill from './seckill/Seckill'; | 10 | import Seckill from './seckill/Seckill'; |
11 | import Guang from './guang/Guang'; | 11 | import Guang from './guang/Guang'; |
12 | 12 | ||
13 | +import Message from './message/Message'; | ||
14 | +import NewArrival from './newArrival/NewArrival'; | ||
15 | + | ||
13 | // import Search from './search/Search'; | 16 | // import Search from './search/Search'; |
14 | 17 | ||
15 | export default function native(platform) { | 18 | export default function native(platform) { |
@@ -19,7 +22,8 @@ export default function native(platform) { | @@ -19,7 +22,8 @@ export default function native(platform) { | ||
19 | Seckill(platform); | 22 | Seckill(platform); |
20 | Guang(platform); | 23 | Guang(platform); |
21 | Plustar(platform); | 24 | Plustar(platform); |
22 | - | 25 | + Message(platform) |
26 | + NewArrival(NewArrival) | ||
23 | 27 | ||
24 | if (Platform.OS === 'ios') { | 28 | if (Platform.OS === 'ios') { |
25 | Community(platform); | 29 | Community(platform); |
@@ -123,7 +123,6 @@ export default function brandStoreReducer(state=initialState, action) { | @@ -123,7 +123,6 @@ export default function brandStoreReducer(state=initialState, action) { | ||
123 | .set('is_show_shop_name', is_show_shop_name) | 123 | .set('is_show_shop_name', is_show_shop_name) |
124 | .set('shop_domain', shop_domain) | 124 | .set('shop_domain', shop_domain) |
125 | .set('shops_id', shops_id) | 125 | .set('shops_id', shops_id) |
126 | - .set('is_addFav',false); | ||
127 | let nextState = state.set('info', info); | 126 | let nextState = state.set('info', info); |
128 | return nextState; | 127 | return nextState; |
129 | } | 128 | } |
@@ -41,21 +41,17 @@ export default class BannerReourceList extends React.Component { | @@ -41,21 +41,17 @@ export default class BannerReourceList extends React.Component { | ||
41 | <TouchableOpacity activeOpacity={0.5} onPress={() => { | 41 | <TouchableOpacity activeOpacity={0.5} onPress={() => { |
42 | this.props.onPressSlideItem && this.props.onPressSlideItem(rowData, rowID); | 42 | this.props.onPressSlideItem && this.props.onPressSlideItem(rowData, rowID); |
43 | }}> | 43 | }}> |
44 | - <View style={styles.row}> | ||
45 | - <View style={styles.thumbnailV}> | ||
46 | - <Image | ||
47 | - source={{uri: newSrc}} | ||
48 | - style={styles.thumbnail} | ||
49 | - resizeMode={'contain'} | ||
50 | - > | ||
51 | - <View style={styles.textV}> | ||
52 | - <Text style={styles.text} numberOfLines={1}> | ||
53 | - {rowData.name} | ||
54 | - </Text> | ||
55 | - </View> | ||
56 | - </Image> | ||
57 | - | ||
58 | - </View> | 44 | + <View style={styles.thumbnailV}> |
45 | + <Image | ||
46 | + source={{uri: newSrc}} | ||
47 | + style={styles.thumbnail} | ||
48 | + resizeMode={'contain'} | ||
49 | + ></Image> | ||
50 | + <View style={styles.textV}> | ||
51 | + <Text style={styles.text} numberOfLines={1}> | ||
52 | + {rowData.name} | ||
53 | + </Text> | ||
54 | + </View> | ||
59 | </View> | 55 | </View> |
60 | </TouchableOpacity> | 56 | </TouchableOpacity> |
61 | ); | 57 | ); |
@@ -113,14 +109,9 @@ let styles = StyleSheet.create({ | @@ -113,14 +109,9 @@ let styles = StyleSheet.create({ | ||
113 | width:Dimensions.get('window').width, | 109 | width:Dimensions.get('window').width, |
114 | backgroundColor: 'white', | 110 | backgroundColor: 'white', |
115 | }, | 111 | }, |
116 | - row: { | ||
117 | - marginLeft: 10, | ||
118 | - width: itemWidth, | ||
119 | - height: itemWidth, | ||
120 | - backgroundColor: 'white', | ||
121 | - }, | ||
122 | textV: { | 112 | textV: { |
123 | - marginTop: itemHeight - 20, | 113 | + position: 'absolute', |
114 | + top: itemHeight - 20, | ||
124 | width: itemWidth, | 115 | width: itemWidth, |
125 | alignItems: 'center', | 116 | alignItems: 'center', |
126 | height: 20, | 117 | height: 20, |
@@ -140,6 +131,7 @@ let styles = StyleSheet.create({ | @@ -140,6 +131,7 @@ let styles = StyleSheet.create({ | ||
140 | fontWeight: 'bold', | 131 | fontWeight: 'bold', |
141 | }, | 132 | }, |
142 | thumbnailV: { | 133 | thumbnailV: { |
134 | + marginLeft: 10, | ||
143 | width: itemWidth, | 135 | width: itemWidth, |
144 | height: itemHeight, | 136 | height: itemHeight, |
145 | backgroundColor: 'white', | 137 | backgroundColor: 'white', |
js/message/Message.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +import React from 'react'; | ||
4 | +import ReactNative, { | ||
5 | + AppRegistry, | ||
6 | + Platform, | ||
7 | +} from 'react-native'; | ||
8 | + | ||
9 | +import { | ||
10 | + Provider, | ||
11 | + connect | ||
12 | +} from 'react-redux'; | ||
13 | + | ||
14 | +import configureStore from './store/configureStore'; | ||
15 | +import {Record, List, Map} from 'immutable'; | ||
16 | + | ||
17 | +import appInitialState from './reducers/app/appInitialState'; | ||
18 | +import messageInitialState from './reducers/message/messageInitialState'; | ||
19 | + | ||
20 | +import MessageContainer from './containers/MessageContainer'; | ||
21 | + | ||
22 | +import { | ||
23 | + setPlatform, | ||
24 | + setHost, | ||
25 | + setServiceHost, | ||
26 | +} from './reducers/app/appActions'; | ||
27 | + | ||
28 | + | ||
29 | +function getInitialState() { | ||
30 | + const _initState = { | ||
31 | + app: (new appInitialState()), | ||
32 | + message: (new messageInitialState()), | ||
33 | + }; | ||
34 | + return _initState; | ||
35 | +} | ||
36 | + | ||
37 | +export default function native(platform) { | ||
38 | + | ||
39 | + let YH_Message = React.createClass({ | ||
40 | + | ||
41 | + render() { | ||
42 | + const store = configureStore(getInitialState()); | ||
43 | + store.dispatch(setPlatform(platform)); | ||
44 | + store.dispatch(setHost(this.props.host)); | ||
45 | + store.dispatch(setServiceHost(this.props.serviceHost)); | ||
46 | + | ||
47 | + return ( | ||
48 | + <Provider store={store}> | ||
49 | + <MessageContainer /> | ||
50 | + </Provider> | ||
51 | + ); | ||
52 | + } | ||
53 | + }); | ||
54 | + | ||
55 | + AppRegistry.registerComponent('YH_Message', () => YH_Message); | ||
56 | +} |
js/message/components/message/Message.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +import React, {Component} from 'react'; | ||
4 | +import ReactNative, { | ||
5 | + View, | ||
6 | + Text, | ||
7 | + Image, | ||
8 | + ListView, | ||
9 | + StyleSheet, | ||
10 | + Dimensions, | ||
11 | + TouchableOpacity, | ||
12 | + InteractionManager, | ||
13 | + Platform, | ||
14 | +} from 'react-native'; | ||
15 | + | ||
16 | + | ||
17 | + | ||
18 | +export default class Message extends Component { | ||
19 | + | ||
20 | + constructor(props) { | ||
21 | + super(props); | ||
22 | + | ||
23 | + this._renderRow = this._renderRow.bind(this); | ||
24 | + | ||
25 | + this.dataSource = new ListView.DataSource({ | ||
26 | + rowHasChanged: (r1, r2) => !Immutable.is(r1, r2), | ||
27 | + }); | ||
28 | + } | ||
29 | + | ||
30 | + componentDidMount() { | ||
31 | + | ||
32 | + } | ||
33 | + | ||
34 | + _renderRow(rowData: object, sectionID: number, rowID: number) { | ||
35 | + | ||
36 | + return ( | ||
37 | + <TouchableOpacity | ||
38 | + onPress={() => { | ||
39 | + console.log(rowID) | ||
40 | + }} | ||
41 | + > | ||
42 | + <View style={styles.rowContainer}> | ||
43 | + <Text>{rowData.get('title')}</Text> | ||
44 | + <Text>{rowData.get('detail')}</Text> | ||
45 | + </View> | ||
46 | + </TouchableOpacity> | ||
47 | + ); | ||
48 | + } | ||
49 | + | ||
50 | + | ||
51 | + render() { | ||
52 | + | ||
53 | + let dataSource = this.props.data.dataSource.toArray(); | ||
54 | + | ||
55 | + return ( | ||
56 | + <View style={styles.container}> | ||
57 | + <ListView | ||
58 | + contentContainerStyle={styles.contentContainer} | ||
59 | + dataSource={this.dataSource.cloneWithRows(dataSource)} | ||
60 | + renderRow={this._renderRow} | ||
61 | + enableEmptySections={true} | ||
62 | + /> | ||
63 | + </View> | ||
64 | + ); | ||
65 | + } | ||
66 | +} | ||
67 | + | ||
68 | +let {width, height} = Dimensions.get('window'); | ||
69 | + | ||
70 | +let styles = StyleSheet.create({ | ||
71 | + container: { | ||
72 | + flex: 1, | ||
73 | + backgroundColor: '#f0f0f0', | ||
74 | + }, | ||
75 | + contentContainer: { | ||
76 | + | ||
77 | + }, | ||
78 | + rowContainer: { | ||
79 | + | ||
80 | + }, | ||
81 | +}); |
js/message/constants/actionTypes.js
0 → 100644
js/message/containers/MessageContainer.js
0 → 100644
1 | +'use strict' | ||
2 | + | ||
3 | +import React, {Component} from 'react'; | ||
4 | +import ReactNative, { | ||
5 | + StyleSheet, | ||
6 | + Dimensions, | ||
7 | + Platform, | ||
8 | + View, | ||
9 | + Text, | ||
10 | + NativeModules, | ||
11 | + InteractionManager, | ||
12 | + NativeAppEventEmitter, | ||
13 | +} from 'react-native' | ||
14 | + | ||
15 | +import {bindActionCreators} from 'redux'; | ||
16 | +import {connect} from 'react-redux'; | ||
17 | +import {Map} from 'immutable'; | ||
18 | +import * as messageActions from '../reducers/message/messageActions'; | ||
19 | + | ||
20 | +import Message from '../components/message/Message'; | ||
21 | + | ||
22 | + | ||
23 | +const actions = [ | ||
24 | + messageActions, | ||
25 | +]; | ||
26 | + | ||
27 | +function mapStateToProps(state) { | ||
28 | + return { | ||
29 | + ...state | ||
30 | + }; | ||
31 | +} | ||
32 | + | ||
33 | +function mapDispatchToProps(dispatch) { | ||
34 | + | ||
35 | + const creators = Map() | ||
36 | + .merge(...actions) | ||
37 | + .filter(value => typeof value === 'function') | ||
38 | + .toObject(); | ||
39 | + | ||
40 | + return { | ||
41 | + actions: bindActionCreators(creators, dispatch), | ||
42 | + dispatch | ||
43 | + }; | ||
44 | +} | ||
45 | + | ||
46 | +class MessageContainer extends Component { | ||
47 | + constructor(props) { | ||
48 | + super(props); | ||
49 | + | ||
50 | + this._onRefresh = this._onRefresh.bind(this); | ||
51 | + | ||
52 | + | ||
53 | + } | ||
54 | + | ||
55 | + componentDidMount() { | ||
56 | + | ||
57 | + } | ||
58 | + | ||
59 | + componentWillUnmount() { | ||
60 | + | ||
61 | + } | ||
62 | + | ||
63 | + _onRefresh() { | ||
64 | + | ||
65 | + } | ||
66 | + | ||
67 | + render() { | ||
68 | + let {message} = this.props; | ||
69 | + return ( | ||
70 | + <View style={styles.container}> | ||
71 | + <Message | ||
72 | + data={message} | ||
73 | + onRefresh={this._onRefresh} | ||
74 | + /> | ||
75 | + </View> | ||
76 | + ); | ||
77 | + } | ||
78 | +} | ||
79 | + | ||
80 | +let styles = StyleSheet.create({ | ||
81 | + container: { | ||
82 | + flex: 1, | ||
83 | + }, | ||
84 | + | ||
85 | +}); | ||
86 | + | ||
87 | +export default connect(mapStateToProps, mapDispatchToProps)(MessageContainer); |
js/message/reducers/app/appActions.js
0 → 100755
1 | +'use strict'; | ||
2 | + | ||
3 | +import ReactNative from 'react-native'; | ||
4 | + | ||
5 | +const { | ||
6 | + SET_PLATFORM, | ||
7 | + SET_CHANNEL, | ||
8 | + SET_HOST, | ||
9 | + SET_SERVICE_HOST, | ||
10 | +} = require('../../constants/actionTypes').default; | ||
11 | + | ||
12 | +export function setPlatform(platform) { | ||
13 | + return { | ||
14 | + type: SET_PLATFORM, | ||
15 | + payload: platform | ||
16 | + }; | ||
17 | +} | ||
18 | + | ||
19 | +export function setChannel(channel) { | ||
20 | + return { | ||
21 | + type: SET_CHANNEL, | ||
22 | + payload: channel | ||
23 | + }; | ||
24 | +} | ||
25 | + | ||
26 | +export function setHost(host) { | ||
27 | + return { | ||
28 | + type: SET_HOST, | ||
29 | + payload: host | ||
30 | + }; | ||
31 | +} | ||
32 | + | ||
33 | +export function setServiceHost(host) { | ||
34 | + return { | ||
35 | + type: SET_SERVICE_HOST, | ||
36 | + payload: host | ||
37 | + }; | ||
38 | +} |
js/message/reducers/app/appInitialState.js
0 → 100755
1 | +'use strict'; | ||
2 | + | ||
3 | +import {Record, List, Map} from 'immutable'; | ||
4 | + | ||
5 | +let InitialState = Record({ | ||
6 | + platform: 'ios', // ios, android | ||
7 | + channel: 1, // 1 - boy, 2 - girl, 3 - kid, 4 - lifestyle, 5 - yoho | ||
8 | + host: 'http://api.yoho.cn', | ||
9 | + serviceHost: 'http://service.yoho.cn', | ||
10 | +}); | ||
11 | + | ||
12 | +export default InitialState; |
js/message/reducers/app/appReducer.js
0 → 100755
1 | +'use strict'; | ||
2 | + | ||
3 | +import InitialState from './appInitialState'; | ||
4 | + | ||
5 | +const { | ||
6 | + SET_PLATFORM, | ||
7 | + SET_CHANNEL, | ||
8 | + SET_HOST, | ||
9 | + SET_SERVICE_HOST, | ||
10 | +} = require('../../constants/actionTypes').default; | ||
11 | + | ||
12 | +const initialState = new InitialState; | ||
13 | + | ||
14 | +export default function appReducer(state = initialState, action) { | ||
15 | + if (!(state instanceof InitialState)) return initialState.merge(state); | ||
16 | + | ||
17 | + switch (action.type) { | ||
18 | + case SET_PLATFORM: | ||
19 | + return state.set('platform', action.payload); | ||
20 | + case SET_CHANNEL: | ||
21 | + return state.set('channel', action.payload); | ||
22 | + case SET_HOST: | ||
23 | + return state.set('host', action.payload); | ||
24 | + case SET_SERVICE_HOST: | ||
25 | + return state.set('serviceHost', action.payload); | ||
26 | + } | ||
27 | + | ||
28 | + return state; | ||
29 | +} |
js/message/reducers/index.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +import Immutable, {Record, List, Map} from 'immutable'; | ||
4 | + | ||
5 | +let dataSource = Immutable.fromJS([ | ||
6 | + { | ||
7 | + id: 'member', | ||
8 | + title: '会员信息', | ||
9 | + detail: '会员等级变更提醒、会员生日福利', | ||
10 | + }, | ||
11 | + { | ||
12 | + id: 'asset', | ||
13 | + title: '我的资产', | ||
14 | + detail: '新注册用户提示新人专享优惠券信息', | ||
15 | + }, | ||
16 | + { | ||
17 | + id: 'customer', | ||
18 | + title: '客户服务', | ||
19 | + detail: '没有收到任何关于你的消息', | ||
20 | + }, | ||
21 | + { | ||
22 | + id: 'other', | ||
23 | + title: '其他', | ||
24 | + detail: '没有收到任何系统给消息', | ||
25 | + }, | ||
26 | + ]); | ||
27 | + | ||
28 | +let InitialState = Record({ | ||
29 | + dataSource, | ||
30 | + newMessage: new (Record({ | ||
31 | + isFetching: false, | ||
32 | + error: null, | ||
33 | + data: List(), | ||
34 | + })), | ||
35 | +}); | ||
36 | + | ||
37 | +export default InitialState; |
1 | +'use strict'; | ||
2 | + | ||
3 | +import InitialState from './messageInitialState'; | ||
4 | +import Immutable, {Map} from 'immutable'; | ||
5 | + | ||
6 | +const { | ||
7 | + SET_CHANNEL, | ||
8 | + | ||
9 | +} = require('../../constants/actionTypes').default; | ||
10 | + | ||
11 | +const initialState = new InitialState; | ||
12 | + | ||
13 | +export default function messageReducer(state=initialState, action) { | ||
14 | + switch(action.type) { | ||
15 | + | ||
16 | + | ||
17 | + } | ||
18 | + | ||
19 | + return state; | ||
20 | +} |
js/message/services/MessageService.js
0 → 100644
js/message/store/configureStore.js
0 → 100644
1 | +/** | ||
2 | + * # configureStore.js | ||
3 | + * | ||
4 | + * A Redux boilerplate setup | ||
5 | + * | ||
6 | + */ | ||
7 | +'use strict'; | ||
8 | + | ||
9 | +/** | ||
10 | + * ## Imports | ||
11 | + * | ||
12 | + * redux functions | ||
13 | + */ | ||
14 | +import { createStore, applyMiddleware } from 'redux'; | ||
15 | +import thunk from 'redux-thunk'; | ||
16 | +import createLogger from 'redux-logger'; | ||
17 | + | ||
18 | +/** | ||
19 | +* ## Reducer | ||
20 | +* The reducer contains the 4 reducers from | ||
21 | +* device, global, auth, profile | ||
22 | +*/ | ||
23 | +import reducer from '../reducers'; | ||
24 | + | ||
25 | +const logger = createLogger({ | ||
26 | + predicate: (getState, action) => process.env.NODE_ENV === `development` | ||
27 | +}); | ||
28 | + | ||
29 | +/** | ||
30 | + * ## creatStoreWithMiddleware | ||
31 | + * Like the name... | ||
32 | + */ | ||
33 | +const createStoreWithMiddleware = applyMiddleware( | ||
34 | + thunk, | ||
35 | + logger | ||
36 | +)(createStore); | ||
37 | + | ||
38 | +/** | ||
39 | + * ## configureStore | ||
40 | + * @param {Object} the state with for keys: | ||
41 | + * device, global, auth, profile | ||
42 | + * | ||
43 | + */ | ||
44 | +export default function configureStore(initialState) { | ||
45 | + return createStoreWithMiddleware(reducer, initialState); | ||
46 | +}; |
js/newArrival/NewArrival.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +import React from 'react'; | ||
4 | +import ReactNative, { | ||
5 | + AppRegistry, | ||
6 | + Platform, | ||
7 | +} from 'react-native'; | ||
8 | + | ||
9 | +import { | ||
10 | + Provider, | ||
11 | + connect | ||
12 | +} from 'react-redux'; | ||
13 | + | ||
14 | +import configureStore from './store/configureStore'; | ||
15 | +import {Record, List, Map} from 'immutable'; | ||
16 | + | ||
17 | +import appInitialState from './reducers/app/appInitialState'; | ||
18 | +import newArrivalInitialState from './reducers/newArrival/newArrivalInitialState'; | ||
19 | + | ||
20 | +import NewArrivalContainer from './containers/NewArrivalContainer'; | ||
21 | + | ||
22 | +import { | ||
23 | + setPlatform, | ||
24 | + setHost, | ||
25 | + setServiceHost, | ||
26 | +} from './reducers/app/appActions'; | ||
27 | + | ||
28 | + | ||
29 | +function getInitialState() { | ||
30 | + const _initState = { | ||
31 | + app: (new appInitialState()), | ||
32 | + newArrival: (new newArrivalInitialState()), | ||
33 | + }; | ||
34 | + return _initState; | ||
35 | +} | ||
36 | + | ||
37 | +export default function native(platform) { | ||
38 | + | ||
39 | + let YH_NewArrival = React.createClass({ | ||
40 | + | ||
41 | + render() { | ||
42 | + const store = configureStore(getInitialState()); | ||
43 | + store.dispatch(setPlatform(platform)); | ||
44 | + store.dispatch(setHost(this.props.host)); | ||
45 | + store.dispatch(setServiceHost(this.props.serviceHost)); | ||
46 | + | ||
47 | + return ( | ||
48 | + <Provider store={store}> | ||
49 | + <NewArrivalContainer /> | ||
50 | + </Provider> | ||
51 | + ); | ||
52 | + } | ||
53 | + }); | ||
54 | + | ||
55 | + AppRegistry.registerComponent('YH_NewArrival', () => YH_NewArrival); | ||
56 | +} |
1 | +'use strict'; | ||
2 | + | ||
3 | +import React, {Component} from 'react'; | ||
4 | +import ReactNative, { | ||
5 | + View, | ||
6 | + Text, | ||
7 | + Image, | ||
8 | + ListView, | ||
9 | + StyleSheet, | ||
10 | + Dimensions, | ||
11 | + TouchableOpacity, | ||
12 | + InteractionManager, | ||
13 | + Platform, | ||
14 | +} from 'react-native'; | ||
15 | + | ||
16 | + | ||
17 | + | ||
18 | +export default class NewArrival extends Component { | ||
19 | + | ||
20 | + constructor(props) { | ||
21 | + super(props); | ||
22 | + | ||
23 | + this._renderRow = this._renderRow.bind(this); | ||
24 | + this._onEndReached = this._onEndReached.bind(this); | ||
25 | + this._renderFooter = this._renderFooter.bind(this); | ||
26 | + this.trigggePullToRefresh = this.trigggePullToRefresh.bind(this); | ||
27 | + | ||
28 | + this.dataSource = new ListView.DataSource({ | ||
29 | + rowHasChanged: (r1, r2) => !Immutable.is(r1, r2), | ||
30 | + }); | ||
31 | + } | ||
32 | + | ||
33 | + componentDidMount() { | ||
34 | + this.trigggePullToRefresh(); | ||
35 | + } | ||
36 | + | ||
37 | + componentWillReceiveProps(nextProps) { | ||
38 | + if (nextProps.data.ptr) { | ||
39 | + this.listView && this.listView.scrollTo({x: 0, y: 0, animated: false, }); | ||
40 | + } | ||
41 | + } | ||
42 | + | ||
43 | + trigggePullToRefresh() { | ||
44 | + if (Platform.OS === 'ios') { | ||
45 | + InteractionManager.runAfterInteractions(() => { | ||
46 | + this.listView && this.listView.getScrollResponder().startPullToRefresh(); | ||
47 | + }); | ||
48 | + } else { | ||
49 | + this.props.onRefresh && this.props.onRefresh(); | ||
50 | + } | ||
51 | + } | ||
52 | + | ||
53 | + _renderRow(rowData: object, sectionID: number, rowID: number) { | ||
54 | + return null; | ||
55 | + } | ||
56 | + | ||
57 | + _onEndReached() { | ||
58 | + | ||
59 | + } | ||
60 | + | ||
61 | + _renderFooter() { | ||
62 | + return null; | ||
63 | + } | ||
64 | + | ||
65 | + render() { | ||
66 | + | ||
67 | + let {list, ptr, isFetching, endReached, showLoginTip, cachedList} = this.props.data; | ||
68 | + let dataSource = list.size == 0 ? cachedList.toArray() : list.toArray(); | ||
69 | + | ||
70 | + let isLoadingMore = list.size != 0 && !ptr && isFetching; | ||
71 | + | ||
72 | + return ( | ||
73 | + <View style={styles.container}> | ||
74 | + <ListView | ||
75 | + ref={(c) => { | ||
76 | + this.listView = c; | ||
77 | + }} | ||
78 | + contentContainerStyle={styles.contentContainer} | ||
79 | + dataSource={this.dataSource.cloneWithRows(dataSource)} | ||
80 | + renderRow={this._renderRow} | ||
81 | + enableEmptySections={true} | ||
82 | + onEndReached={this._onEndReached} | ||
83 | + renderFooter={this._renderFooter} | ||
84 | + /> | ||
85 | + </View> | ||
86 | + ); | ||
87 | + } | ||
88 | +} | ||
89 | + | ||
90 | +let {width, height} = Dimensions.get('window'); | ||
91 | + | ||
92 | +let styles = StyleSheet.create({ | ||
93 | + container: { | ||
94 | + flex: 1, | ||
95 | + backgroundColor: '#f0f0f0', | ||
96 | + }, | ||
97 | + contentContainer: { | ||
98 | + | ||
99 | + }, | ||
100 | +}); |
js/newArrival/constants/actionTypes.js
0 → 100644
1 | +'use strict' | ||
2 | + | ||
3 | +import React, {Component} from 'react'; | ||
4 | +import ReactNative, { | ||
5 | + StyleSheet, | ||
6 | + Dimensions, | ||
7 | + Platform, | ||
8 | + View, | ||
9 | + Text, | ||
10 | + NativeModules, | ||
11 | + InteractionManager, | ||
12 | + NativeAppEventEmitter, | ||
13 | +} from 'react-native' | ||
14 | + | ||
15 | +import {bindActionCreators} from 'redux'; | ||
16 | +import {connect} from 'react-redux'; | ||
17 | +import {Map} from 'immutable'; | ||
18 | +import * as newArrivalActions from '../reducers/newArrival/newArrivalActions'; | ||
19 | + | ||
20 | +import NewArrival from '../components/newArrival/NewArrival'; | ||
21 | + | ||
22 | + | ||
23 | +const actions = [ | ||
24 | + newArrivalActions, | ||
25 | +]; | ||
26 | + | ||
27 | +function mapStateToProps(state) { | ||
28 | + return { | ||
29 | + ...state | ||
30 | + }; | ||
31 | +} | ||
32 | + | ||
33 | +function mapDispatchToProps(dispatch) { | ||
34 | + | ||
35 | + const creators = Map() | ||
36 | + .merge(...actions) | ||
37 | + .filter(value => typeof value === 'function') | ||
38 | + .toObject(); | ||
39 | + | ||
40 | + return { | ||
41 | + actions: bindActionCreators(creators, dispatch), | ||
42 | + dispatch | ||
43 | + }; | ||
44 | +} | ||
45 | + | ||
46 | +class NewArrivalContainer extends Component { | ||
47 | + constructor(props) { | ||
48 | + super(props); | ||
49 | + | ||
50 | + this._onEndReached = this._onEndReached.bind(this); | ||
51 | + } | ||
52 | + | ||
53 | + componentDidMount() { | ||
54 | + | ||
55 | + } | ||
56 | + | ||
57 | + componentWillUnmount() { | ||
58 | + | ||
59 | + } | ||
60 | + | ||
61 | + _onEndReached() { | ||
62 | + | ||
63 | + } | ||
64 | + | ||
65 | + render() { | ||
66 | + let {newArrival} = this.props; | ||
67 | + return ( | ||
68 | + <View style={styles.container}> | ||
69 | + <NewArrival | ||
70 | + data={newArrival} | ||
71 | + onEndReached={this._onEndReached} | ||
72 | + /> | ||
73 | + </View> | ||
74 | + ); | ||
75 | + } | ||
76 | +} | ||
77 | + | ||
78 | +let styles = StyleSheet.create({ | ||
79 | + container: { | ||
80 | + flex: 1, | ||
81 | + }, | ||
82 | + | ||
83 | +}); | ||
84 | + | ||
85 | +export default connect(mapStateToProps, mapDispatchToProps)(NewArrivalContainer); |
js/newArrival/reducers/app/appActions.js
0 → 100755
1 | +'use strict'; | ||
2 | + | ||
3 | +import ReactNative from 'react-native'; | ||
4 | + | ||
5 | +const { | ||
6 | + SET_PLATFORM, | ||
7 | + SET_CHANNEL, | ||
8 | + SET_HOST, | ||
9 | + SET_SERVICE_HOST, | ||
10 | +} = require('../../constants/actionTypes').default; | ||
11 | + | ||
12 | +export function setPlatform(platform) { | ||
13 | + return { | ||
14 | + type: SET_PLATFORM, | ||
15 | + payload: platform | ||
16 | + }; | ||
17 | +} | ||
18 | + | ||
19 | +export function setChannel(channel) { | ||
20 | + return { | ||
21 | + type: SET_CHANNEL, | ||
22 | + payload: channel | ||
23 | + }; | ||
24 | +} | ||
25 | + | ||
26 | +export function setHost(host) { | ||
27 | + return { | ||
28 | + type: SET_HOST, | ||
29 | + payload: host | ||
30 | + }; | ||
31 | +} | ||
32 | + | ||
33 | +export function setServiceHost(host) { | ||
34 | + return { | ||
35 | + type: SET_SERVICE_HOST, | ||
36 | + payload: host | ||
37 | + }; | ||
38 | +} |
1 | +'use strict'; | ||
2 | + | ||
3 | +import {Record, List, Map} from 'immutable'; | ||
4 | + | ||
5 | +let InitialState = Record({ | ||
6 | + platform: 'ios', // ios, android | ||
7 | + channel: 1, // 1 - boy, 2 - girl, 3 - kid, 4 - lifestyle, 5 - yoho | ||
8 | + host: 'http://api.yoho.cn', | ||
9 | + serviceHost: 'http://service.yoho.cn', | ||
10 | +}); | ||
11 | + | ||
12 | +export default InitialState; |
js/newArrival/reducers/app/appReducer.js
0 → 100755
1 | +'use strict'; | ||
2 | + | ||
3 | +import InitialState from './appInitialState'; | ||
4 | + | ||
5 | +const { | ||
6 | + SET_PLATFORM, | ||
7 | + SET_CHANNEL, | ||
8 | + SET_HOST, | ||
9 | + SET_SERVICE_HOST, | ||
10 | +} = require('../../constants/actionTypes').default; | ||
11 | + | ||
12 | +const initialState = new InitialState; | ||
13 | + | ||
14 | +export default function appReducer(state = initialState, action) { | ||
15 | + if (!(state instanceof InitialState)) return initialState.merge(state); | ||
16 | + | ||
17 | + switch (action.type) { | ||
18 | + case SET_PLATFORM: | ||
19 | + return state.set('platform', action.payload); | ||
20 | + case SET_CHANNEL: | ||
21 | + return state.set('channel', action.payload); | ||
22 | + case SET_HOST: | ||
23 | + return state.set('host', action.payload); | ||
24 | + case SET_SERVICE_HOST: | ||
25 | + return state.set('serviceHost', action.payload); | ||
26 | + } | ||
27 | + | ||
28 | + return state; | ||
29 | +} |
js/newArrival/reducers/index.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +import InitialState from './newArrivalInitialState'; | ||
4 | +import Immutable, {Map} from 'immutable'; | ||
5 | + | ||
6 | +const { | ||
7 | + SET_CHANNEL, | ||
8 | + | ||
9 | +} = require('../../constants/actionTypes').default; | ||
10 | + | ||
11 | +const initialState = new InitialState; | ||
12 | + | ||
13 | +export default function newArrivalReducer(state=initialState, action) { | ||
14 | + switch(action.type) { | ||
15 | + | ||
16 | + | ||
17 | + } | ||
18 | + | ||
19 | + return state; | ||
20 | +} |
js/newArrival/services/NewArrivalService.js
0 → 100644
js/newArrival/store/configureStore.js
0 → 100644
1 | +/** | ||
2 | + * # configureStore.js | ||
3 | + * | ||
4 | + * A Redux boilerplate setup | ||
5 | + * | ||
6 | + */ | ||
7 | +'use strict'; | ||
8 | + | ||
9 | +/** | ||
10 | + * ## Imports | ||
11 | + * | ||
12 | + * redux functions | ||
13 | + */ | ||
14 | +import { createStore, applyMiddleware } from 'redux'; | ||
15 | +import thunk from 'redux-thunk'; | ||
16 | +import createLogger from 'redux-logger'; | ||
17 | + | ||
18 | +/** | ||
19 | +* ## Reducer | ||
20 | +* The reducer contains the 4 reducers from | ||
21 | +* device, global, auth, profile | ||
22 | +*/ | ||
23 | +import reducer from '../reducers'; | ||
24 | + | ||
25 | +const logger = createLogger({ | ||
26 | + predicate: (getState, action) => process.env.NODE_ENV === `development` | ||
27 | +}); | ||
28 | + | ||
29 | +/** | ||
30 | + * ## creatStoreWithMiddleware | ||
31 | + * Like the name... | ||
32 | + */ | ||
33 | +const createStoreWithMiddleware = applyMiddleware( | ||
34 | + thunk, | ||
35 | + logger | ||
36 | +)(createStore); | ||
37 | + | ||
38 | +/** | ||
39 | + * ## configureStore | ||
40 | + * @param {Object} the state with for keys: | ||
41 | + * device, global, auth, profile | ||
42 | + * | ||
43 | + */ | ||
44 | +export default function configureStore(initialState) { | ||
45 | + return createStoreWithMiddleware(reducer, initialState); | ||
46 | +}; |
@@ -94,19 +94,19 @@ export default function native(platform) { | @@ -94,19 +94,19 @@ export default function native(platform) { | ||
94 | } | 94 | } |
95 | 95 | ||
96 | let type = this.props.type; | 96 | let type = this.props.type; |
97 | - if (type == 'list') { | 97 | + if (type == 'detail') { |
98 | + let id=this.props.id; | ||
99 | + let udid=this.props.udid; | ||
100 | + store.dispatch(setId(id)); | ||
98 | return ( | 101 | return ( |
99 | <Provider store={store}> | 102 | <Provider store={store}> |
100 | - <PlustarContainer /> | 103 | + <DetailContainer /> |
101 | </Provider> | 104 | </Provider> |
102 | ); | 105 | ); |
103 | } else { | 106 | } else { |
104 | - let id=this.props.id; | ||
105 | - let udid=this.props.udid; | ||
106 | - store.dispatch(setId(id)); | ||
107 | return ( | 107 | return ( |
108 | <Provider store={store}> | 108 | <Provider store={store}> |
109 | - <DetailContainer /> | 109 | + <PlustarContainer /> |
110 | </Provider> | 110 | </Provider> |
111 | ); | 111 | ); |
112 | } | 112 | } |
1 | -'use strict'; | ||
2 | - | ||
3 | -import React from 'react'; | ||
4 | -import ReactNative from 'react-native'; | ||
5 | - | ||
6 | -const { | ||
7 | - View, | ||
8 | - Image, | ||
9 | - Text, | ||
10 | - TouchableOpacity, | ||
11 | - Dimensions, | ||
12 | - StyleSheet, | ||
13 | -} = ReactNative; | ||
14 | - | ||
15 | -export default class GPTags extends React.Component { | ||
16 | - | ||
17 | - constructor(props) { | ||
18 | - super (props); | ||
19 | - | ||
20 | - } | ||
21 | - | ||
22 | - render() { | ||
23 | - let {title, isLimit} = this.props; | ||
24 | - | ||
25 | - let leftWidth = tagMaxWidth; | ||
26 | - if (isLimit) { | ||
27 | - leftWidth = tagMaxWidth - limitWidth - 2; | ||
28 | - } | ||
29 | - | ||
30 | - let textMaxWidth = leftWidth - iconWidth - 5 * 2; | ||
31 | - | ||
32 | - return ( | ||
33 | - <View style={styles.container}> | ||
34 | - <View style={[styles.leftContainer, {width: leftWidth}]}> | ||
35 | - <Image | ||
36 | - style={styles.icon} | ||
37 | - source={require('../../images/tag/globalpurchase_fly_smallicon.png')} | ||
38 | - /> | ||
39 | - <Text numberOfLines={1} style={[styles.text, {maxWidth: textMaxWidth}]}>{title}</Text> | ||
40 | - </View> | ||
41 | - | ||
42 | - {isLimit ? <Image | ||
43 | - style={styles.limit} | ||
44 | - source={require('../../images/tag/gp_tip_xl_product.png')} | ||
45 | - /> : null} | ||
46 | - | ||
47 | - </View> | ||
48 | - ); | ||
49 | - } | ||
50 | -} | ||
51 | - | ||
52 | -let {width, height} = Dimensions.get('window'); | ||
53 | - | ||
54 | -const DEVICE_WIDTH_RATIO = width / 320; | ||
55 | -let tagMaxWidth = Math.ceil(137.5 * DEVICE_WIDTH_RATIO); | ||
56 | -let tagHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO); | ||
57 | -let iconWidth = Math.ceil(10 * DEVICE_WIDTH_RATIO); | ||
58 | - | ||
59 | -let limitWidth = Math.ceil(30 * DEVICE_WIDTH_RATIO); | ||
60 | -let limitHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO); | ||
61 | - | ||
62 | -let styles = StyleSheet.create({ | ||
63 | - container: { | ||
64 | - flexDirection: 'row', | ||
65 | - alignItems: 'center', | ||
66 | - width: width, | ||
67 | - height: tagHeight, | ||
68 | - }, | ||
69 | - leftContainer: { | ||
70 | - flexDirection: 'row', | ||
71 | - alignItems: 'center', | ||
72 | - backgroundColor: '#462e3d', | ||
73 | - height: tagHeight, | ||
74 | - }, | ||
75 | - icon: { | ||
76 | - marginLeft: 5, | ||
77 | - width: iconWidth, | ||
78 | - height: iconWidth, | ||
79 | - resizeMode: 'contain', | ||
80 | - }, | ||
81 | - text: { | ||
82 | - marginLeft: 5, | ||
83 | - marginRight: 5, | ||
84 | - color: 'white', | ||
85 | - fontSize: 10, | ||
86 | - fontFamily: 'STHeitiSC-Light', | ||
87 | - }, | ||
88 | - limit: { | ||
89 | - marginLeft: 2, | ||
90 | - width: limitWidth, | ||
91 | - height: limitHeight, | ||
92 | - resizeMode: 'contain', | ||
93 | - }, | ||
94 | -}); |
@@ -13,7 +13,7 @@ import ReactNative, { | @@ -13,7 +13,7 @@ import ReactNative, { | ||
13 | 13 | ||
14 | import SlicedImage from '../../../common/components/SlicedImage'; | 14 | import SlicedImage from '../../../common/components/SlicedImage'; |
15 | import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator'; | 15 | import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator'; |
16 | -import ProductListCell from './ProductListCell'; | 16 | +import ProductListCell from '../../../common/components/ListCell/ProductListCell'; |
17 | import ProductFilter from './ProductFilter'; | 17 | import ProductFilter from './ProductFilter'; |
18 | import ProductShopCell from './ProductShopCell'; | 18 | import ProductShopCell from './ProductShopCell'; |
19 | 19 |
1 | -'use strict'; | ||
2 | - | ||
3 | -import React, {Component} from 'react'; | ||
4 | -import ReactNative, { | ||
5 | - View, | ||
6 | - Text, | ||
7 | - Image, | ||
8 | - ListView, | ||
9 | - StyleSheet, | ||
10 | - Dimensions, | ||
11 | - TouchableOpacity, | ||
12 | -} from 'react-native'; | ||
13 | - | ||
14 | -import SlicedImage from '../../../common/components/SlicedImage'; | ||
15 | -import Tags from './Tags'; | ||
16 | -import GPTags from './GPTags'; | ||
17 | - | ||
18 | - | ||
19 | -export default class Search extends Component { | ||
20 | - | ||
21 | - constructor(props) { | ||
22 | - super(props); | ||
23 | - | ||
24 | - this._renderTags = this._renderTags.bind(this); | ||
25 | - this._renderImages = this._renderImages.bind(this); | ||
26 | - this._renderPrice = this._renderPrice.bind(this); | ||
27 | - } | ||
28 | - | ||
29 | - _renderTags() { | ||
30 | - let {data, sourceType} = this.props; | ||
31 | - let isGlobalProduct = data.get('is_global') && data.get('is_global') == 'Y'; // 是否全球购商品 | ||
32 | - | ||
33 | - let tags = data.get('tags'); // 商品标签 | ||
34 | - // 数据源是全球购 | ||
35 | - if (sourceType == 1) { | ||
36 | - if (isGlobalProduct) { | ||
37 | - | ||
38 | - } else { | ||
39 | - tags = ['is_in_stock', ...tags]; | ||
40 | - } | ||
41 | - } | ||
42 | - | ||
43 | - let countryName = isGlobalProduct && data.get('country_name'); // 全球购国家名称 | ||
44 | - | ||
45 | - if (isGlobalProduct) { | ||
46 | - return <GPTags title={countryName} limit={showGPLimitTag}/>; | ||
47 | - } else { | ||
48 | - return <Tags items={tags}/>; | ||
49 | - } | ||
50 | - } | ||
51 | - | ||
52 | - _renderImages() { | ||
53 | - let {data, sourceType} = this.props; | ||
54 | - let url = data.get('default_images').replace('{width}', rowWidth).replace('{height}', imageHeight); // 商品缩略图 | ||
55 | - url = SlicedImage.getSlicedUrl(data.get('default_images'), 290, 386, 2); | ||
56 | - | ||
57 | - let isGlobalProduct = data.get('is_global') && data.get('is_global') == 'Y'; // 是否全球购商品 | ||
58 | - | ||
59 | - | ||
60 | - let showGPLimitTag = isGlobalProduct && data.get('is_limited') && data.get('is_limited') == 'Y'; // 全球购限量商品 | ||
61 | - let showGPSoldOut = isGlobalProduct && data.get('is_stock') && data.get('is_stock') == 'Y'; // 全球购售罄 | ||
62 | - | ||
63 | - let showAlmostSoldOut = !isGlobalProduct && data.get('tags', []).indexOf('is_soon_sold_out') !== -1; // 非全球购的即将售罄 | ||
64 | - let showSoldOut = sourceType == 2 && data.get('storage_num') && data.get('storage_num') == 0; // 数据源是奥莱才显示 | ||
65 | - | ||
66 | - return ( | ||
67 | - <View style={styles.imageContainer}> | ||
68 | - <Image style={styles.image} source={{uri: url}}> | ||
69 | - {showAlmostSoldOut ? <Image style={styles.almostSoldOutImage} source={require('../../images/tag/tip_jjsq.png')}/> : null} | ||
70 | - {showSoldOut ? <Image style={styles.soldOutImage} source={require('../../images/tag/outlet_sellout_bg.png')}/> : null} | ||
71 | - {showGPSoldOut ? <Image style={styles.gpSoldOutImage} source={require('../../images/tag/gp_tip_SQ.png')}/> : null} | ||
72 | - </Image> | ||
73 | - </View> | ||
74 | - ); | ||
75 | - } | ||
76 | - | ||
77 | - _renderPrice() { | ||
78 | - let {data, sourceType} = this.props; | ||
79 | - let isGlobalProduct = data.get('is_global') && data.get('is_global') == 'Y'; // 是否全球购商品 | ||
80 | - | ||
81 | - let salePrice = 0; // 售卖价 | ||
82 | - let originPrice = 0; // 原价 | ||
83 | - let salePriceStr = ''; // 拼接的售卖价 | ||
84 | - let originPriceStr = ''; // 拼接的原价 | ||
85 | - let showOriginPrice = true; // 是否显示原价 | ||
86 | - let salePriceColor = '#d0021b'; // 不显示原价时,售卖价颜色 | ||
87 | - | ||
88 | - if (isGlobalProduct) { | ||
89 | - salePrice = parseFloat(data.get('final_price')); | ||
90 | - originPrice = parseFloat(data.get('orign_price')); | ||
91 | - salePriceStr = data.get('formart_final_price'); | ||
92 | - originPriceStr = data.get('formart_orign_price'); | ||
93 | - } else { | ||
94 | - salePrice = parseFloat(data.get('sales_price')); | ||
95 | - originPrice = parseFloat(data.get('market_price')); | ||
96 | - salePriceStr = '¥' + salePrice.toFixed(2); | ||
97 | - originPriceStr = '¥' + originPrice.toFixed(2); | ||
98 | - } | ||
99 | - | ||
100 | - if (!originPrice || (salePrice == originPrice)) { | ||
101 | - showOriginPrice = false; | ||
102 | - salePriceColor = '#444444'; | ||
103 | - } | ||
104 | - | ||
105 | - if (showOriginPrice) { | ||
106 | - return ( | ||
107 | - <View style={styles.priceContainer}> | ||
108 | - <Text style={[styles.nowPrice, {color: salePriceColor}]} numberOfLines={1}>{salePriceStr}</Text> | ||
109 | - <View style={styles.oldPriceContainer}> | ||
110 | - <Text style={styles.oldPrice} numberOfLines={1}>{originPriceStr}</Text> | ||
111 | - <View style={styles.deleteLine}/> | ||
112 | - </View> | ||
113 | - </View> | ||
114 | - | ||
115 | - ); | ||
116 | - } else { | ||
117 | - return ( | ||
118 | - <View style={styles.priceContainer}> | ||
119 | - <Text style={[styles.nowPrice, {color: salePriceColor}]} numberOfLines={1}>{salePriceStr}</Text> | ||
120 | - </View> | ||
121 | - ); | ||
122 | - } | ||
123 | - } | ||
124 | - | ||
125 | - | ||
126 | - render() { | ||
127 | - let {data, sourceType, rowID, style} = this.props; | ||
128 | - let name = data.get('product_name') ? data.get('product_name') : ''; | ||
129 | - | ||
130 | - return ( | ||
131 | - <TouchableOpacity | ||
132 | - style={[styles.container, style]} | ||
133 | - activeOpacity={1} | ||
134 | - onPress={() => { | ||
135 | - this.props.onPressProduct && this.props.onPressProduct(data, rowID); | ||
136 | - }} | ||
137 | - > | ||
138 | - <View> | ||
139 | - | ||
140 | - {this._renderTags()} | ||
141 | - | ||
142 | - {this._renderImages()} | ||
143 | - | ||
144 | - <View style={styles.nameContainer}> | ||
145 | - <Text style={styles.name} numberOfLines={2}>{name}</Text> | ||
146 | - </View> | ||
147 | - | ||
148 | - {this._renderPrice()} | ||
149 | - | ||
150 | - </View> | ||
151 | - </TouchableOpacity> | ||
152 | - ); | ||
153 | - } | ||
154 | -} | ||
155 | - | ||
156 | -let {width, height} = Dimensions.get('window'); | ||
157 | - | ||
158 | -const DEVICE_WIDTH_RATIO = width / 320; | ||
159 | -let rowWidth = Math.ceil(137.5 * DEVICE_WIDTH_RATIO); | ||
160 | -let rowHeight = Math.ceil(254 * DEVICE_WIDTH_RATIO); | ||
161 | -let rowMarginTop = Math.ceil(10 * DEVICE_WIDTH_RATIO); | ||
162 | - | ||
163 | -const IMAGE_WIDTH = 145; | ||
164 | -const IMAGE_HEIGHT = 193; | ||
165 | -const IMAGE_RATIO = IMAGE_HEIGHT / IMAGE_WIDTH; | ||
166 | -let imageTop = 14 * DEVICE_WIDTH_RATIO; | ||
167 | -let imageHeight = rowWidth * IMAGE_RATIO; | ||
168 | - | ||
169 | -let almostSoldOutImageHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO); | ||
170 | -let almostSoldOutImageTop = imageHeight - almostSoldOutImageHeight; | ||
171 | - | ||
172 | -let nameMarginTop = Math.ceil(7 * DEVICE_WIDTH_RATIO); | ||
173 | -let nameHeight = Math.ceil(36 * DEVICE_WIDTH_RATIO); | ||
174 | - | ||
175 | -let gpSoldOutImageHeight = Math.ceil(25 * DEVICE_WIDTH_RATIO); | ||
176 | - | ||
177 | -let styles = StyleSheet.create({ | ||
178 | - container: { | ||
179 | - width: rowWidth, | ||
180 | - height: rowHeight, | ||
181 | - marginTop: rowMarginTop, | ||
182 | - }, | ||
183 | - rowContainer: { | ||
184 | - width: rowWidth, | ||
185 | - height: rowHeight, | ||
186 | - | ||
187 | - }, | ||
188 | - imageContainer: { | ||
189 | - width: rowWidth, | ||
190 | - height: imageHeight, | ||
191 | - backgroundColor: '#f0f0f0', | ||
192 | - }, | ||
193 | - image: { | ||
194 | - width: rowWidth, | ||
195 | - height: imageHeight, | ||
196 | - backgroundColor: '#f0f0f0', | ||
197 | - }, | ||
198 | - soldOutImage: { | ||
199 | - position: 'absolute', | ||
200 | - top: 0, | ||
201 | - left: 0, | ||
202 | - width: rowWidth, | ||
203 | - height: imageHeight, | ||
204 | - }, | ||
205 | - almostSoldOutImage: { | ||
206 | - top: almostSoldOutImageTop, | ||
207 | - width: rowWidth, | ||
208 | - height: almostSoldOutImageHeight, | ||
209 | - backgroundColor: '#ff9e0d', | ||
210 | - }, | ||
211 | - nameContainer: { | ||
212 | - // justifyContent: 'center', | ||
213 | - marginTop: nameMarginTop, | ||
214 | - width: rowWidth, | ||
215 | - height: nameHeight, | ||
216 | - }, | ||
217 | - name: { | ||
218 | - fontFamily: 'STHeitiSC-Light', | ||
219 | - fontSize: 12, | ||
220 | - color: '#444444', | ||
221 | - }, | ||
222 | - priceContainer: { | ||
223 | - flexDirection: 'row', | ||
224 | - }, | ||
225 | - nowPrice: { | ||
226 | - fontSize: 12, | ||
227 | - color: '#d0021b', | ||
228 | - }, | ||
229 | - oldPriceContainer: { | ||
230 | - flexDirection: 'row', | ||
231 | - marginLeft: 5, | ||
232 | - }, | ||
233 | - oldPrice: { | ||
234 | - fontSize: 12, | ||
235 | - color: '#b0b0b0', | ||
236 | - height: 16, | ||
237 | - }, | ||
238 | - deleteLine: { | ||
239 | - position: 'absolute', | ||
240 | - top: (16 / 2) - 0.8, | ||
241 | - left: 0, | ||
242 | - right: 0, | ||
243 | - height: 1, | ||
244 | - backgroundColor: '#b0b0b0', | ||
245 | - }, | ||
246 | - gpSoldOutImage: { | ||
247 | - position: 'absolute', | ||
248 | - top: 5, | ||
249 | - right: 5, | ||
250 | - width: gpSoldOutImageHeight, | ||
251 | - height: gpSoldOutImageHeight, | ||
252 | - }, | ||
253 | -}); |
js/search/components/search/Tags.js
deleted
100644 → 0
1 | -'use strict'; | ||
2 | - | ||
3 | -import React from 'react'; | ||
4 | -import ReactNative from 'react-native'; | ||
5 | - | ||
6 | -const { | ||
7 | - View, | ||
8 | - Image, | ||
9 | - Text, | ||
10 | - ListView, | ||
11 | - Dimensions, | ||
12 | - StyleSheet, | ||
13 | -} = ReactNative; | ||
14 | - | ||
15 | -export default class Tags extends React.Component { | ||
16 | - | ||
17 | - constructor(props) { | ||
18 | - super (props); | ||
19 | - | ||
20 | - this.config = { | ||
21 | - is_discount: { | ||
22 | - image: require('../../images/tag/tip_sale.png'), | ||
23 | - width: 30, | ||
24 | - }, // YH_ProductTagTypeSale | ||
25 | - resale: { | ||
26 | - image: require('../../images/tag/tip_zdz.png'), | ||
27 | - width: 45, | ||
28 | - }, // YH_ProductTagTypeReSale | ||
29 | - 'mid-year': { | ||
30 | - image: require('../../images/tag/tip_nzrc.png'), | ||
31 | - width: 45, | ||
32 | - }, // YH_ProductTagTypeSaleMiddle | ||
33 | - 'year-end': { | ||
34 | - image: require('../../images/tag/tip_nzdc.png'), | ||
35 | - width: 45, | ||
36 | - }, // YH_ProductTagTypeSaleHot | ||
37 | - is_new: { | ||
38 | - image: require('../../images/tag/tip_new.png'), | ||
39 | - width: 30, | ||
40 | - }, // YH_ProductTagTypeNew | ||
41 | - is_yohood: { | ||
42 | - image: require('../../images/tag/tip_xpj.png'), | ||
43 | - width: 45, | ||
44 | - }, // YH_ProductTagTypeYohood | ||
45 | - is_limited: { | ||
46 | - image: require('../../images/tag/tip_xl_product.png'), | ||
47 | - width: 30, | ||
48 | - }, // YH_ProductTagTypeLimited | ||
49 | - is_in_stock: { | ||
50 | - image: require('../../images/tag/tip_gnzf.png'), | ||
51 | - width: 45, | ||
52 | - }, // YH_ProductTagTypeInland | ||
53 | - is_deposit_advance: { | ||
54 | - image: require('../../images/tag/tip_advance.png'), | ||
55 | - width: 30, | ||
56 | - }, // YH_ProductTagTypeDeposit | ||
57 | - default: { | ||
58 | - image: '', | ||
59 | - width: 45, | ||
60 | - }, | ||
61 | - }; | ||
62 | - | ||
63 | - this._renderRow = this._renderRow.bind(this); | ||
64 | - | ||
65 | - this.dataSource = new ListView.DataSource({ | ||
66 | - rowHasChanged: (r1, r2) => r1 != r2, | ||
67 | - }); | ||
68 | - } | ||
69 | - | ||
70 | - _renderRow(rowData, sectionID, rowID) { | ||
71 | - let item = this.config[rowData]; | ||
72 | - if (!item) { | ||
73 | - return null; | ||
74 | - } | ||
75 | - | ||
76 | - let width = Math.ceil(item.width * DEVICE_WIDTH_RATIO); | ||
77 | - let marginLeft = rowID == 0 ? 0 : 2; | ||
78 | - let iconStyle = {width, height: tagHeight, marginLeft}; | ||
79 | - | ||
80 | - return ( | ||
81 | - <Image style={[styles.icon, iconStyle]} source={item.image}/> | ||
82 | - ); | ||
83 | - } | ||
84 | - | ||
85 | - render() { | ||
86 | - | ||
87 | - let {style, items} = this.props; | ||
88 | - // let tags = ['is_discount', 'resale', ]; | ||
89 | - | ||
90 | - return ( | ||
91 | - <View style={[styles.container]}> | ||
92 | - <ListView | ||
93 | - style={[styles.container]} | ||
94 | - contentContainerStyle={[styles.contentContainer]} | ||
95 | - enableEmptySections={true} | ||
96 | - dataSource={this.dataSource.cloneWithRows(items.toArray())} | ||
97 | - renderRow={this._renderRow} | ||
98 | - scrollEnabled={false} | ||
99 | - scrollsToTop={false} | ||
100 | - horizontal={true} | ||
101 | - showsHorizontalScrollIndicator={false} | ||
102 | - /> | ||
103 | - </View> | ||
104 | - ); | ||
105 | - } | ||
106 | -} | ||
107 | - | ||
108 | -let {width, height} = Dimensions.get('window'); | ||
109 | - | ||
110 | -const DEVICE_WIDTH_RATIO = width / 320; | ||
111 | -let tagHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO); | ||
112 | - | ||
113 | -let styles = StyleSheet.create({ | ||
114 | - container: { | ||
115 | - | ||
116 | - }, | ||
117 | - contentContainer: { | ||
118 | - height: tagHeight, | ||
119 | - }, | ||
120 | - icon: { | ||
121 | - resizeMode: 'contain', | ||
122 | - }, | ||
123 | -}); |
-
Please register or login to post a comment