1. 关注页增加导航菜单按钮,调试页面跳转

2. 日记本列表组件
This commit is contained in:
xuwenyang 2019-05-16 00:20:21 +08:00
parent 2a75bd4e33
commit 7852b9e05a
8 changed files with 336 additions and 13 deletions

View file

@ -0,0 +1,108 @@
import React, {Component} from 'react';
import {View, StyleSheet, Text, Image, ImageBackground, TouchableOpacity} from 'react-native';
import Api from '../../util/api';
import Color from '../../style/color'
export default class Notebook extends Component {
getLabel(isPublic) {
return isPublic ? null : (
<Text style={localStyle.privateLabel}>私密</Text>
);
}
render() {
let notebook = this.props.notebook;
return (
<TouchableOpacity key={notebook.id} style={localStyle.container}
activeOpacity={0.7}
onPress={() => {}}>
<View style={Api.IS_ANDROID ? localStyle.androidBox : localStyle.iosBox}>
<ImageBackground key={notebook.id}
style={localStyle.cover} imageStyle={{resizeMode: 'cover'}}
source={{uri: notebook.coverUrl}}>
{this.getLabel(notebook.isPublic)}
</ImageBackground>
<View style={localStyle.banner}>
<View style={localStyle.subject}>
<Text allowFontScaling={false}>{notebook.subject}</Text>
</View>
<Text style={localStyle.desc} allowFontScaling={false}>
{notebook.isExpired ? '已过期' : '未过期'}
</Text>
<Text style={localStyle.desc} allowFontScaling={false}>
{notebook.created}{notebook.expired}
</Text>
</View>
</View>
</TouchableOpacity>
);
}
}
const localStyle = StyleSheet.create({
container: {
marginBottom: 15
},
androidBox: {
width: 140,
elevation: 1,
backgroundColor: '#fff',
alignItems: 'center',
margin: 3
},
iosBox: {
width: 140,
shadowColor: '#444',
shadowOpacity: 0.1,
shadowOffset: {width: 0, height: 0},
backgroundColor: '#fff',
alignItems: 'center',
margin: 3
},
privateLabel: {
position: 'absolute',
top: 0,
right: 7,
fontSize: 11,
padding: 3,
backgroundColor: 'red',
color: 'white',
opacity: 0.75
},
cover: {
width: 140,
height: 105,
flexDirection: 'row',
justifyContent: 'flex-end',
overflow: 'hidden'
},
banner: {
alignItems:'center',
width: 141,
borderColor: '#eee',
borderWidth: StyleSheet.hairlineWidth,
borderTopWidth: 0,
paddingBottom: 5
},
subject: {
alignItems: 'center',
justifyContent: 'center',
padding: 5,
height: 55,
textAlign: 'center',
fontWeight: 'bold',
color: Color.text
},
desc: {
fontSize: 10,
color: Color.inactiveText
}
});

View file

@ -0,0 +1,123 @@
import React, { Component } from 'react';
import {
InteractionManager,
View,
Text,
FlatList,
StyleSheet,
RefreshControl
} from 'react-native';
import Api from '../../util/api';
import Notebook from './notebook'
export default class NotebookList extends Component {
constructor(props) {
super(props);
this.itemsPerRow = 2;
this.state = {
notebooks: [],
refreshing: false
};
}
componentDidMount(){
InteractionManager.runAfterInteractions(() => {
this.refresh();
});
}
createGroup(items, itemsPerRow) {
let bucket = [];
let groups = [];
items.forEach(function (item) {
if(bucket.length === itemsPerRow) {
groups.push(bucket);
bucket = [item];
} else {
bucket.push(item);
}
});
if(bucket.length > 0) {
while(bucket.length < itemsPerRow) {
bucket.push(null);
}
groups.push(bucket);
}
return groups;
}
refresh() {
this.setState({refreshing: true});
Api.getSelfNotebooks()
.then(notebooks => {
console.log('get notebooks:', notebooks);
let groups = this.createGroup(notebooks, this.itemsPerRow);
this.setState({
notebooks: groups
});
}).done(() => {
this.setState({refreshing: false});
});
}
_renderItem(notebook) {
return notebook ? (
<Notebook key={notebook.id} notebook={notebook} onPress={() => {}} />
) : null
}
render() {
let hasData = this.state.notebooks && this.state.notebooks.length > 0;
return hasData ? (
<FlatList style={{marginTop: 15}}
data={this.state.notebooks}
keyExtractor={(item, index) => {
return item[0].id.toString()
}}
renderItem={({item}) => {
let row = item.map((notebook) => {
return this._renderItem(notebook);
});
return (
<View style={localStyle.row}>
{row}
</View>
);
}}
refreshing={this.state.refreshing}
onRefresh={this.refresh.bind(this)}
/>
) : null;
}
}
const localStyle = StyleSheet.create({
row: {
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: 'white'
},
item: {
marginBottom: 15
}
});

