1. 话题

This commit is contained in:
xuwenyang 2019-06-04 19:18:56 +08:00
parent 5e7754e294
commit 703da75c5f
7 changed files with 244 additions and 4 deletions

View file

@ -112,6 +112,10 @@ export default class DiaryList extends Component {
return; return;
} }
if(this.props.refreshHeader) {
this.props.refreshHeader();
}
this.setState({refreshing: true, refreshFailed: false}); this.setState({refreshing: true, refreshFailed: false});
this.dataSource.refresh() this.dataSource.refresh()
.then(result => { .then(result => {
@ -219,6 +223,8 @@ export default class DiaryList extends Component {
ItemSeparatorComponent={({highlighted}) => <Divider style={{backgroundColor: '#eee'}}/>} ItemSeparatorComponent={({highlighted}) => <Divider style={{backgroundColor: '#eee'}}/>}
ListHeaderComponent={this.props.listHeader}
ListFooterComponent={() => { ListFooterComponent={() => {
if (this.state.refreshing || this.state.loadingMore || this.state.diaries.length == 0) { if (this.state.refreshing || this.state.loadingMore || this.state.diaries.length == 0) {
return null; return null;

View file

@ -0,0 +1,30 @@
import Api from '../util/api'
const PAGE_SIZE = 21;
export default class TopicDiaryData {
list: [];
last_id: 0;
async refresh(loadMore = false) {
let lastId = !loadMore ? 0 : this.last_id;
let data = await Api.getTodayTopicDiaries(0, PAGE_SIZE, lastId);
let more = data.diaries.length === PAGE_SIZE;
if(!loadMore) {
this.list = data.diaries.slice(0, PAGE_SIZE - 1);
} else if(data.diaries.length > 0) {
this.list = this.list.concat(data.diaries.slice(0, PAGE_SIZE - 1));
}
this.last_id = more ? data.diaries[PAGE_SIZE - 1].id : 0;
return {
list: this.list,
more
};
}
}

View file

@ -1,7 +1,8 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native'; import {StyleSheet, Text, View, TouchableOpacity, ImageBackground} from 'react-native';
import {Navigation} from 'react-native-navigation'; import {Navigation} from 'react-native-navigation';
import Color from '../style/color'
import Api from '../util/api'; import Api from '../util/api';
import DiaryList from '../component/diary/diaryList' import DiaryList from '../component/diary/diaryList'
@ -13,6 +14,41 @@ export default class HomePage extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.dataSource = new HomeDiaryData(); this.dataSource = new HomeDiaryData();
this.state = {
topic: null
}
}
refreshTopic() {
Api.getTodayTopic()
.then(topic => {
if(topic) {
this.setState({topic});
}
})
.done();
}
openTopicPage() {
Navigation.push(this.props.componentId, {
component: {
name: 'Topic',
options: {
bottomTabs: {
visible: false,
// hide bottom tab for android
drawBehind: true,
animate: true
}
},
passProps: {
topic: this.state.topic,
title: '话题:' + this.state.topic.title
}
}
});
} }
render() { render() {
@ -20,17 +56,65 @@ export default class HomePage extends Component {
<View style={localStyle.wrap}> <View style={localStyle.wrap}>
<DiaryList ref={(r) => this.list = r} <DiaryList ref={(r) => this.list = r}
dataSource={this.dataSource} dataSource={this.dataSource}
listHeader={this.renderHeader.bind(this)}
refreshHeader={this.refreshTopic.bind(this)}
{...this.props} {...this.props}
></DiaryList> ></DiaryList>
</View> </View>
); );
} }
renderHeader() {
return this.state.topic ? (
<View style={localStyle.topic}>
<TouchableOpacity onPress={this.openTopicPage.bind(this)} activeOpacity={0.7}>
<ImageBackground
style={localStyle.topicBox} imageStyle={{borderRadius: 8}}
source={{uri: this.state.topic.imageUrl}}>
<Text style={localStyle.topicTitle} allowFontScaling={false}># {this.state.topic.title}</Text>
<Text style={localStyle.topicIntro} allowFontScaling={false}>{this.state.topic.intro}</Text>
</ImageBackground>
</TouchableOpacity>
</View>
) : null;
}
} }
const localStyle = StyleSheet.create({ const localStyle = StyleSheet.create({
wrap: { wrap: {
flex: 1, flex: 1,
backgroundColor: '#fff' backgroundColor: '#fff'
},
topic: {
paddingTop: 0
},
topicBox: {
flex: 1,
height: 240,
marginTop: 15,
marginBottom: 15,
marginHorizontal: 15,
backgroundColor: Color.spaceBackground,
borderRadius: 8
},
topicTitle: {
fontSize: 24,
color: '#FFF',
paddingHorizontal: 20,
paddingTop: 15,
paddingBottom: 10,
textShadowColor: '#000',
textShadowOffset: { width: 1, height: 1 },
textShadowRadius: 2,
shadowOpacity: 0.2
},
topicIntro: {
fontSize: 16,
color: '#FFF',
paddingHorizontal: 22,
textShadowColor: '#000',
textShadowOffset: { width: 1, height: 1 },
textShadowRadius: 2,
shadowOpacity: 0.5
} }
}); });

84
src/page/TopicPage.js Normal file
View file

@ -0,0 +1,84 @@
import React, {Component} from 'react';
import {StyleSheet, Text, View, DeviceEventEmitter} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {Icon} from '../style/icon'
import Event from '../util/event'
import DiaryList from '../component/diary/diaryList'
import TopicDiaryData from '../dataLoader/TopicDiaryData';
export default class TopicPage extends Component {
constructor(props) {
super(props);
Navigation.events().bindComponent(this);
this.dataSource = new TopicDiaryData();
}
static options(passProps) {
return {
topBar: {
title: {
text: passProps.title
},
rightButtons: [{
id: 'write',
icon: Icon.navButtonWrite,
color: '#aaa' // android
}]
}
};
}
navigationButtonPressed({buttonId}) {
Navigation.push(this.props.componentId, {
component: {
name: 'Write',
options: {
bottomTabs: {
visible: false,
// hide bottom tab for android
drawBehind: true,
animate: true
}
},
passProps: {
topic: this.props.topic
}
}
});
}
componentDidMount() {
this.diaryListener = DeviceEventEmitter.addListener(Event.updateDiarys, (param) => {
this.diaryList.refresh();
});
}
componentWillUnmount() {
this.diaryListener.remove();
}
render() {
return (
<View style={localStyle.wrap}>
<DiaryList ref={(r) => this.diaryList = r}
dataSource={this.dataSource}
{...this.props}
></DiaryList>
</View>
);
}
}
const localStyle = StyleSheet.create({
wrap: {
flex: 1,
backgroundColor: '#fff'
}
});

View file

@ -36,6 +36,8 @@ export default class WritePage extends Component {
Navigation.events().bindComponent(this); Navigation.events().bindComponent(this);
let diary = this.diary = props.diary; let diary = this.diary = props.diary;
let topic = this.topic = props.topic;
this.state = { this.state = {
notebooks: [], notebooks: [],
@ -73,7 +75,7 @@ export default class WritePage extends Component {
navigationButtonPressed({buttonId}) { navigationButtonPressed({buttonId}) {
if(buttonId == 'cancel') { if(buttonId == 'cancel') {
if(this.diary) { if(this.diary || this.topic) {
Navigation.pop(this.props.componentId); Navigation.pop(this.props.componentId);
} else { } else {
@ -250,7 +252,7 @@ export default class WritePage extends Component {
Msg.showMsg('日记保存完成'); Msg.showMsg('日记保存完成');
DeviceEventEmitter.emit(Event.updateDiarys); DeviceEventEmitter.emit(Event.updateDiarys);
if(this.diary) { if(this.diary || this.topic) {
Navigation.pop(this.props.componentId); Navigation.pop(this.props.componentId);
} else { } else {
@ -313,6 +315,7 @@ export default class WritePage extends Component {
<View style={{flex: 1}} /> <View style={{flex: 1}} />
{this.renderTopicButton()}
{this.renderPhotoButton()} {this.renderPhotoButton()}
</View> </View>
@ -327,6 +330,20 @@ export default class WritePage extends Component {
); );
} }
renderTopicButton() {
if(!this.topic) {
return null;
}
return (
<TouchableOpacity>
<Text style={{color: Color.light, fontSize: 15, paddingRight: 15}}>
# {this.topic.title}
</Text>
</TouchableOpacity>
)
}
renderPhotoButton() { renderPhotoButton() {
if(this.diary) { if(this.diary) {
return null; return null;

View file

@ -13,6 +13,7 @@ Notification: require("./NotificationPage.js").default,
Password: require("./PasswordPage.js").default, Password: require("./PasswordPage.js").default,
Photo: require("./PhotoPage.js").default, Photo: require("./PhotoPage.js").default,
Setting: require("./SettingPage.js").default, Setting: require("./SettingPage.js").default,
Topic: require("./TopicPage.js").default,
UserInfoEdit: require("./UserInfoEditPage.js").default, UserInfoEdit: require("./UserInfoEditPage.js").default,
UserIntroEdit: require("./UserIntroEditPage.js").default, UserIntroEdit: require("./UserIntroEditPage.js").default,
UserNameEdit: require("./UserNameEditPage.js").default, UserNameEdit: require("./UserNameEditPage.js").default,

View file

@ -85,6 +85,16 @@ async function getTodayDiaries(page = 1, page_size = 20, first_id = '') {
}); });
} }
async function getTodayTopicDiaries(page = 1, page_size = 20, first_id = '') {
return call('GET', `/topic/diaries?page=${page}&page_size=${page_size}&first_id=${first_id}`)
.then((json) => {
json.page = Number(json.page);
json.page_size = Number(json.page_size);
return json;
});
}
async function getFollowDiaries(page = 1, page_size = 20, first_id = '') { async function getFollowDiaries(page = 1, page_size = 20, first_id = '') {
return call('GET', '/diaries/follow?page=' + page + '&page_size=' + page_size + `&first_id=${first_id}`) return call('GET', '/diaries/follow?page=' + page + '&page_size=' + page_size + `&first_id=${first_id}`)
.then((json) => { .then((json) => {
@ -109,6 +119,11 @@ async function getUserTodayDiaries(userId) {
return call('GET', '/users/' + userId + '/diaries/'); return call('GET', '/users/' + userId + '/diaries/');
} }
async function getTodayTopic() {
return call('GET', '/topic/');
}
async function getDiaryComments(diaryId) { async function getDiaryComments(diaryId) {
return call('GET', '/diaries/' + diaryId + '/comments'); return call('GET', '/diaries/' + diaryId + '/comments');
} }
@ -389,10 +404,13 @@ export default {
updateUserInfo, updateUserInfo,
getTodayDiaries, getTodayDiaries,
getTodayTopicDiaries,
getFollowDiaries, getFollowDiaries,
getNotebookDiaries, getNotebookDiaries,
getUserTodayDiaries, getUserTodayDiaries,
getTodayTopic,
getDiary, getDiary,
deleteDiary, deleteDiary,