Authored by 于良

Merge branch 'local' into develop

... ... @@ -14,6 +14,7 @@ export default class LoadMoreIndicator extends Component {
static propTypes = {
isVisible: React.PropTypes.bool.isRequired,
animating: React.PropTypes.bool,
text: React.PropTypes.string,
};
... ...
... ... @@ -22,13 +22,15 @@ export default class SlicedImage extends React.Component {
_generateImageUrl(src) {
let style = StyleSheet.flatten(this.props.style);
let {width, height} = style;
width = PixelRatio.getPixelSizeForLayoutSize(width);
height = PixelRatio.getPixelSizeForLayoutSize(height);
let newSrc = src;
if (src.indexOf('imageView2') === -1) {
newSrc = src + '?imageView2/2/w/' + width + '/h/' + height;
} else {
newSrc = src.replace('{mode}', 2)
.replace('{width}', PixelRatio.getPixelSizeForLayoutSize(width))
.replace('{height}', PixelRatio.getPixelSizeForLayoutSize(height));
.replace('{width}', width)
.replace('{height}', height);
}
// __DEV__ && console.log(newSrc);
... ...
... ... @@ -50,8 +50,8 @@ import {
} from './reducers/app/appActions';
import {
syncUser,
} from './reducers/home/homeActions';
setUid,
} from './reducers/user/userActions';
import Immutable, {List, Record} from 'immutable';
... ... @@ -90,10 +90,19 @@ export default function community(platform) {
let YH_Community = React.createClass({
contanerIsYohoBuy() {
return parseInt(this.props.container) === 1;
},
render() {
const store = configureStore(getInitialState());
ReactNative.NativeModules.YH_CommunityHelper.uid()
.then(uid => {
store.dispatch(setUid(parseInt(uid)));
});
//Connect w/ the Router
const NewRouter = connect()(Router);
... ... @@ -104,8 +113,12 @@ export default function community(platform) {
store.dispatch(setChannel(this.props.channel));
store.dispatch(mergeCachedPosting());
let navBarStyle = contaner === 2 ? {backgroundColor: 'gray',} : null;
let extraTitleStyle = contaner === 2 ? {color: 'black',} : null;
let navBarStyle = this.contanerIsYohoBuy() ? null : {backgroundColor: 'white',};
let extraTitleStyle = this.contanerIsYohoBuy() ? null : {color: 'black',};
let backImage = this.contanerIsYohoBuy() ? require('./images/home/menu_back1.png') : require('./images/home/menu_back2.png');
let leftImage = this.contanerIsYohoBuy() ? require('./images/home/menu_burger1.png') : require('./images/home/menu_burger2.png');
let rightImage = this.contanerIsYohoBuy() ? require('./images/home/menu_write1.png') : require('./images/home/menu_write2.png');
// setup the router table with App selected as the initial component
return (
... ... @@ -120,6 +133,7 @@ export default function community(platform) {
titleStyle={[styles.navTitle, extraTitleStyle]}
leftButtonStyle={styles.leftButton}
rightButtonStyle={styles.rightButton}
backButtonImage={backImage}
getSceneStyle={(props) => {
return this.navPushStyle(props);
}}
... ... @@ -132,14 +146,14 @@ export default function community(platform) {
component={HomeContainer}
initial={true}
leftTitle={null}
leftButtonImage={require('./images/home/menu_burger1.png')}
leftButtonImage={leftImage}
onLeft={() => {
ReactNative.NativeModules.YH_CommunityHelper.toggleDrawer();
}}
rightTitle={null}
rightButtonImage={require('./images/home/menu_write.png')}
rightButtonImage={rightImage}
onRight={this.homeOnRight}
renderTitle={parseInt(this.props.container) === 1 ? this.renderHomeTitle : null}
renderTitle={this.contanerIsYohoBuy() ? this.renderHomeTitle : null}
getPostingState={
() => {
return store.getState().posting.inPosting;
... ... @@ -154,7 +168,7 @@ export default function community(platform) {
component={SectionContainer}
initial={false}
rightTitle={null}
rightButtonImage={require('./images/home/menu_write.png')}
rightButtonImage={rightImage}
onRight={this.homeOnRight}
getTitle={(childState) => {
let name = store.getState().section.get('name');
... ...
... ... @@ -38,8 +38,8 @@ import {
BackAndroid,
} from 'react-native';
import {Actions} from 'react-native-router-flux';
import _drawerImage from '../images/home/menu_burger.png';
import _backButtonImage from '../images/home/menu_back.png';
import _drawerImage from '../images/home/menu_burger1.png';
import _backButtonImage from '../images/home/menu_back1.png';
const styles = StyleSheet.create({
title: {
... ...
... ... @@ -112,7 +112,7 @@ export default class Home extends React.Component {
user: ImmutablePropTypes.contains({
avatar: React.PropTypes.string,
uid: React.PropTypes.number,
msgNumber: React.PropTypes.number,
msgCount: React.PropTypes.string,
}),
bannerDuration: React.PropTypes.number,
... ... @@ -260,7 +260,7 @@ export default class Home extends React.Component {
}
render() {
let {progressing, banner, notice, section, recommendation, user, isRefreshing, isLoadingMore, isFetching, isSyncFetching} = this.props;
let {progressing, banner, notice, section, recommendation, user, endReached, isRefreshing, isLoadingMore, isFetching, isSyncFetching} = this.props;
let dataSource = {
progressing: progressing.toArray(),
banner: banner.toArray(),
... ... @@ -290,10 +290,17 @@ export default class Home extends React.Component {
}
}}
renderFooter={()=>{
return <LoadMoreIndicator
isVisible={isLoadingMore}
animating={isFetching}
/>
if (endReached) {
return <LoadMoreIndicator
isVisible={true}
text={'没有更多啦'}
/>
} else {
return <LoadMoreIndicator
isVisible={isLoadingMore}
animating={isFetching}
/>
}
}}
/>
<LoadingIndicator
... ... @@ -302,7 +309,7 @@ export default class Home extends React.Component {
<SuperMan
fly={styles.fly}
avatar={user.avatar}
msgNumber={user.msgNumber}
msgCount={user.msgCount}
onSaveingTheWorld={this.props.onSaveingTheWorld}
/>
</View>
... ...
... ... @@ -3,6 +3,7 @@
import React from 'react';
import ReactNative from 'react-native';
import ImmutablePropTypes from 'react-immutable-proptypes';
import SlicedImage from '../../../common/components/SlicedImage';
const {
View,
... ... @@ -17,7 +18,7 @@ export default class SuperMan extends React.Component {
static propTypes = {
avatar: React.PropTypes.string,
msgNumber: React.PropTypes.number,
msgCount: React.PropTypes.string,
onSaveingTheWorld: React.PropTypes.func,
};
... ... @@ -27,11 +28,11 @@ export default class SuperMan extends React.Component {
}
renderMsgNumber() {
if (this.props.msgNumber > 0) {
renderMsgCount() {
if (parseInt(this.props.msgCount) !== 0) {
return (
<View style={styles.textContainer}>
<Text style={styles.text}>{this.props.msgNumber}</Text>
<Text style={styles.text}>{this.props.msgCount}</Text>
</View>
);
} else {
... ... @@ -47,9 +48,9 @@ export default class SuperMan extends React.Component {
this.props.onSaveingTheWorld && this.props.onSaveingTheWorld();
}}>
<View style={avtatStyle}>
<Image style={styles.avatar} source={{uri: this.props.avatar}} resizeMode={'cover'} defaultSource={require('../../images/home/superman.png')}/>
<SlicedImage style={styles.avatar} source={{uri: this.props.avatar}} resizeMode={'cover'} defaultSource={require('../../images/home/superman.png')}/>
</View>
{this.renderMsgNumber()}
{this.renderMsgCount()}
</TouchableOpacity>
</View>
);
... ... @@ -69,6 +70,7 @@ let styles = StyleSheet.create({
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: 'white',
shadowColor: 'darkgray',
shadowOpacity: 1,
shadowOffset: {width: 0, height: 0},
... ...
... ... @@ -238,7 +238,7 @@ export default class Section extends React.Component {
}
render() {
let {header, notice, list, isRefreshing, isLoadingMore, isFetching} = this.props;
let {header, notice, list, endReached, isRefreshing, isLoadingMore, isFetching} = this.props;
let dataSource = {
progressing: this.props.progressing.toArray(),
header: header.toArray(),
... ... @@ -262,11 +262,18 @@ export default class Section extends React.Component {
this.props.onEndReached && this.props.onEndReached(this.currentPage);
}
}}
renderFooter={()=>{
return <LoadMoreIndicator
isVisible={isLoadingMore}
animating={isFetching}
/>
renderFooter={() => {
if (endReached) {
return <LoadMoreIndicator
isVisible={true}
text={'没有更多啦'}
/>
} else {
return <LoadMoreIndicator
isVisible={isLoadingMore}
animating={isFetching}
/>
}
}}
/>
);
... ...
... ... @@ -10,6 +10,7 @@ export default keyMirror({
INCREASE_ERROR_COUNT: null,
RESET_ERROR_COUNT: null,
SET_UID: null,
SYNC_USER_REQUEST: null,
SYNC_USER_SUCCESS: null,
SYNC_USER_FAILURE: null,
... ...
... ... @@ -240,6 +240,7 @@ class HomeContainer extends React.Component {
onRefresh={this._onRefresh}
isFetching={recommendation.isFetching}
ptr={ptr}
endReached={recommendation.endReached}
isRefreshing={isFetching}
isLoadingMore={!ptr && recommendation.isFetching}
onEndReached={this._onEndReached}
... ...
... ... @@ -200,15 +200,17 @@ class SectionContainer extends React.Component {
progressing = Immutable.fromJS(progressing);
let {activeTab, new: newPost, hot: hotPost, header, notice, ptr, isFetching : bnsIsFetching} = this.props.section;
let isRefreshing, isLoadingMore, isFetching;
let isRefreshing, isLoadingMore, isFetching, endReached;
if (activeTab === 0) {
isRefreshing = bnsIsFetching;
isLoadingMore = !ptr && newPost.isFetching;
isFetching = newPost.isFetching;
endReached = newPost.endReached;
} else {
isRefreshing = bnsIsFetching;
isLoadingMore = !ptr && hotPost.isFetching;
isFetching = hotPost.isFetching;
endReached = hotPost.endReached;
}
let headerData = Immutable.fromJS([header]);
... ... @@ -234,6 +236,7 @@ class SectionContainer extends React.Component {
onRefresh={this._onRefresh}
isFetching={isFetching}
ptr={ptr}
endReached={endReached}
isRefreshing={isRefreshing}
isLoadingMore={isLoadingMore}
onEndReached={this._onEndReached}
... ... @@ -249,7 +252,7 @@ let navbarHeight = (Platform.OS === 'android') ? 50 : 64;
let styles = StyleSheet.create({
container: {
top: navbarHeight,
height: height - navbarHeight,
marginBottom: navbarHeight,
flex: 1,
},
... ...
... ... @@ -8,7 +8,7 @@
import {Actions} from 'react-native-router-flux';
import HomeService from '../../services/HomeService';
import timeago from 'timeago.js';
import timeago from '../../utils/timeago';
const {
... ... @@ -296,7 +296,7 @@ function parseRecommendation(json) {
let uid = authorInfo && authorInfo.uid ? authorInfo.uid : 0;
let name = authorInfo && authorInfo.nickName ? authorInfo.nickName : '';
let createTime = item.createTime;
let timeagoStr = timeago().format(createTime, 'zh_CN');
let timeagoStr = timeago(createTime);
let isLike = item.hasPraise === 'Y' ? true : false;
let title = item.postsTitle ? decodeURI(item.postsTitle) : '';
... ...
... ... @@ -8,7 +8,7 @@
import {Actions} from 'react-native-router-flux';
import SectionService from '../../services/SectionService';
import timeago from 'timeago.js';
import timeago from '../../utils/timeago';
const {
SECTION_HEADER_REQUEST,
... ... @@ -258,7 +258,7 @@ function parseNewPost(json) {
let uid = authorInfo && authorInfo.uid ? authorInfo.uid : 0;
let name = authorInfo && authorInfo.nickName ? authorInfo.nickName : '';
let createTime = item.createTime;
let timeagoStr = timeago().format(createTime, 'zh_CN');
let timeagoStr = timeago(createTime);
let isLike = item.hasPraise === 'Y' ? true : false;
let title = item.postsTitle ? decodeURI(item.postsTitle) : '';
... ...
... ... @@ -30,6 +30,8 @@ const {
GET_USER_INFO_SUCCESS,
GET_USER_INFO_FAILURE,
SET_UID,
} = require('../../constants/actionTypes').default;
export function postRequest() {
... ... @@ -237,7 +239,7 @@ export function syncUserFailure(error) {
export function syncUserWithSSOUid(uid) {
return (dispatch, getState) => {
let {app} = getState();
// dispatch(syncUserRequest()); //这一行会导致首页不停触发下拉刷新,不知道为什么????????????????
dispatch(syncUserRequest());
return new UserService().syncUser(uid, app.container)
.then(json => {
let profile = parseSyncUser(json);
... ... @@ -253,24 +255,36 @@ export function syncUserWithoutSSOUid(shouldDisplayLoginView) {
return (dispatch, getState) => {
ReactNative.NativeModules.YH_CommunityHelper.uid()
.then(uid => {
return dispatch(syncUserWithContainerUid(uid));
return dispatch(syncUserWithSSOUid(uid));
})
.catch(error => {
if (shouldDisplayLoginView) {
ReactNative.NativeModules.YH_CommunityHelper.login()
.then(uid => {
return dispatch(syncUserWithContainerUid(uid));
return dispatch(syncUserWithSSOUid(uid));
});
}
});
};
}
export function setUid(uid) {
return {
type: SET_UID,
payload: uid,
};
}
function parseSyncUser(json) {
let msgNumber = json.msgcount ? json.msgcount : 0;
let msgCount = json.msgcount ? json.msgcount : 0;
if (msgCount > 99) {
msgCount = '99+';
} else {
msgCount = msgCount + '';
}
let profile = {
uid: json.ssoUid ? parseInt(json.ssoUid) : 0,
avatar: json.headIco ? json.headIco : '',
avatar: json.headIcon ? json.headIcon : '',
bgImage: '',
nickName: json.nickName ? json.nickName : '',
realName: json.realName ? json.realName : '',
... ... @@ -280,7 +294,7 @@ function parseSyncUser(json) {
birthday: json.birthday ? json.birthday : '',
height: json.height ? json.height : 0,
weight: json.weight ? json.weight : 0,
msgNumber: json.msgcount ? json.msgcount : 0,
msgCount: msgCount,
}
return profile;
... ...
... ... @@ -19,7 +19,7 @@ let InitialState = Record({
birthday: '',
height: 0,
weight: 0,
msgNumber: 0,
msgCount: '',
})),
posts: new (Record({
jsonData: List(),
... ...
... ... @@ -28,6 +28,8 @@ const {
GET_USER_INFO_SUCCESS,
GET_USER_INFO_FAILURE,
SET_UID,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
... ... @@ -81,10 +83,9 @@ export default function user(state = initialState, action) {
}
case SYNC_USER_SUCCESS: {
let {uid, avatar, bgImage, nickName, realName, gender, sign, age, birthday, height, weight, msgNumber} = action.payload;
let {avatar, bgImage, nickName, realName, gender, sign, age, birthday, height, weight, msgCount} = action.payload;
let nextState = state.setIn(['profile', 'isFetching'], false)
.setIn(['profile', 'error'], null)
.setIn(['profile', 'uid'], uid)
.setIn(['profile', 'avatar'], avatar)
.setIn(['profile', 'bgImage'], bgImage)
.setIn(['profile', 'nickName'], nickName)
... ... @@ -95,7 +96,7 @@ export default function user(state = initialState, action) {
.setIn(['profile', 'birthday'], birthday)
.setIn(['profile', 'height'], height)
.setIn(['profile', 'weight'], weight)
.setIn(['profile', 'msgNumber'], msgNumber);
.setIn(['profile', 'msgCount'], msgCount);
return nextState;
}
... ... @@ -105,6 +106,8 @@ export default function user(state = initialState, action) {
return nextState;
}
case SET_UID:
return state.setIn(['profile', 'uid'], action.payload);
}
return state;
... ...
'use strict';
import TA from 'timeago.js';
import moment from 'moment';
export default function timeago(timestamp) {
let timeagoStr = TA().format(timestamp, 'zh_CN');
let isNSecondsAgo = timeagoStr.indexOf('秒');
if (timeagoStr === '刚刚' || isNSecondsAgo !== -1) {
return '1分钟前';
}
if (timeagoStr === '1天前') {
return '昨天';
}
let isNDaysAgo = timeagoStr.indexOf('天');
if (isNDaysAgo !== -1) {
return moment(timestamp, 'x').format('YYYY-M-D');
}
return timeagoStr;
}
... ...