View file

@ -17,6 +17,7 @@ function config() {
name: 'Home',
options: {
topBar: {
// visible: false,
title: {
text: '首页'
}
@ -42,14 +43,7 @@ function config() {
stack: {
children: [{
component: {
name: 'Follow',
options: {
topBar: {
title: {
text: '关注'
}
}
}
name: 'Follow'
}
}],
options: {

View file

@ -3,6 +3,7 @@ import {StyleSheet, Text, View} from 'react-native';
import {Navigation} from 'react-native-navigation';
import Api from '../util/api'
import {Icon} from '../style/icon'
import DiaryList from '../component/diary/diaryList'
import FollowListData from '../dataLoader/followListData';
@ -12,11 +13,56 @@ export default class FollowPage extends Component {
constructor(props) {
super(props);
Navigation.events().bindComponent(this);
this.dataSource = new FollowListData();
}
static options(passProps) {
return {
topBar: {
title: {
text: '关注'
},
rightButtons: [{
id: 'followIcon',
icon: Icon.followIcon,
color: '#aaa' // android
}]
}
};
}
navigationButtonPressed({buttonId}) {
/*
Navigation.setRoot({
root: {
stack: {
children: [{
component: {
name: 'FollowUser'
}
}]
}
}
});
*/
Navigation.push(this.props.componentId, {
component: {
name: 'FollowUser',
options: {
bottomTabs: {
visible: false
}
}
}
});
}
_onDiaryPress(diary) {
console.log('componentId:', this.props.componentId, diary);
Navigation.push(this.props.componentId, {
component: {
name: 'DiaryDetail',
@ -25,7 +71,6 @@ export default class FollowPage extends Component {
}
}
});
}
renderHeader() {
@ -41,7 +86,7 @@ export default class FollowPage extends Component {
<View style={localStyle.wrap}>
<DiaryList ref={(r) => this.list = r}
dataSource={this.dataSource}
header={this.renderHeader.bind(this)}
/* header={this.renderHeader.bind(this)} */
onDiaryPress={this._onDiaryPress.bind(this)}
navigator={this.props.navigator}

View file

@ -0,0 +1,42 @@
import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';
export default class FollowPage extends Component {
constructor(props) {
super(props);
}
static options(passProps) {
return {
topBar: {
title: {
text: '关注用户'
}
}
};
}
render() {
return (
<View style={localStyle.container}>
<Text style={localStyle.welcome}>Follow User Page !</Text>
</View>
);
}
}
const localStyle = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
}
});

View file

@ -10,6 +10,8 @@ import {
import Api from '../util/api';
import Color from '../style/color';
import NotebookList from '../component/notebook/notebookList'
export default class UserPage extends Component {
@ -55,7 +57,10 @@ export default class UserPage extends Component {
_renderScene = SceneMap({
userInfo: () => <View style={localStyle.container}><Text style={localStyle.welcome}>user info !</Text></View>,
diary: () => <View style={localStyle.container}><Text style={localStyle.welcome}>diary !</Text></View>,
notebook: () => <View style={localStyle.container}><Text style={localStyle.welcome}>notebook !</Text></View>
notebook: () => <NotebookList
navigator={this.props.navigator}
/>
});
render() {

View file

@ -1,6 +1,7 @@
export default {
DiaryDetail: require("./DiaryDetailPage.js").default,
Follow: require("./FollowPage.js").default,
FollowUser: require("./FollowUserPage.js").default,
Home: require("./HomePage.js").default,
Notification: require("./NotificationPage.js").default,
User: require("./UserPage.js").default,

View file

@ -68,6 +68,10 @@ async function getDiaryComments(diaryId) {
return call('GET', '/diaries/' + diaryId + '/comments')
}
async function getSelfNotebooks() {
return call('GET', '/notebooks/my')
}
async function call(method, api, body, _timeout = 10000) {
let token = await TokenManager.getUserToken();
@ -157,5 +161,6 @@ export default {
login,
getTodayDiaries,
getFollowDiaries,
getDiaryComments
getDiaryComments,
getSelfNotebooks
}