Skip to content

Commit 8ae3afe

Browse files
committed
list and detail page handle.
1 parent e4ce077 commit 8ae3afe

26 files changed

+772
-251
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"react-native-html-converter": "^1.0.4",
4545
"react-native-parallax-scroll-view": "^0.19.0",
4646
"react-native-scrollable-tab-view": "^0.5.1",
47+
"react-native-simple-markdown": "^1.0.54",
4748
"react-native-vector-icons": "^2.0.3",
4849
"react-redux": "^4.4.5",
4950
"react-timer-mixin": "^0.13.3",

source/common/index.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,29 @@ import _ from 'lodash';
77
import Config from '../config';
88
import entities from 'entities';
99

10+
const imageSourcePath = Config.assetDomain + "/public/img/metarial/";
11+
const bloggerAvatarPath = "https://pic.cnblogs.com/face/";
12+
const questionAvatarPath = "http://pic.cnblogs.com/avatar/";
13+
1014
export function getBloggerName(authorUri) {
1115
authorUri = _.trimEnd(authorUri, '\/');
1216
return authorUri.slice(authorUri.lastIndexOf("\/") + 1);
1317
}
1418

15-
const seedColors = ['#ec898a', '#69bb97', '#55b9ce', '#cc936e', '#65be8d', '#6bb6cb', '#ae9cc3'];
16-
export function getRandomColor(){
17-
return seedColors[_.random(0, seedColors.length -1)];
18-
}
19-
2019
export function getBloggerAvatar(avatarUri){
21-
if (avatarUri != "https://pic.cnblogs.com/face/") {
20+
if (avatarUri != bloggerAvatarPath) {
2221
return avatarUri;
2322
}
2423
return Config.appInfo.avatar;
2524
}
2625

26+
export function getQuestionAuthorAvatar(avatarName){
27+
if(avatarName && avatarName !== "sample_face.gif"){
28+
return questionAvatarPath + avatarName;
29+
}
30+
return Config.appInfo.avatar;
31+
}
32+
2733
export function getBloggerHdpiAvatar(avatarUri){
2834
if (avatarUri && !_.endsWith(avatarUri, ".gif")) {
2935
avatarUri = avatarUri.replace(/face/, 'avatar');
@@ -59,11 +65,14 @@ export function decodeHTML(htmlStr) {
5965
return htmlStr;
6066
}
6167

62-
const imageSourcePath = Config.assetDomain + "/public/img/metarial/";
6368
export function getImageSource(key){
6469
let imageLen = 20;
6570
if (!key) {
6671
key = _.random(1, imageLen - 1);
6772
}
6873
return imageSourcePath + key + ".jpg?v=1.1";
6974
}
75+
76+
export function splitStrToArray(str, char = ',', count = 3){
77+
return _.split(str, char, count);
78+
}

source/component/header/post.js

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import {
33
View,
44
Image,
55
Text,
6-
Dimensions,
76
ScrollView,
7+
StyleSheet,
88
TouchableOpacity
99
} from 'react-native';
1010

@@ -21,11 +21,9 @@ class PostRender extends Component {
2121

2222
constructor(props) {
2323
super(props);
24-
2524
this.state = {
2625
cover: null
2726
};
28-
2927
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
3028
}
3129

@@ -53,41 +51,41 @@ class PostRender extends Component {
5351

5452
renderParallaxBackground(postInfo){
5553
return (
56-
<View style={ CommonStyles.headerBackground } key="parallax-background">
54+
<View key="parallax-background">
5755
<Animatable.Image
5856
resizeMode="cover"
59-
style={ CommonStyles.headerBackgroundImage }
60-
source={{uri: this.state.cover }}
57+
style={ [ComponentStyles.header_img ] }
58+
source={ {uri: this.state.cover } }
6159
ref={(view)=>{this.parallaxBackground = view}} >
6260
</Animatable.Image>
63-
<View style={ CommonStyles.headerBackgroundMask }/>
61+
<View style={ [ ComponentStyles.header_backdrop ] }/>
6462
</View>
6563
)
6664
}
6765

6866
renderParallaxForeground(postInfo){
6967

70-
let postTitle = _.truncate(postInfo.title, { length : 50 });
68+
let postTitle = _.truncate(postInfo.Title, { length : 50 });
7169

7270
return (
7371
<Animatable.View
7472
key="parallax-foreground"
75-
ref={(view)=>{ this.parallaxForeground = view}}
76-
style={ ComponentStyles.headerContainer } >
77-
<Text style={ ComponentStyles.headerTitleText }>
73+
style = { [ CommonStyles.flexColumn, CommonStyles.flexItemsCenter, CommonStyles.p_a_3, styles.foreground ] }
74+
ref={(view)=>{ this.parallaxForeground = view}}>
75+
<Text style={ [ CommonStyles.text_white, CommonStyles.font_eg, CommonStyles.text_left ] }>
7876
{ postTitle }
7977
</Text>
8078

81-
<View style={ ComponentStyles.headerMetaContainer }>
82-
<View style={ ComponentStyles.headerMetaInfo }>
83-
<Image style={ ComponentStyles.metaAuthorAvatar }
84-
source={{ uri: postInfo.authorAvatar }}/>
85-
<Text style={ ComponentStyles.metaAuthorName }>
86-
{ postInfo.authorName }
79+
<View style={ [ ComponentStyles.pos_absolute, CommonStyles.flexRow, CommonStyles.flexItemsMiddle, CommonStyles.flexItemsBetween, CommonStyles.p_a_3, styles.header_meta ] }>
80+
<View style={ [ CommonStyles.flexRow, CommonStyles.flexItemsMiddle ] }>
81+
<Image style={ [ ComponentStyles.avatar_mini, CommonStyles.m_r_2 ] }
82+
source={{ uri: postInfo.Avatar }}/>
83+
<Text style={ [ CommonStyles.text_white, CommonStyles.font_sm ] }>
84+
{ postInfo.Author }
8785
</Text>
8886
</View>
89-
<Text style={ ComponentStyles.metaRight }>
90-
{ postInfo.published }
87+
<Text style={ [ CommonStyles.text_light ] }>
88+
{ postInfo.PostDate }
9189
</Text>
9290
</View>
9391
</Animatable.View>
@@ -98,8 +96,8 @@ class PostRender extends Component {
9896
return (
9997
<Navbar
10098
backgroundImage = { {uri: this.state.cover} }
101-
leftIconName = { postInfo.authorAvatar }
102-
title={ postInfo.authorName }/>
99+
leftIconName = { postInfo.Avatar }
100+
title={ postInfo.Author }/>
103101
);
104102
}
105103

@@ -111,8 +109,8 @@ class PostRender extends Component {
111109
<ParallaxScrollView
112110
headerBackgroundColor="#111"
113111
ref={(view)=>{this.parallaxView = view}}
114-
stickyHeaderHeight={ StyleConfig.navbarHeight }
115-
parallaxHeaderHeight={ StyleConfig.parallaxHeaderHeight }
112+
stickyHeaderHeight={ StyleConfig.navbar_height }
113+
parallaxHeaderHeight={ StyleConfig.header_height }
116114
renderScrollComponent={()=> this.renderParallaxScrollComponent()}
117115
renderBackground={() => this.renderParallaxBackground(post)}
118116
renderForeground={() => this.renderParallaxForeground(post)}
@@ -125,4 +123,15 @@ class PostRender extends Component {
125123
}
126124
}
127125

126+
export const styles = StyleSheet.create({
127+
foreground:{
128+
height: StyleConfig.header_height,
129+
paddingTop: StyleConfig.space_4
130+
},
131+
header_meta:{
132+
bottom:0,
133+
width: StyleConfig.width
134+
}
135+
});
136+
128137
export default PostRender;

source/component/htmlConvertor.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import _ from 'lodash';
1313
import HTMLView from 'react-native-html-converter';
1414
import PureRenderMixin from 'react-addons-pure-render-mixin';
1515
import { HtmlConvertorStyles, StyleConfig } from '../style';
16-
import { filterCodeSnippet, decodeHTML, formatNewsImgUri } from '../common';
16+
import { filterCodeSnippet, decodeHTML } from '../common';
1717
import ImageBox from './imageBox';
1818

1919
const {width, height} = Dimensions.get('window');
@@ -95,7 +95,7 @@ class HtmlRender extends Component {
9595
return undefined;
9696
}
9797

98-
let imageUri = formatNewsImgUri(node.attribs.src);
98+
let imageUri = node.attribs.src;
9999
let imageId = _.uniqueId('image_');
100100
return (
101101
<ImageBox

source/component/listview/blinkList.js

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import {
88
import { bindActionCreators } from 'redux';
99
import { connect } from 'react-redux';
1010
import PureRenderMixin from 'react-addons-pure-render-mixin';
11+
import * as PostAction from '../../action/post';
12+
import BlinkRow from './blinkRow';
1113
import Spinner from '../spinner';
1214
import { CommonStyles } from '../../style';
1315
import { postCategory } from '../../config';
@@ -17,41 +19,75 @@ const category = postCategory.blink;
1719
class BlinkList extends Component {
1820
constructor(props) {
1921
super(props);
20-
21-
}
22+
let dataSource = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
23+
this.state = {
24+
dataSource: dataSource.cloneWithRows(props.blinks||{}),
25+
};
2226

23-
componentWillReceiveProps(nextProps) {
24-
27+
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
2528
}
2629

27-
onListEndReached() {
28-
30+
componentWillReceiveProps(nextProps) {
31+
if (nextProps.blinks && nextProps.blinks.length && nextProps.blinks !== this.props.blinks) {
32+
this.setState({
33+
dataSource: this.state.dataSource.cloneWithRows(nextProps.blinks)
34+
});
35+
}
2936
}
3037

3138
renderListFooter() {
32-
39+
if (this.props.ui && this.props.ui.pagePending) {
40+
return (
41+
<View style={ [ CommonStyles.m_a_4 ] }>
42+
<Spinner/>
43+
</View>
44+
)
45+
}
46+
return null;
3347
}
3448

35-
onListRowClick(post){
36-
49+
onListRowPress(blink){
50+
this.props.router.toBlink({
51+
id: blink.id,
52+
category: category,
53+
blink
54+
});
3755
}
3856

39-
renderListRow(post) {
40-
57+
renderListRow(blink) {
58+
if(blink && blink.Id){
59+
return (
60+
<BlinkRow
61+
key={ blink.Id }
62+
blink={ blink }
63+
category={ category }
64+
onRowPress={ (e)=>this.onListRowPress(e) } />
65+
)
66+
}
4167
}
4268

43-
4469
render() {
4570
return (
46-
<Text>
47-
blink list
48-
</Text>
71+
<ListView
72+
ref = {(view)=> this.listView = view }
73+
removeClippedSubviews
74+
enableEmptySections = { true }
75+
onEndReachedThreshold={ 10 }
76+
initialListSize={ 10 }
77+
pageSize = { 10 }
78+
pagingEnabled={ false }
79+
scrollRenderAheadDistance={ 150 }
80+
dataSource={ this.state.dataSource }
81+
renderRow={ (e)=>this.renderListRow(e) }
82+
renderFooter={ (e)=>this.renderListFooter(e) }>
83+
</ListView>
4984
);
5085
}
5186
}
5287

5388
export default connect((state, props) => ({
54-
89+
blinks : state.post[category],
90+
ui: state.postListUI[category]
5591
}), dispatch => ({
56-
92+
postAction : bindActionCreators(PostAction, dispatch)
5793
}))(BlinkList);

source/component/listview/blinkRow.js

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
import moment from 'moment';
1010
import _ from 'lodash';
1111
import PureRenderMixin from 'react-addons-pure-render-mixin';
12+
import Icon from 'react-native-vector-icons/Ionicons';
1213
import { decodeHTML } from '../../common';
1314
import { CommonStyles, ComponentStyles, StyleConfig } from '../../style';
1415

@@ -19,19 +20,78 @@ class BlinkRow extends Component {
1920
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
2021
}
2122

22-
getPostInfo(){
23-
23+
getBlinkInfo(){
24+
let { blink } = this.props;
25+
let blinkInfo = {};
26+
if (blink && blink.Id) {
27+
blinkInfo.Id = blink.Id;
28+
blinkInfo.Content = blink.Content;
29+
blinkInfo.CommentCount = blink.CommentCount;
30+
blinkInfo.AuthorName = blink.UserDisplayName;
31+
blinkInfo.AuthorAvatar = blink.UserIconUrl;
32+
blinkInfo.DateAdded = moment(blink.DateAdded).startOf('minute').fromNow();
33+
}
34+
return blinkInfo;
2435
}
2536

26-
renderPostRowMetas(postInfo){
27-
37+
renderBlinkHeader(blinkInfo){
38+
return (
39+
<View style={ [ CommonStyles.flexRow, CommonStyles.flexItemsMiddle, CommonStyles.m_b_2 ] }>
40+
<Image ref={view => this.imgView=view}
41+
style={ [ ComponentStyles.avatar_mini, CommonStyles.m_r_2] }
42+
source={ {uri:blinkInfo.AuthorAvatar} }>
43+
</Image>
44+
<Text style={ [ CommonStyles.text_danger, CommonStyles.font_xs ] }>
45+
{ blinkInfo.AuthorName }
46+
</Text>
47+
</View>
48+
);
49+
}
50+
51+
renderBlinkContent(blinkInfo){
52+
return (
53+
<View style={ [ CommonStyles.m_b_2 ] }>
54+
<Text style={ [CommonStyles.text_gray, CommonStyles.font_sm, CommonStyles.line_height_sm ] }>
55+
{ blinkInfo.Content }
56+
</Text>
57+
</View>
58+
);
59+
}
60+
61+
renderBlinkMeta(blinkInfo){
62+
return (
63+
<View style={ [ CommonStyles.flexRow, CommonStyles.flexItemsBetween ] }>
64+
<Text style={ CommonStyles.text_gray }>
65+
{ blinkInfo.DateAdded }
66+
</Text>
67+
68+
<View style={[ CommonStyles.flexRow, CommonStyles.flexItemsMiddle]}>
69+
<Icon
70+
name={ "ios-chatbubbles-outline" }
71+
size= { StyleConfig.icon_size - 4 }
72+
color={ StyleConfig.color_primary } />
73+
<Text style={ [ CommonStyles.text_primary, CommonStyles.m_l_1 ] }>
74+
{ blinkInfo.CommentCount }
75+
</Text>
76+
</View>
77+
</View>
78+
);
2879
}
2980

3081
render() {
82+
let blinkInfo = this.getBlinkInfo();
3183
return (
32-
<Text>
33-
blink row
34-
</Text>
84+
<TouchableHighlight
85+
onPress={(e)=>{ this.props.onRowPress(blinkInfo) }}
86+
underlayColor={ StyleConfig.touchable_press_color }
87+
key={ blinkInfo.Id }>
88+
89+
<View style={ ComponentStyles.list }>
90+
{ this.renderBlinkHeader(blinkInfo) }
91+
{ this.renderBlinkContent(blinkInfo) }
92+
{ this.renderBlinkMeta(blinkInfo) }
93+
</View>
94+
</TouchableHighlight>
3595
)
3696
}
3797
}

0 commit comments

Comments
 (0)