Merge branch 'develop' of http://git.yoho.cn/mobile/YH_RNComponent into develop
Conflicts: js/community/containers/HomeContainer.js
Showing
30 changed files
with
402 additions
and
60 deletions
js/common/components/LoadingIndicator.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +import React, {Component} from 'react' | ||
4 | +import { | ||
5 | + StyleSheet, | ||
6 | + View, | ||
7 | + Text, | ||
8 | + Dimensions, | ||
9 | + ActivityIndicator, | ||
10 | + Platform, | ||
11 | +} from 'react-native'; | ||
12 | + | ||
13 | +export default class LoadingIndicator extends Component { | ||
14 | + | ||
15 | + static propTypes = { | ||
16 | + isVisible: React.PropTypes.bool.isRequired, | ||
17 | + size: React.PropTypes.string, | ||
18 | + color: React.PropTypes.string, | ||
19 | + overlayWidth: React.PropTypes.number, | ||
20 | + overlayHeight: React.PropTypes.number, | ||
21 | + overlayColor: React.PropTypes.string, | ||
22 | + text: React.PropTypes.string, | ||
23 | + textColor: React.PropTypes.string, | ||
24 | + textFontSize: React.PropTypes.number, | ||
25 | + }; | ||
26 | + | ||
27 | + static defaultProps = { | ||
28 | + isDismissible: false, | ||
29 | + overlayWidth: 100, | ||
30 | + overlayHeight: 100, | ||
31 | + overlayColor: 'rgba(0,0,0,0.6)', | ||
32 | + size: (Platform.OS === 'ios') ? 'large' : 'Normal', | ||
33 | + color: (Platform.OS === 'ios') ? 'white' : 'gray', | ||
34 | + text: '加载中...', | ||
35 | + textColor: '#eeeeee', | ||
36 | + textFontSize: 14, | ||
37 | + }; | ||
38 | + | ||
39 | + render() { | ||
40 | + | ||
41 | + if (!this.props.isVisible) { | ||
42 | + return null; | ||
43 | + } | ||
44 | + | ||
45 | + let customStyles = StyleSheet.create({ | ||
46 | + overlay: { | ||
47 | + alignItems: 'center', | ||
48 | + justifyContent: 'center', | ||
49 | + borderRadius: 10, | ||
50 | + backgroundColor: this.props.overlayColor, | ||
51 | + width: this.props.overlayWidth, | ||
52 | + height: this.props.overlayHeight, | ||
53 | + }, | ||
54 | + text: { | ||
55 | + color: this.props.textColor, | ||
56 | + fontSize: this.props.textFontSize, | ||
57 | + marginTop: 8, | ||
58 | + }, | ||
59 | + }); | ||
60 | + | ||
61 | + return ( | ||
62 | + <View style={styles.container}> | ||
63 | + <View style={customStyles.overlay}> | ||
64 | + <ActivityIndicator color={this.props.color} size={this.props.size}/> | ||
65 | + <Text style={customStyles.text}>{this.props.text}</Text> | ||
66 | + </View> | ||
67 | + </View> | ||
68 | + ); | ||
69 | + } | ||
70 | +} | ||
71 | + | ||
72 | +const styles = StyleSheet.create({ | ||
73 | + container: { | ||
74 | + position: 'absolute', | ||
75 | + backgroundColor: 'transparent', | ||
76 | + justifyContent: 'center', | ||
77 | + alignItems: 'center', | ||
78 | + top: 0, | ||
79 | + bottom: 0, | ||
80 | + left: 0, | ||
81 | + right: 0, | ||
82 | + }, | ||
83 | +}); |
1 | 'use strict'; | 1 | 'use strict'; |
2 | 2 | ||
3 | import React from 'react'; | 3 | import React from 'react'; |
4 | -import {AppRegistry, Platform, StyleSheet, Dimensions, Text, Alert} from 'react-native'; | 4 | +import ReactNative, { |
5 | + AppRegistry, | ||
6 | + Platform, | ||
7 | + StyleSheet, | ||
8 | + Dimensions, | ||
9 | + TouchableOpacity, | ||
10 | + View, | ||
11 | + Text, | ||
12 | + Image, | ||
13 | + Alert, | ||
14 | + Animated, | ||
15 | +} from 'react-native'; | ||
5 | 16 | ||
6 | import { | 17 | import { |
7 | Provider, | 18 | Provider, |
@@ -35,9 +46,13 @@ import NavBar from './components/NavBar'; | @@ -35,9 +46,13 @@ import NavBar from './components/NavBar'; | ||
35 | import { | 46 | import { |
36 | setPlatform, | 47 | setPlatform, |
37 | setContianer, | 48 | setContianer, |
38 | - setDot | 49 | + setChannel, |
39 | } from './reducers/app/appActions'; | 50 | } from './reducers/app/appActions'; |
40 | 51 | ||
52 | +import { | ||
53 | + syncUser, | ||
54 | +} from './reducers/home/homeActions'; | ||
55 | + | ||
41 | 56 | ||
42 | /** | 57 | /** |
43 | * | 58 | * |
@@ -70,6 +85,8 @@ export default function community(platform) { | @@ -70,6 +85,8 @@ export default function community(platform) { | ||
70 | 85 | ||
71 | store.dispatch(setPlatform(platform)); | 86 | store.dispatch(setPlatform(platform)); |
72 | store.dispatch(setContianer(this.props.container)); | 87 | store.dispatch(setContianer(this.props.container)); |
88 | + store.dispatch(setChannel(this.props.channel)); | ||
89 | + | ||
73 | // setup the router table with App selected as the initial component | 90 | // setup the router table with App selected as the initial component |
74 | return ( | 91 | return ( |
75 | <Provider store={store}> | 92 | <Provider store={store}> |
@@ -80,9 +97,12 @@ export default function community(platform) { | @@ -80,9 +97,12 @@ export default function community(platform) { | ||
80 | hideTabBar={true} | 97 | hideTabBar={true} |
81 | navBar={NavBar} | 98 | navBar={NavBar} |
82 | titleStyle={styles.navTitle} | 99 | titleStyle={styles.navTitle} |
100 | + leftButtonStyle={styles.button} | ||
101 | + rightButtonStyle={styles.button} | ||
83 | getSceneStyle={(props) => { | 102 | getSceneStyle={(props) => { |
84 | return this.navPushStyle(props); | 103 | return this.navPushStyle(props); |
85 | }} | 104 | }} |
105 | + getChannel={() => store.getState().app.channel} | ||
86 | > | 106 | > |
87 | <Scene | 107 | <Scene |
88 | key="Home" | 108 | key="Home" |
@@ -92,10 +112,13 @@ export default function community(platform) { | @@ -92,10 +112,13 @@ export default function community(platform) { | ||
92 | initial={true} | 112 | initial={true} |
93 | leftTitle={null} | 113 | leftTitle={null} |
94 | leftButtonImage={require('./images/home/menu_burger.png')} | 114 | leftButtonImage={require('./images/home/menu_burger.png')} |
95 | - onLeft={() => {}} | 115 | + onLeft={() => { |
116 | + ReactNative.NativeModules.YH_CommunityHelper.toggleDrawer(); | ||
117 | + }} | ||
96 | rightTitle={null} | 118 | rightTitle={null} |
97 | rightButtonImage={require('./images/home/menu_write.png')} | 119 | rightButtonImage={require('./images/home/menu_write.png')} |
98 | - onRight={() => {Actions.Posting();}} | 120 | + onRight={this.homeOnRight} |
121 | + renderTitle={this.renderHomeTitle} | ||
99 | /> | 122 | /> |
100 | 123 | ||
101 | <Scene | 124 | <Scene |
@@ -164,6 +187,51 @@ export default function community(platform) { | @@ -164,6 +187,51 @@ export default function community(platform) { | ||
164 | ); | 187 | ); |
165 | }, | 188 | }, |
166 | 189 | ||
190 | + renderHomeTitle(navProps) { | ||
191 | + let {width, height} = Dimensions.get('window'); | ||
192 | + let distance = Math.ceil(width * 90 / 375); | ||
193 | + let distance2 = Math.ceil(width * 60 / 375); | ||
194 | + let distance3 = Math.ceil(width * 35 / 375); | ||
195 | + let line = 375 - (distance + distance2); | ||
196 | + | ||
197 | + return ( | ||
198 | + <Animated.View style={[styles.title,]}> | ||
199 | + <TouchableOpacity onPress={() => { | ||
200 | + ReactNative.NativeModules.YH_CommunityHelper.hideRNNavBar(0); | ||
201 | + }}> | ||
202 | + <Text style={[styles.text, {flex: 0, marginLeft: distance,}]}>逛</Text> | ||
203 | + </TouchableOpacity> | ||
204 | + <Text style={[styles.text, {flex: 0, marginLeft: distance2,}]}>社区</Text> | ||
205 | + <TouchableOpacity onPress={() => { | ||
206 | + ReactNative.NativeModules.YH_CommunityHelper.hideRNNavBar(2); | ||
207 | + }}> | ||
208 | + <Image style={{marginLeft: distance3,}} source={require('./images/home/sd_show_ic.png')}/> | ||
209 | + </TouchableOpacity> | ||
210 | + <View style={{ | ||
211 | + backgroundColor: 'white', | ||
212 | + position: 'absolute', | ||
213 | + width: 45, | ||
214 | + height: 2, | ||
215 | + left: 165, | ||
216 | + top: 30, | ||
217 | + }}/> | ||
218 | + </Animated.View> | ||
219 | + ); | ||
220 | + }, | ||
221 | + | ||
222 | + homeOnRight(state) { | ||
223 | + ReactNative.NativeModules.YH_CommunityHelper.uid() | ||
224 | + .then(uid => { | ||
225 | + state.dispatch(syncUser(uid)); | ||
226 | + }) | ||
227 | + .catch(error => { | ||
228 | + ReactNative.NativeModules.YH_CommunityHelper.login() | ||
229 | + .then(uid => { | ||
230 | + state.dispatch(syncUser(uid)); | ||
231 | + }); | ||
232 | + }); | ||
233 | + }, | ||
234 | + | ||
167 | /* | 235 | /* |
168 | * 自定义导航push动画 | 236 | * 自定义导航push动画 |
169 | * | 237 | * |
@@ -214,13 +282,16 @@ export default function community(platform) { | @@ -214,13 +282,16 @@ export default function community(platform) { | ||
214 | 282 | ||
215 | let styles = StyleSheet.create({ | 283 | let styles = StyleSheet.create({ |
216 | scene: { | 284 | scene: { |
217 | - backgroundColor:'#F0F0F0', | 285 | + backgroundColor: '#F0F0F0', |
218 | }, | 286 | }, |
219 | navTitle: { | 287 | navTitle: { |
220 | color: 'white', | 288 | color: 'white', |
221 | marginLeft: 60, | 289 | marginLeft: 60, |
222 | marginRight: 60, | 290 | marginRight: 60, |
223 | }, | 291 | }, |
292 | + button: { | ||
293 | + width: 60, | ||
294 | + }, | ||
224 | rightButton: { | 295 | rightButton: { |
225 | width: 100, | 296 | width: 100, |
226 | height: 37, | 297 | height: 37, |
@@ -242,4 +313,30 @@ let styles = StyleSheet.create({ | @@ -242,4 +313,30 @@ let styles = StyleSheet.create({ | ||
242 | textAlign: 'right', | 313 | textAlign: 'right', |
243 | fontSize: 17, | 314 | fontSize: 17, |
244 | }, | 315 | }, |
316 | + title: { | ||
317 | + flexDirection: 'row', | ||
318 | + // justifyContent: 'space-around', | ||
319 | + alignItems: 'center', | ||
320 | + | ||
321 | + marginTop: 12, | ||
322 | + // width: Dimensions.get('window').width - 2 * 50, | ||
323 | + position: 'absolute', | ||
324 | + ...Platform.select({ | ||
325 | + ios: { | ||
326 | + top: 20, | ||
327 | + }, | ||
328 | + android: { | ||
329 | + top: 5, | ||
330 | + }, | ||
331 | + }), | ||
332 | + left: 0, | ||
333 | + right: 0, | ||
334 | + backgroundColor: 'transparent', | ||
335 | + }, | ||
336 | + text: { | ||
337 | + textAlign: 'center', | ||
338 | + fontSize: 18, | ||
339 | + fontWeight: 'bold', | ||
340 | + color: '#ffffff', | ||
341 | + }, | ||
245 | }); | 342 | }); |
@@ -454,6 +454,28 @@ class NavBar extends React.Component { | @@ -454,6 +454,28 @@ class NavBar extends React.Component { | ||
454 | ); | 454 | ); |
455 | } | 455 | } |
456 | 456 | ||
457 | + getNavBarBackgroundImage(channel) { | ||
458 | + let img = require('../images/nav/boy/navbar_bg.png'); | ||
459 | + switch (parseInt(channel)) { | ||
460 | + case 1: | ||
461 | + img = require('../images/nav/boy/navbar_bg.png'); | ||
462 | + break; | ||
463 | + case 2: | ||
464 | + img = require('../images/nav/girl/navbar_bg.png'); | ||
465 | + break; | ||
466 | + case 3: | ||
467 | + img = require('../images/nav/kid/navbar_bg.png'); | ||
468 | + break; | ||
469 | + case 4: | ||
470 | + img = require('../images/nav/lifestyle/navbar_bg.png'); | ||
471 | + break; | ||
472 | + case 5: | ||
473 | + img = require('../images/nav/yoho/navbar_bg.png'); | ||
474 | + break; | ||
475 | + } | ||
476 | + return img; | ||
477 | + } | ||
478 | + | ||
457 | render() { | 479 | render() { |
458 | let state = this.props.navigationState; | 480 | let state = this.props.navigationState; |
459 | let selected = state.children[state.index]; | 481 | let selected = state.children[state.index]; |
@@ -474,6 +496,7 @@ class NavBar extends React.Component { | @@ -474,6 +496,7 @@ class NavBar extends React.Component { | ||
474 | const renderTitle = selected.renderTitle || | 496 | const renderTitle = selected.renderTitle || |
475 | selected.component.renderTitle || | 497 | selected.component.renderTitle || |
476 | this.props.renderTitle; | 498 | this.props.renderTitle; |
499 | + | ||
477 | return ( | 500 | return ( |
478 | <Animated.View | 501 | <Animated.View |
479 | style={[ | 502 | style={[ |
@@ -484,7 +507,7 @@ class NavBar extends React.Component { | @@ -484,7 +507,7 @@ class NavBar extends React.Component { | ||
484 | ]} | 507 | ]} |
485 | > | 508 | > |
486 | <Image | 509 | <Image |
487 | - source={require('../images/navbar.png')} | 510 | + source={this.getNavBarBackgroundImage(this.props.getChannel())} |
488 | style={styles.image} | 511 | style={styles.image} |
489 | > | 512 | > |
490 | {renderTitle ? renderTitle(navProps) : state.children.map(this.renderTitle, this)} | 513 | {renderTitle ? renderTitle(navProps) : state.children.map(this.renderTitle, this)} |
@@ -8,6 +8,7 @@ import Notice from './Notice'; | @@ -8,6 +8,7 @@ import Notice from './Notice'; | ||
8 | import YH_SectionView from './YH_SectionView'; | 8 | import YH_SectionView from './YH_SectionView'; |
9 | import ListCell from './ListCell'; | 9 | import ListCell from './ListCell'; |
10 | import UploadProgress from './UploadProgress'; | 10 | import UploadProgress from './UploadProgress'; |
11 | +import LoadingIndicator from '../../../common/components/LoadingIndicator'; | ||
11 | import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator'; | 12 | import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator'; |
12 | 13 | ||
13 | 14 | ||
@@ -172,11 +173,10 @@ export default class Home extends React.Component { | @@ -172,11 +173,10 @@ export default class Home extends React.Component { | ||
172 | /> | 173 | /> |
173 | ); | 174 | ); |
174 | case 'section': | 175 | case 'section': |
175 | - console.log(rowData.toJS()); | ||
176 | return ( | 176 | return ( |
177 | <YH_SectionView | 177 | <YH_SectionView |
178 | style={styles.carouselSection} | 178 | style={styles.carouselSection} |
179 | - items={rowData} | 179 | + items={rowData.toJS()} |
180 | onClick={(info) => { | 180 | onClick={(info) => { |
181 | let item = rowData.get(info.index); | 181 | let item = rowData.get(info.index); |
182 | let section = { | 182 | let section = { |
@@ -241,7 +241,7 @@ export default class Home extends React.Component { | @@ -241,7 +241,7 @@ export default class Home extends React.Component { | ||
241 | } | 241 | } |
242 | 242 | ||
243 | render() { | 243 | render() { |
244 | - let {banner, notice, section, recommendation, isRefreshing, isLoadingMore, isFetching} = this.props; | 244 | + let {banner, notice, section, recommendation, isRefreshing, isLoadingMore, isFetching, isSyncFetching} = this.props; |
245 | let dataSource = { | 245 | let dataSource = { |
246 | progressing: this.props.progressing.toArray(), | 246 | progressing: this.props.progressing.toArray(), |
247 | banner: banner.toArray(), | 247 | banner: banner.toArray(), |
@@ -251,30 +251,35 @@ export default class Home extends React.Component { | @@ -251,30 +251,35 @@ export default class Home extends React.Component { | ||
251 | } | 251 | } |
252 | 252 | ||
253 | return ( | 253 | return ( |
254 | - <ListView | ||
255 | - dataSource={this.dataSource.cloneWithRowsAndSections(dataSource)} | ||
256 | - renderRow={this._renderRow} | ||
257 | - renderSectionHeader={this._renderSectionHeader} | ||
258 | - renderSeparator={this._renderSeparator} | ||
259 | - enableEmptySections={true} | ||
260 | - refreshControl={ | ||
261 | - <RefreshControl | ||
262 | - refreshing={isRefreshing} | ||
263 | - onRefresh={() => { | ||
264 | - this.props.onRefresh && this.props.onRefresh(); | ||
265 | - }} | ||
266 | - /> | ||
267 | - } | ||
268 | - onEndReached={() => { | ||
269 | - this.props.onEndReached && this.props.onEndReached(); | ||
270 | - }} | ||
271 | - renderFooter={()=>{ | ||
272 | - return <LoadMoreIndicator | ||
273 | - isVisible={isLoadingMore} | ||
274 | - animating={isFetching} | 254 | + <View> |
255 | + <ListView | ||
256 | + dataSource={this.dataSource.cloneWithRowsAndSections(dataSource)} | ||
257 | + renderRow={this._renderRow} | ||
258 | + renderSectionHeader={this._renderSectionHeader} | ||
259 | + renderSeparator={this._renderSeparator} | ||
260 | + enableEmptySections={true} | ||
261 | + refreshControl={ | ||
262 | + <RefreshControl | ||
263 | + refreshing={isRefreshing} | ||
264 | + onRefresh={() => { | ||
265 | + this.props.onRefresh && this.props.onRefresh(); | ||
266 | + }} | ||
275 | /> | 267 | /> |
276 | - }} | ||
277 | - /> | 268 | + } |
269 | + onEndReached={() => { | ||
270 | + this.props.onEndReached && this.props.onEndReached(); | ||
271 | + }} | ||
272 | + renderFooter={()=>{ | ||
273 | + return <LoadMoreIndicator | ||
274 | + isVisible={isLoadingMore} | ||
275 | + animating={isFetching} | ||
276 | + /> | ||
277 | + }} | ||
278 | + /> | ||
279 | + <LoadingIndicator | ||
280 | + isVisible={isSyncFetching} | ||
281 | + /> | ||
282 | + </View> | ||
278 | ); | 283 | ); |
279 | 284 | ||
280 | } | 285 | } |
@@ -26,15 +26,14 @@ class SectionView extends React.Component { | @@ -26,15 +26,14 @@ class SectionView extends React.Component { | ||
26 | } | 26 | } |
27 | 27 | ||
28 | render() { | 28 | render() { |
29 | - | ||
30 | - return <YH_SectionView {...this.props} items={this.props.items.toJS()} onClick={this._onClick} />; | 29 | + return <YH_SectionView {...this.props} items={this.props.items} onClick={this._onClick} />; |
31 | } | 30 | } |
32 | } | 31 | } |
33 | 32 | ||
34 | SectionView.propTypes = { | 33 | SectionView.propTypes = { |
35 | - items: ImmutablePropTypes.listOf( | ||
36 | - ImmutablePropTypes.contains({ | ||
37 | - header: ImmutablePropTypes.contains({ | 34 | + items: React.PropTypes.arrayOf( |
35 | + React.PropTypes.shape({ | ||
36 | + header: React.PropTypes.shape({ | ||
38 | id: React.PropTypes.number.isRequired, | 37 | id: React.PropTypes.number.isRequired, |
39 | logo: React.PropTypes.string.isRequired, | 38 | logo: React.PropTypes.string.isRequired, |
40 | title: React.PropTypes.string.isRequired, | 39 | title: React.PropTypes.string.isRequired, |
@@ -42,15 +41,15 @@ SectionView.propTypes = { | @@ -42,15 +41,15 @@ SectionView.propTypes = { | ||
42 | commentNum: React.PropTypes.number.isRequired, | 41 | commentNum: React.PropTypes.number.isRequired, |
43 | laudCount: React.PropTypes.number.isRequired, | 42 | laudCount: React.PropTypes.number.isRequired, |
44 | }), | 43 | }), |
45 | - hot: ImmutablePropTypes.contains({ | 44 | + hot: React.PropTypes.shape({ |
46 | avatar: React.PropTypes.string, | 45 | avatar: React.PropTypes.string, |
47 | content: React.PropTypes.string.isRequired, | 46 | content: React.PropTypes.string.isRequired, |
48 | }), | 47 | }), |
49 | - new: ImmutablePropTypes.contains({ | 48 | + new: React.PropTypes.shape({ |
50 | avatar: React.PropTypes.string, | 49 | avatar: React.PropTypes.string, |
51 | content: React.PropTypes.string.isRequired, | 50 | content: React.PropTypes.string.isRequired, |
52 | }), | 51 | }), |
53 | - num: ImmutablePropTypes.contains({ | 52 | + num: React.PropTypes.shape({ |
54 | onedayAddNum: React.PropTypes.number.isRequired, | 53 | onedayAddNum: React.PropTypes.number.isRequired, |
55 | }), | 54 | }), |
56 | }) | 55 | }) |
@@ -4,6 +4,11 @@ export default keyMirror({ | @@ -4,6 +4,11 @@ export default keyMirror({ | ||
4 | 4 | ||
5 | SET_PLATFORM: null, | 5 | SET_PLATFORM: null, |
6 | SET_CONTAINER: null, | 6 | SET_CONTAINER: null, |
7 | + SET_CHANNEL: null, | ||
8 | + | ||
9 | + SYNC_USER_REQUEST: null, | ||
10 | + SYNC_USER_SUCCESS: null, | ||
11 | + SYNC_USER_FAILURE: null, | ||
7 | 12 | ||
8 | GO_TO_SECTION: null, | 13 | GO_TO_SECTION: null, |
9 | 14 |
@@ -11,6 +11,7 @@ import Immutable, {Map, List} from 'immutable'; | @@ -11,6 +11,7 @@ import Immutable, {Map, List} from 'immutable'; | ||
11 | import Home from '../components/home/Home'; | 11 | import Home from '../components/home/Home'; |
12 | 12 | ||
13 | import * as homeActions from '../reducers/home/homeActions'; | 13 | import * as homeActions from '../reducers/home/homeActions'; |
14 | +import * as appActions from '../reducers/app/appActions'; | ||
14 | 15 | ||
15 | import {Actions} from 'react-native-router-flux'; | 16 | import {Actions} from 'react-native-router-flux'; |
16 | 17 | ||
@@ -22,6 +23,7 @@ const { | @@ -22,6 +23,7 @@ const { | ||
22 | Platform, | 23 | Platform, |
23 | NativeModules, | 24 | NativeModules, |
24 | InteractionManager, | 25 | InteractionManager, |
26 | + NativeAppEventEmitter, | ||
25 | } = ReactNative; | 27 | } = ReactNative; |
26 | 28 | ||
27 | /** | 29 | /** |
@@ -30,6 +32,7 @@ const { | @@ -30,6 +32,7 @@ const { | ||
30 | */ | 32 | */ |
31 | const actions = [ | 33 | const actions = [ |
32 | homeActions, | 34 | homeActions, |
35 | + appActions, | ||
33 | ]; | 36 | ]; |
34 | 37 | ||
35 | /** | 38 | /** |
@@ -74,16 +77,35 @@ class HomeContainer extends React.Component { | @@ -74,16 +77,35 @@ class HomeContainer extends React.Component { | ||
74 | this._onRefresh = this._onRefresh.bind(this); | 77 | this._onRefresh = this._onRefresh.bind(this); |
75 | this._onEndReached = this._onEndReached.bind(this); | 78 | this._onEndReached = this._onEndReached.bind(this); |
76 | 79 | ||
80 | + if (parseInt(this.props.app.container) === 1) { | ||
81 | + this.subscription = NativeAppEventEmitter.addListener( | ||
82 | + 'ChannelReminder', | ||
83 | + (reminder) => { | ||
84 | + this.props.actions.setChannel(reminder.channel); | ||
85 | + Actions.refresh({channel: reminder.channel}); | ||
86 | + } | ||
87 | + ); | ||
88 | + } | ||
77 | } | 89 | } |
78 | 90 | ||
79 | componentDidMount() { | 91 | componentDidMount() { |
80 | - let RNNativeConfig = NativeModules.RNNativeConfig; | ||
81 | - RNNativeConfig.hideNavBar(); | ||
82 | InteractionManager.runAfterInteractions(() => { | 92 | InteractionManager.runAfterInteractions(() => { |
83 | this._onRefresh(); | 93 | this._onRefresh(); |
84 | }); | 94 | }); |
85 | } | 95 | } |
86 | 96 | ||
97 | + componentWillReceiveProps(nextProps) { | ||
98 | + if (nextProps.showNativeTabBar) { | ||
99 | + ReactNative.NativeModules.YH_CommunityHelper.showTabBar(); | ||
100 | + } | ||
101 | + } | ||
102 | + | ||
103 | + componentWillUnmount() { | ||
104 | + if (parseInt(this.props.app.container) === 1) { | ||
105 | + this.subscription && this.subscription.remove(); | ||
106 | + } | ||
107 | + } | ||
108 | + | ||
87 | _onPressBanner(url) { | 109 | _onPressBanner(url) { |
88 | console.log('banner'); | 110 | console.log('banner'); |
89 | 111 | ||
@@ -94,7 +116,7 @@ class HomeContainer extends React.Component { | @@ -94,7 +116,7 @@ class HomeContainer extends React.Component { | ||
94 | } | 116 | } |
95 | 117 | ||
96 | _onPressSection(section) { | 118 | _onPressSection(section) { |
97 | - this.props.actions.goToSection(section); | 119 | + this.props.actions.goToSection(section, this.props.navigationState.name); |
98 | } | 120 | } |
99 | 121 | ||
100 | _onPressPost(url) { | 122 | _onPressPost(url) { |
@@ -155,10 +177,9 @@ class HomeContainer extends React.Component { | @@ -155,10 +177,9 @@ class HomeContainer extends React.Component { | ||
155 | image:'', | 177 | image:'', |
156 | }]; | 178 | }]; |
157 | 179 | ||
158 | - | ||
159 | progressing = Immutable.fromJS(progressing); | 180 | progressing = Immutable.fromJS(progressing); |
160 | 181 | ||
161 | - let {banner, notice, section, recommendation, isFetching, ptr} = this.props.home; | 182 | + let {banner, notice, section, recommendation, isFetching, ptr, sync} = this.props.home; |
162 | let bannerData = Immutable.fromJS([banner.list]); | 183 | let bannerData = Immutable.fromJS([banner.list]); |
163 | let noticeData = notice.open === 'Y' ? Immutable.fromJS([notice.list]) : List(); | 184 | let noticeData = notice.open === 'Y' ? Immutable.fromJS([notice.list]) : List(); |
164 | let sectionData = Immutable.fromJS([section]); | 185 | let sectionData = Immutable.fromJS([section]); |
@@ -196,6 +217,8 @@ class HomeContainer extends React.Component { | @@ -196,6 +217,8 @@ class HomeContainer extends React.Component { | ||
196 | onUploadSuccess={this._onUploadSuccess} | 217 | onUploadSuccess={this._onUploadSuccess} |
197 | onUploadRetry={this._onUploadRetry} | 218 | onUploadRetry={this._onUploadRetry} |
198 | onUploadDelete={this._onUploadDelete} | 219 | onUploadDelete={this._onUploadDelete} |
220 | + isSyncFetching={sync.isFetching} | ||
221 | + | ||
199 | /> | 222 | /> |
200 | </View> | 223 | </View> |
201 | ); | 224 | ); |
@@ -73,17 +73,23 @@ class SectionContainer extends React.Component { | @@ -73,17 +73,23 @@ class SectionContainer extends React.Component { | ||
73 | this._onPressLike = this._onPressLike.bind(this); | 73 | this._onPressLike = this._onPressLike.bind(this); |
74 | this._onRefresh = this._onRefresh.bind(this); | 74 | this._onRefresh = this._onRefresh.bind(this); |
75 | this._onEndReached = this._onEndReached.bind(this); | 75 | this._onEndReached = this._onEndReached.bind(this); |
76 | - | ||
77 | - this.page = 0; | ||
78 | } | 76 | } |
79 | 77 | ||
80 | componentDidMount() { | 78 | componentDidMount() { |
79 | + if (this.props.section.previousScene === 'Home') { | ||
80 | + ReactNative.NativeModules.YH_CommunityHelper.hideTabBar(); | ||
81 | + } | ||
82 | + | ||
81 | InteractionManager.runAfterInteractions(() => { | 83 | InteractionManager.runAfterInteractions(() => { |
82 | this._onRefresh(); | 84 | this._onRefresh(); |
83 | }); | 85 | }); |
84 | } | 86 | } |
85 | 87 | ||
86 | componentWillUnmount() { | 88 | componentWillUnmount() { |
89 | + if (this.props.section.previousScene === 'Home') { | ||
90 | + Actions.refresh({key: 'Home', showNativeTabBar: true}); | ||
91 | + } | ||
92 | + | ||
87 | this.props.actions.sectionClean(); | 93 | this.props.actions.sectionClean(); |
88 | } | 94 | } |
89 | 95 | ||
@@ -189,7 +195,7 @@ let navbarHeight = (Platform.OS === 'android') ? 50 : 64; | @@ -189,7 +195,7 @@ let navbarHeight = (Platform.OS === 'android') ? 50 : 64; | ||
189 | let styles = StyleSheet.create({ | 195 | let styles = StyleSheet.create({ |
190 | container: { | 196 | container: { |
191 | top: navbarHeight, | 197 | top: navbarHeight, |
192 | - height: height - navbarHeight - 49, | 198 | + height: height - navbarHeight, |
193 | flex: 1, | 199 | flex: 1, |
194 | }, | 200 | }, |
195 | 201 |
js/community/images/home/sd_show_ic@2x.png
0 → 100644
4.71 KB
js/community/images/home/sd_show_ic@3x.png
0 → 100644
6.41 KB
1.42 KB
2.27 KB
js/community/images/nav/kid/navbar_bg@2x.png
0 → 100644
636 Bytes
js/community/images/nav/kid/navbar_bg@3x.png
0 → 100644
1.48 KB
1.42 KB
2.37 KB
1.42 KB
2.37 KB
@@ -11,7 +11,7 @@ import {Actions} from 'react-native-router-flux'; | @@ -11,7 +11,7 @@ import {Actions} from 'react-native-router-flux'; | ||
11 | const { | 11 | const { |
12 | SET_PLATFORM, | 12 | SET_PLATFORM, |
13 | SET_CONTAINER, | 13 | SET_CONTAINER, |
14 | - | 14 | + SET_CHANNEL, |
15 | } = require('../../constants/actionTypes').default; | 15 | } = require('../../constants/actionTypes').default; |
16 | 16 | ||
17 | export function setPlatform(platform) { | 17 | export function setPlatform(platform) { |
@@ -27,3 +27,10 @@ export function setContianer(container) { | @@ -27,3 +27,10 @@ export function setContianer(container) { | ||
27 | payload: container | 27 | payload: container |
28 | }; | 28 | }; |
29 | } | 29 | } |
30 | + | ||
31 | +export function setChannel(channel) { | ||
32 | + return { | ||
33 | + type: SET_CHANNEL, | ||
34 | + payload: channel | ||
35 | + }; | ||
36 | +} |
@@ -16,7 +16,8 @@ import {Record, List, Map} from 'immutable'; | @@ -16,7 +16,8 @@ import {Record, List, Map} from 'immutable'; | ||
16 | */ | 16 | */ |
17 | let InitialState = Record({ | 17 | let InitialState = Record({ |
18 | platform: 'ios', // ios, android | 18 | platform: 'ios', // ios, android |
19 | - container: 1, // 1:有货APP,2:YOHO! | 19 | + container: 1, // 1:有货APP, 2:YOHO! |
20 | + channel: 1, // 1 - boy, 2 - girl, 3 - kid, 4 - lifestyle, 5 - yoho | ||
20 | }); | 21 | }); |
21 | 22 | ||
22 | export default InitialState; | 23 | export default InitialState; |
@@ -14,7 +14,7 @@ import InitialState from './appInitialState'; | @@ -14,7 +14,7 @@ import InitialState from './appInitialState'; | ||
14 | const { | 14 | const { |
15 | SET_PLATFORM, | 15 | SET_PLATFORM, |
16 | SET_CONTAINER, | 16 | SET_CONTAINER, |
17 | - | 17 | + SET_CHANNEL, |
18 | } = require('../../constants/actionTypes').default; | 18 | } = require('../../constants/actionTypes').default; |
19 | 19 | ||
20 | const initialState = new InitialState; | 20 | const initialState = new InitialState; |
@@ -32,6 +32,8 @@ export default function appReducer(state = initialState, action) { | @@ -32,6 +32,8 @@ export default function appReducer(state = initialState, action) { | ||
32 | return state.set('platform', action.payload); | 32 | return state.set('platform', action.payload); |
33 | case SET_CONTAINER: | 33 | case SET_CONTAINER: |
34 | return state.set('container', action.payload); | 34 | return state.set('container', action.payload); |
35 | + case SET_CHANNEL: | ||
36 | + return state.set('channel', action.payload); | ||
35 | } | 37 | } |
36 | 38 | ||
37 | return state; | 39 | return state; |
@@ -21,9 +21,46 @@ const { | @@ -21,9 +21,46 @@ const { | ||
21 | HOME_RECOMMENDATION_FAILURE, | 21 | HOME_RECOMMENDATION_FAILURE, |
22 | 22 | ||
23 | GO_TO_SECTION, | 23 | GO_TO_SECTION, |
24 | + SYNC_USER_REQUEST, | ||
25 | + SYNC_USER_SUCCESS, | ||
26 | + SYNC_USER_FAILURE, | ||
24 | 27 | ||
25 | } = require('../../constants/actionTypes').default; | 28 | } = require('../../constants/actionTypes').default; |
26 | 29 | ||
30 | +export function syncUserRequest() { | ||
31 | + return { | ||
32 | + type: SYNC_USER_REQUEST, | ||
33 | + }; | ||
34 | +} | ||
35 | + | ||
36 | +export function syncUserSuccess(json) { | ||
37 | + return { | ||
38 | + type: SYNC_USER_SUCCESS, | ||
39 | + payload: json | ||
40 | + }; | ||
41 | +} | ||
42 | + | ||
43 | +export function syncUserFailure(error) { | ||
44 | + return { | ||
45 | + type: SYNC_USER_FAILURE, | ||
46 | + payload: error | ||
47 | + }; | ||
48 | +} | ||
49 | + | ||
50 | +export function syncUser(uid) { | ||
51 | + return (dispatch, getState) => { | ||
52 | + dispatch(syncUserRequest()); | ||
53 | + let {app} = getState(); | ||
54 | + return new HomeService().syncUser(uid, app.container) | ||
55 | + .then(json => { | ||
56 | + dispatch(syncUserSuccess(json.ssouid)); | ||
57 | + }) | ||
58 | + .catch(error => { | ||
59 | + dispatch(syncUserFailure(error)); | ||
60 | + }); | ||
61 | + }; | ||
62 | +} | ||
63 | + | ||
27 | export function bnsRequest() { | 64 | export function bnsRequest() { |
28 | return { | 65 | return { |
29 | type: HOME_BNS_REQUEST, | 66 | type: HOME_BNS_REQUEST, |
@@ -83,7 +120,7 @@ export function bannerNoticeSection() { | @@ -83,7 +120,7 @@ export function bannerNoticeSection() { | ||
83 | export function recommendation(ptr = false) { | 120 | export function recommendation(ptr = false) { |
84 | return (dispatch, getState) => { | 121 | return (dispatch, getState) => { |
85 | let {home} = getState(); | 122 | let {home} = getState(); |
86 | - if (home.isFetching) { | 123 | + if (home.isFetching || home.recommendation.endReached) { |
87 | return; | 124 | return; |
88 | } | 125 | } |
89 | dispatch(recommendationRequest(ptr)); | 126 | dispatch(recommendationRequest(ptr)); |
@@ -110,11 +147,11 @@ export function recommendation(ptr = false) { | @@ -110,11 +147,11 @@ export function recommendation(ptr = false) { | ||
110 | }; | 147 | }; |
111 | } | 148 | } |
112 | 149 | ||
113 | -export function goToSection(section) { | 150 | +export function goToSection(section, previousScene) { |
114 | Actions.Section(); | 151 | Actions.Section(); |
115 | return { | 152 | return { |
116 | type: GO_TO_SECTION, | 153 | type: GO_TO_SECTION, |
117 | - payload: section, | 154 | + payload: {...section, previousScene}, |
118 | }; | 155 | }; |
119 | } | 156 | } |
120 | 157 | ||
@@ -223,8 +260,10 @@ function parseRecommendation(json) { | @@ -223,8 +260,10 @@ function parseRecommendation(json) { | ||
223 | posts.push(post); | 260 | posts.push(post); |
224 | }); | 261 | }); |
225 | 262 | ||
263 | + let endReached = posts.length == 0; | ||
226 | return { | 264 | return { |
227 | lastedTime, | 265 | lastedTime, |
228 | list: posts, | 266 | list: posts, |
267 | + endReached, | ||
229 | } | 268 | } |
230 | } | 269 | } |
@@ -31,6 +31,12 @@ let InitialState = Record({ | @@ -31,6 +31,12 @@ let InitialState = Record({ | ||
31 | recommendation: new (Record({ | 31 | recommendation: new (Record({ |
32 | lastedTime: 0, | 32 | lastedTime: 0, |
33 | list: List(), | 33 | list: List(), |
34 | + endReached: false, | ||
35 | + })), | ||
36 | + sync: new (Record({ | ||
37 | + isFetching: false, | ||
38 | + error: null, | ||
39 | + ssouid: 0, | ||
34 | })), | 40 | })), |
35 | }); | 41 | }); |
36 | 42 |
@@ -22,6 +22,9 @@ const { | @@ -22,6 +22,9 @@ const { | ||
22 | HOME_RECOMMENDATION_SUCCESS, | 22 | HOME_RECOMMENDATION_SUCCESS, |
23 | HOME_RECOMMENDATION_FAILURE, | 23 | HOME_RECOMMENDATION_FAILURE, |
24 | 24 | ||
25 | + SYNC_USER_REQUEST, | ||
26 | + SYNC_USER_SUCCESS, | ||
27 | + SYNC_USER_FAILURE, | ||
25 | 28 | ||
26 | } = require('../../constants/actionTypes').default; | 29 | } = require('../../constants/actionTypes').default; |
27 | 30 | ||
@@ -55,10 +58,11 @@ export default function homeReducer(state = initialState, action) { | @@ -55,10 +58,11 @@ export default function homeReducer(state = initialState, action) { | ||
55 | return nextState; | 58 | return nextState; |
56 | } | 59 | } |
57 | case HOME_RECOMMENDATION_SUCCESS: { | 60 | case HOME_RECOMMENDATION_SUCCESS: { |
58 | - let {lastedTime, list} = action.payload; | 61 | + let {lastedTime, list, endReached} = action.payload; |
59 | let nextState = state.set('isFetching', false) | 62 | let nextState = state.set('isFetching', false) |
60 | .set('error', null) | 63 | .set('error', null) |
61 | .setIn(['recommendation', 'lastedTime'], lastedTime) | 64 | .setIn(['recommendation', 'lastedTime'], lastedTime) |
65 | + .setIn(['recommendation', 'endReached'], endReached) | ||
62 | .setIn(['recommendation', 'list'], Immutable.fromJS(list)); | 66 | .setIn(['recommendation', 'list'], Immutable.fromJS(list)); |
63 | return nextState; | 67 | return nextState; |
64 | } | 68 | } |
@@ -67,6 +71,23 @@ export default function homeReducer(state = initialState, action) { | @@ -67,6 +71,23 @@ export default function homeReducer(state = initialState, action) { | ||
67 | return state.set('isFetching', false) | 71 | return state.set('isFetching', false) |
68 | .set('error', action.payload); | 72 | .set('error', action.payload); |
69 | 73 | ||
74 | + case SYNC_USER_REQUEST: { | ||
75 | + let nextState = state.setIn(['sync', 'isFetching'], true) | ||
76 | + .setIn(['sync', 'error'], null); | ||
77 | + return nextState; | ||
78 | + } | ||
79 | + | ||
80 | + case SYNC_USER_SUCCESS: { | ||
81 | + let nextState = state.setIn(['sync', 'isFetching'], false) | ||
82 | + .setIn(['sync', 'error'], null) | ||
83 | + .setIn(['sync', 'ssouid'], action.payload); | ||
84 | + return nextState; | ||
85 | + } | ||
86 | + | ||
87 | + case SYNC_USER_FAILURE: | ||
88 | + return state.setIn(['sync', 'isFetching'], false) | ||
89 | + .setIn(['sync', 'error'], action.payload); | ||
90 | + | ||
70 | } | 91 | } |
71 | 92 | ||
72 | return state; | 93 | return state; |
@@ -105,7 +105,7 @@ export function header() { | @@ -105,7 +105,7 @@ export function header() { | ||
105 | export function newPost(ptr = false) { | 105 | export function newPost(ptr = false) { |
106 | return (dispatch, getState) => { | 106 | return (dispatch, getState) => { |
107 | let {section} = getState(); | 107 | let {section} = getState(); |
108 | - if (section.new.isFetching) { | 108 | + if (section.new.isFetching || section.new.endReached) { |
109 | return; | 109 | return; |
110 | } | 110 | } |
111 | dispatch(newPostRequest(ptr)); | 111 | dispatch(newPostRequest(ptr)); |
@@ -135,7 +135,7 @@ export function newPost(ptr = false) { | @@ -135,7 +135,7 @@ export function newPost(ptr = false) { | ||
135 | export function hotPost(ptr = false) { | 135 | export function hotPost(ptr = false) { |
136 | return (dispatch, getState) => { | 136 | return (dispatch, getState) => { |
137 | let {section} = getState(); | 137 | let {section} = getState(); |
138 | - if (section.hot.isFetching) { | 138 | + if (section.hot.isFetching || section.hot.endReached) { |
139 | return; | 139 | return; |
140 | } | 140 | } |
141 | dispatch(hotPostRequest(ptr)); | 141 | dispatch(hotPostRequest(ptr)); |
@@ -252,8 +252,11 @@ function parseNewPost(json) { | @@ -252,8 +252,11 @@ function parseNewPost(json) { | ||
252 | posts.push(post); | 252 | posts.push(post); |
253 | }); | 253 | }); |
254 | 254 | ||
255 | + let endReached = posts.length == 0; | ||
256 | + | ||
255 | return { | 257 | return { |
256 | lastedTime, | 258 | lastedTime, |
257 | list: posts, | 259 | list: posts, |
260 | + endReached, | ||
258 | } | 261 | } |
259 | } | 262 | } |
@@ -38,13 +38,16 @@ let InitialState = Record({ | @@ -38,13 +38,16 @@ let InitialState = Record({ | ||
38 | error: null, | 38 | error: null, |
39 | lastedTime: 0, | 39 | lastedTime: 0, |
40 | list: List(), | 40 | list: List(), |
41 | + endReached: false, | ||
41 | })), | 42 | })), |
42 | new: new (Record({ | 43 | new: new (Record({ |
43 | isFetching: false, | 44 | isFetching: false, |
44 | error: null, | 45 | error: null, |
45 | lastedTime: 0, | 46 | lastedTime: 0, |
46 | list: List(), | 47 | list: List(), |
48 | + endReached: false, | ||
47 | })), | 49 | })), |
50 | + previousScene: '', | ||
48 | }); | 51 | }); |
49 | 52 | ||
50 | export default InitialState; | 53 | export default InitialState; |
@@ -70,19 +70,21 @@ export default function sectionReducer(state = initialState, action) { | @@ -70,19 +70,21 @@ export default function sectionReducer(state = initialState, action) { | ||
70 | } | 70 | } |
71 | 71 | ||
72 | case SECTION_HOT_POST_SUCCESS: { | 72 | case SECTION_HOT_POST_SUCCESS: { |
73 | - let {lastedTime, list} = action.payload; | 73 | + let {lastedTime, list, endReached} = action.payload; |
74 | let nextState = state.setIn(['hot', 'isFetching'], false) | 74 | let nextState = state.setIn(['hot', 'isFetching'], false) |
75 | .setIn(['hot', 'error'], null) | 75 | .setIn(['hot', 'error'], null) |
76 | .setIn(['hot', 'lastedTime'], lastedTime) | 76 | .setIn(['hot', 'lastedTime'], lastedTime) |
77 | + .setIn(['hot', 'endReached'], endReached) | ||
77 | .setIn(['hot', 'list'], Immutable.fromJS(list)); | 78 | .setIn(['hot', 'list'], Immutable.fromJS(list)); |
78 | return nextState; | 79 | return nextState; |
79 | } | 80 | } |
80 | 81 | ||
81 | case SECTION_NEW_POST_SUCCESS: { | 82 | case SECTION_NEW_POST_SUCCESS: { |
82 | - let {lastedTime, list} = action.payload; | 83 | + let {lastedTime, list, endReached} = action.payload; |
83 | let nextState = state.setIn(['new', 'isFetching'], false) | 84 | let nextState = state.setIn(['new', 'isFetching'], false) |
84 | .setIn(['new', 'error'], null) | 85 | .setIn(['new', 'error'], null) |
85 | .setIn(['new', 'lastedTime'], lastedTime) | 86 | .setIn(['new', 'lastedTime'], lastedTime) |
87 | + .setIn(['new', 'endReached'], endReached) | ||
86 | .setIn(['new', 'list'], Immutable.fromJS(list)); | 88 | .setIn(['new', 'list'], Immutable.fromJS(list)); |
87 | return nextState; | 89 | return nextState; |
88 | } | 90 | } |
@@ -104,7 +106,8 @@ export default function sectionReducer(state = initialState, action) { | @@ -104,7 +106,8 @@ export default function sectionReducer(state = initialState, action) { | ||
104 | 106 | ||
105 | case GO_TO_SECTION: | 107 | case GO_TO_SECTION: |
106 | return state.set('id', action.payload.id) | 108 | return state.set('id', action.payload.id) |
107 | - .set('name', action.payload.name); | 109 | + .set('name', action.payload.name) |
110 | + .set('previousScene', action.payload.previousScene); | ||
108 | 111 | ||
109 | case SECTION_CLEAN: | 112 | case SECTION_CLEAN: |
110 | return initialState; | 113 | return initialState; |
@@ -42,5 +42,21 @@ export default class HomeService { | @@ -42,5 +42,21 @@ export default class HomeService { | ||
42 | }); | 42 | }); |
43 | } | 43 | } |
44 | 44 | ||
45 | + async syncUser(uid, appChannel) { | ||
46 | + return await this.api.get({ | ||
47 | + url: '', | ||
48 | + body: { | ||
49 | + method: 'app.social.synCommunityUser', | ||
50 | + uid, | ||
51 | + appChannel, | ||
52 | + } | ||
53 | + }) | ||
54 | + .then((json) => { | ||
55 | + return json; | ||
56 | + }) | ||
57 | + .catch((error) => { | ||
58 | + throw(error); | ||
59 | + }); | ||
60 | + } | ||
45 | 61 | ||
46 | } | 62 | } |
-
Please register or login to post a comment