Authored by 于良

增加home模块 review by 盖剑秋

  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 homeInitialState from './reducers/home/homeInitialState';
  19 +
  20 +import HomeContainer from './containers/HomeContainer';
  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 + home: (new homeInitialState()),
  33 + };
  34 + return _initState;
  35 +}
  36 +
  37 +export default function native(platform) {
  38 +
  39 + let YH_Home = 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 + <HomeContainer />
  50 + </Provider>
  51 + );
  52 + }
  53 + });
  54 +
  55 + AppRegistry.registerComponent('YH_Home', () => YH_Home);
  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 Home 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 isPullToRefresh = ptr && isFetching;
  71 + let isLoadingMore = list.size != 0 && !ptr && isFetching;
  72 +
  73 + return (
  74 + <View style={styles.container}>
  75 + <ListView
  76 + ref={(c) => {
  77 + this.listView = c;
  78 + }}
  79 + contentContainerStyle={styles.contentContainer}
  80 + dataSource={this.dataSource.cloneWithRows(dataSource)}
  81 + renderRow={this._renderRow}
  82 + enableEmptySections={true}
  83 + enablePullToRefresh={true}
  84 + isOnPullToRefresh={isPullToRefresh}
  85 + onRefreshData={() => {
  86 + this.props.onRefresh && this.props.onRefresh();
  87 + }}
  88 + onEndReached={this._onEndReached}
  89 + renderFooter={this._renderFooter}
  90 + />
  91 + </View>
  92 + );
  93 + }
  94 +}
  95 +
  96 +let {width, height} = Dimensions.get('window');
  97 +
  98 +let styles = StyleSheet.create({
  99 + container: {
  100 + flex: 1,
  101 + backgroundColor: '#f0f0f0',
  102 + },
  103 + contentContainer: {
  104 +
  105 + },
  106 +});
  1 +import keyMirror from 'key-mirror';
  2 +
  3 +export default keyMirror({
  4 +
  5 + SET_PLATFORM: null,
  6 + SET_HOST: null,
  7 + SET_SERVICE_HOST: null,
  8 + SET_CHANNEL: null,
  9 +
  10 +
  11 +
  12 +});
  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 homeActions from '../reducers/home/homeActions';
  19 +
  20 +import Home from '../components/home/Home';
  21 +
  22 +
  23 +const actions = [
  24 + homeActions,
  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 HomeContainer extends Component {
  47 + constructor(props) {
  48 + super(props);
  49 +
  50 + this._onRefresh = this._onRefresh.bind(this);
  51 + this._onEndReached = this._onEndReached.bind(this);
  52 +
  53 + this.subscription = NativeAppEventEmitter.addListener(
  54 + 'ChannelDidChangeEvent',
  55 + (reminder) => {
  56 + this.home && this.home.trigggePullToRefresh();
  57 + }
  58 + );
  59 + }
  60 +
  61 + componentDidMount() {
  62 +
  63 + }
  64 +
  65 + componentWillUnmount() {
  66 + this.subscription && this.subscription.remove();
  67 + }
  68 +
  69 + _onRefresh() {
  70 + InteractionManager.runAfterInteractions(() => {
  71 +
  72 + });
  73 + }
  74 +
  75 + _onEndReached() {
  76 + InteractionManager.runAfterInteractions(() => {
  77 +
  78 + });
  79 + }
  80 +
  81 + render() {
  82 + let {home} = this.props;
  83 + return (
  84 + <View style={styles.container}>
  85 + <Home
  86 + ref={(c) => {
  87 + this.Home = c;
  88 + }}
  89 + data={home}
  90 + onRefresh={this._onRefresh}
  91 + onEndReached={this._onEndReached}
  92 + />
  93 + </View>
  94 + );
  95 + }
  96 +}
  97 +
  98 +let styles = StyleSheet.create({
  99 + container: {
  100 + flex: 1,
  101 + },
  102 +
  103 +});
  104 +
  105 +export default connect(mapStateToProps, mapDispatchToProps)(HomeContainer);
  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;
  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 +}
  1 +'use strict';
  2 +
  3 +import ReactNative from 'react-native';
  4 +import HomeService from '../../services/Home';
  5 +import store from 'react-native-simple-store';
  6 +
  7 +const {
  8 + SET_CHANNEL,
  9 +
  10 +} = require('../../constants/actionTypes').default;
  11 +
  12 +
  1 +'use strict';
  2 +
  3 +import {Record, List, Map} from 'immutable';
  4 +
  5 +let InitialState = Record({
  6 +
  7 +});
  8 +
  9 +export default InitialState;
  1 +'use strict';
  2 +
  3 +import InitialState from './homeInitialState';
  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 homeReducer(state=initialState, action) {
  14 + switch(action.type) {
  15 +
  16 +
  17 + }
  18 +
  19 + return state;
  20 +}
  1 +import {combineReducers} from 'redux';
  2 +import app from './app/appReducer';
  3 +import home from './home/homeReducer';
  4 +
  5 +const rootReducer = combineReducers({
  6 + app,
  7 + home,
  8 +});
  9 +
  10 +export default rootReducer;
  1 +'use strict';
  2 +
  3 +import Request from '../../common/services/Request';
  4 +
  5 +export default class HomeService {
  6 +
  7 + constructor (host) {
  8 + let baseURL = 'http://api.yoho.cn';
  9 + if(host){
  10 + baseURL = host;
  11 + }
  12 + this.api = new Request(baseURL);
  13 + }
  14 +
  15 +}
  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 +};