diff --git a/android/app/src/main/assets/fonts/EvilIcons.ttf b/android/app/src/main/assets/fonts/EvilIcons.ttf index 6868f7b..b270f98 100644 Binary files a/android/app/src/main/assets/fonts/EvilIcons.ttf and b/android/app/src/main/assets/fonts/EvilIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/Feather.ttf b/android/app/src/main/assets/fonts/Feather.ttf index fc963df..244854c 100755 Binary files a/android/app/src/main/assets/fonts/Feather.ttf and b/android/app/src/main/assets/fonts/Feather.ttf differ diff --git a/android/app/src/main/assets/fonts/Ionicons.ttf b/android/app/src/main/assets/fonts/Ionicons.ttf index 67bd842..307ad88 100644 Binary files a/android/app/src/main/assets/fonts/Ionicons.ttf and b/android/app/src/main/assets/fonts/Ionicons.ttf differ diff --git a/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf b/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf index 3219fca..c9a3a30 100644 Binary files a/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf and b/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/Octicons.ttf b/android/app/src/main/assets/fonts/Octicons.ttf index ceac75d..09e2b2d 100644 Binary files a/android/app/src/main/assets/fonts/Octicons.ttf and b/android/app/src/main/assets/fonts/Octicons.ttf differ diff --git a/src/component/diary/diaryBrief.js b/src/component/diary/diaryBrief.js index 510229e..87da2dc 100644 --- a/src/component/diary/diaryBrief.js +++ b/src/component/diary/diaryBrief.js @@ -19,15 +19,21 @@ export default class DiaryBrief extends Component { return ( - + {(user && user.iconUrl) + ? : null} + - - {user.name} - - - 《{diary.notebook_subject}》 - + {(user && user.name) + ? ( + {user.name} + + ) : null} + {(user && user.name) + ? ( + 《{diary.notebook_subject}》 + + ) : null} {moment(diary.created).format('H:mm')} @@ -99,7 +105,7 @@ const localStyle = StyleSheet.create({ alignItems: "center", width: '100%', height: 30, - marginTop: 5, + marginTop: 10, justifyContent: 'space-between' } }); diff --git a/src/component/notebook/notebook.js b/src/component/notebook/notebook.js index 2d246a3..09785c9 100644 --- a/src/component/notebook/notebook.js +++ b/src/component/notebook/notebook.js @@ -17,46 +17,38 @@ export default class Notebook extends Component { let notebook = this.props.notebook; return ( - {}}> + + + + {this.getLabel(notebook.isPublic)} + - - - - {this.getLabel(notebook.isPublic)} - - - - - {notebook.subject} - - - {notebook.isExpired ? '已过期' : '未过期'} - - - {notebook.created}至{notebook.expired} - + + + {notebook.subject} - + + {notebook.isExpired ? '已过期' : '未过期'} + + + {notebook.created}至{notebook.expired} + - + ); } } const localStyle = StyleSheet.create({ - container: { - marginBottom: 15 - }, androidBox: { width: 140, elevation: 1, backgroundColor: '#fff', alignItems: 'center', - margin: 3 + margin: 3, + marginBottom: 15 }, iosBox: { width: 140, @@ -65,7 +57,8 @@ const localStyle = StyleSheet.create({ shadowOffset: {width: 0, height: 0}, backgroundColor: '#fff', alignItems: 'center', - margin: 3 + margin: 3, + marginBottom: 15 }, privateLabel: { position: 'absolute', diff --git a/src/component/notebook/notebookDiaryList.js b/src/component/notebook/notebookDiaryList.js new file mode 100644 index 0000000..3967edf --- /dev/null +++ b/src/component/notebook/notebookDiaryList.js @@ -0,0 +1,216 @@ +import React, {Component} from 'react'; +import { + View, + StyleSheet, + Text, + SectionList, + InteractionManager, + TouchableOpacity, + ActivityIndicator +} from 'react-native'; +import moment from 'moment' + +import Api from '../../util/api'; +import Color from '../../style/color'; +import Touchable from '../touchable'; + +import DiaryBrief from '../diary/diaryBrief'; +import NotebookDiaryData from '../../dataLoader/notebookDiaryData'; + + +export default class NotebookDiaryList extends Component { + + constructor(props) { + super(props); + + this.dataSource = new NotebookDiaryData(); + this.notebook = props.notebook; + + this.state = { + diaries: [], + hasMore: false, + + refreshing: false, + refreshFailed: false + }; + } + + componentDidMount(){ + InteractionManager.runAfterInteractions(() => { + this.refresh(); + }); + } + + formatDiaries(diaries) { + let today = moment().format('YYYY年M月D日'); + let reducedDiaries = diaries.reduce((maplist, item) => { + let [year, month, day] = + item.created.substr(0, 10).split('-') + .map(it => Number(it)); + + let date = `${year}年${month}月${day}日`; + if(date === today) { + date = '今天'; + } + + if(!maplist[date]) { + maplist[date] = []; + } + + maplist[date].push(item); + + return maplist; + + }, {}); + console.log('reduce result:', reducedDiaries); + + let result = []; + for(let key in reducedDiaries) { + result.push({ + title: key, + data: reducedDiaries[key] + }); + } + + console.log('format result:', result); + return result; + } + + refresh(loadMore = false) { + this.setState({refreshing: true}); + this.dataSource.refresh(this.notebook.id, loadMore) + .then(result => { + console.log('get notebook diaries:', result); + + if(!result) { + throw { + message: 'refresh no result' + } + + } else { + let diaries = this.formatDiaries(result.list); + this.setState({ + diaries, + hasMore: result.more, + refreshFailed: false + }); + } + + }).catch(e => { + this.setState({ + diaries: [], + hasMore: false, + refreshFailed: true + }); + + }).done(() => { + this.setState({ + refreshing: false + }); + }); + } + + loadMore() { + if (this.state.refreshing) { + return; + } + + this.refresh(true); + } + + render() { + return this.notebook ? ( + + item.id} + + sections={this.state.diaries} + + renderItem={(rowData) => { + return ( {}}> + + ); + }} + + renderSectionHeader={(info) => { + return ( + {info.section.title} + ); + }} + + ListFooterComponent={this.renderFooter.bind(this)} + + automaticallyAdjustContentInsets={true} + + ItemSeparatorComponent={(sectionID, rowID, adjacentRowHighlighted) => + } + + SectionSeparatorComponent={() => } + + onEndReached={this.state.hasMore ? this.loadMore.bind(this) : null} + /> + + + ) : null; + } + + renderFooter() { + if (this.state.refreshing || this.state.diaries.length === 0) { + return null; + } + + if (this.state.refreshFailed) { + return ( + + {this.loadMore();}}> + 加载失败,请点击重试 + + + ); + } + + if (!this.state.hasMore) { + return ( + + —— THE END —— + + ); + } + + return ( + + + + ); + } +} + +const localStyle = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: 'white' + }, + sectionHeader: { + backgroundColor: '#F9F9F9', + paddingHorizontal: 15, + paddingVertical: 8, + color: Color.text + }, + itemSeparator: { + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: Color.line + }, + sectionSeparator: { + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: Color.line + }, + footer: { + height: 60, + justifyContent: 'center', + alignItems: 'center', + paddingBottom: 15 + } +}); \ No newline at end of file diff --git a/src/component/notebook/notebookList.js b/src/component/notebook/notebookList.js index 6e5ea0d..a714392 100644 --- a/src/component/notebook/notebookList.js +++ b/src/component/notebook/notebookList.js @@ -5,7 +5,8 @@ import { Text, FlatList, StyleSheet, - RefreshControl + RefreshControl, + TouchableOpacity } from 'react-native'; import Api from '../../util/api'; @@ -72,11 +73,14 @@ export default class NotebookList extends Component { } _renderItem(notebook) { - return notebook ? ( - {}} /> + this.props.onNotebookPress(notebook)}> + + + + ) : null - } render() { diff --git a/src/dataLoader/followListData.js b/src/dataLoader/followDiaryData.js similarity index 94% rename from src/dataLoader/followListData.js rename to src/dataLoader/followDiaryData.js index df5accd..78de8dd 100644 --- a/src/dataLoader/followListData.js +++ b/src/dataLoader/followDiaryData.js @@ -3,7 +3,7 @@ import Api from '../util/api' const PAGE_SIZE = 21; -export default class FollowListData { +export default class FollowDiaryData { list: []; last_id: 0; diff --git a/src/dataLoader/followedByUserData.js b/src/dataLoader/followedByUserData.js index 6966f77..c399d71 100644 --- a/src/dataLoader/followedByUserData.js +++ b/src/dataLoader/followedByUserData.js @@ -1,7 +1,7 @@ import Api from '../util/api' -const PAGE_SIZE = 20; +const PAGE_SIZE = 21; export default class FollowedByUserData { diff --git a/src/dataLoader/followingUserData.js b/src/dataLoader/followingUserData.js index fd3fe0d..456fef8 100644 --- a/src/dataLoader/followingUserData.js +++ b/src/dataLoader/followingUserData.js @@ -1,7 +1,7 @@ import Api from '../util/api' -const PAGE_SIZE = 20; +const PAGE_SIZE = 21; export default class FollowingUserData { diff --git a/src/dataLoader/homeListData.js b/src/dataLoader/homeDiaryData.js similarity index 94% rename from src/dataLoader/homeListData.js rename to src/dataLoader/homeDiaryData.js index 37da844..e65f6e2 100644 --- a/src/dataLoader/homeListData.js +++ b/src/dataLoader/homeDiaryData.js @@ -3,7 +3,7 @@ import Api from '../util/api' const PAGE_SIZE = 21; -export default class HomeListData { +export default class HomeDiaryData { list: []; last_id: 0; diff --git a/src/dataLoader/notebookDiaryData.js b/src/dataLoader/notebookDiaryData.js new file mode 100644 index 0000000..c5ce5dc --- /dev/null +++ b/src/dataLoader/notebookDiaryData.js @@ -0,0 +1,30 @@ +import Api from '../util/api' + + +const PAGE_SIZE = 21; + +export default class NotebookDiaryData { + + page: 1; + list: []; + + async refresh(notebookId, loadMore = false) { + let page = !loadMore ? 1 : this.page + 1; + let data = await Api.getNotebookDiaries(notebookId, page, PAGE_SIZE); + let more = data.items.length === PAGE_SIZE; + + if(!loadMore) { + this.page = page; + this.list = data.items.slice(0, PAGE_SIZE - 1); + + } else if(data.items.length > 0) { + this.page = page; + this.list = this.list.concat(data.items.slice(0, PAGE_SIZE - 1)); + } + + return { + list: this.list, + more + }; + } +} \ No newline at end of file diff --git a/src/page/FollowPage.js b/src/page/FollowPage.js index 01378a4..71cb542 100644 --- a/src/page/FollowPage.js +++ b/src/page/FollowPage.js @@ -6,7 +6,7 @@ import Api from '../util/api' import {Icon} from '../style/icon' import DiaryList from '../component/diary/diaryList' -import FollowListData from '../dataLoader/followListData'; +import FollowListData from '../dataLoader/followDiaryData'; export default class FollowPage extends Component { diff --git a/src/page/HomePage.js b/src/page/HomePage.js index d053394..edca37a 100644 --- a/src/page/HomePage.js +++ b/src/page/HomePage.js @@ -5,7 +5,7 @@ import {Navigation} from 'react-native-navigation'; import Api from '../util/api'; import DiaryList from '../component/diary/diaryList' -import HomeListData from '../dataLoader/homeListData'; +import HomeListData from '../dataLoader/homeDiaryData'; export default class HomePage extends Component { diff --git a/src/page/NotebookDetailPage.js b/src/page/NotebookDetailPage.js new file mode 100644 index 0000000..e7d25f8 --- /dev/null +++ b/src/page/NotebookDetailPage.js @@ -0,0 +1,21 @@ +import React, {Component} from 'react'; +import {StyleSheet, Text, View, ScrollView} from 'react-native'; + +import Color from '../style/color'; +import NotebookDiaryList from '../component/notebook/notebookDiaryList'; + + +export default class NotebookDetailPage extends Component { + + render() { + return ( + + + + ); + } +} + +const localStyle = StyleSheet.create({ + +}); diff --git a/src/page/UserPage.js b/src/page/UserPage.js index 61a9d42..b0f6644 100644 --- a/src/page/UserPage.js +++ b/src/page/UserPage.js @@ -6,6 +6,7 @@ import { TabBar, SceneMap } from 'react-native-tab-view'; +import {Navigation} from 'react-native-navigation'; import Api from '../util/api'; import Color from '../style/color'; @@ -27,6 +28,18 @@ export default class UserPage extends Component { }; } + _onNotebookPress(notebook) { + Navigation.push(this.props.componentId, { + component: { + name: 'NotebookDetail', + passProps: { + notebook: notebook + } + } + }); + + } + _renderLabel = props => ({route}) => { let routes = props.navigationState.routes; let index = props.navigationState.index; @@ -58,7 +71,7 @@ export default class UserPage extends Component { userInfo: () => user info !, diary: () => diary !, notebook: () => }); diff --git a/src/page/_list.js b/src/page/_list.js index 254488e..3172c7a 100644 --- a/src/page/_list.js +++ b/src/page/_list.js @@ -3,6 +3,7 @@ DiaryDetail: require("./DiaryDetailPage.js").default, Follow: require("./FollowPage.js").default, FollowUser: require("./FollowUserPage.js").default, Home: require("./HomePage.js").default, +NotebookDetail: require("./NotebookDetailPage.js").default, Notification: require("./NotificationPage.js").default, User: require("./UserPage.js").default, Write: require("./WritePage.js").default diff --git a/src/util/api.js b/src/util/api.js index 34fdb9e..9535430 100644 --- a/src/util/api.js +++ b/src/util/api.js @@ -73,11 +73,21 @@ async function getSelfNotebooks() { } async function getRelationUsers(page, page_size) { - return call('GET', `/relation?page=${page}&page_size=${page_size}`); + return call('GET', `/relation?page=${page}&page_size=${page_size}`); } async function getRelationReverseUsers(page, page_size) { - return call('GET', `/relation/reverse?page=${page}&page_size=${page_size}`); + return call('GET', `/relation/reverse?page=${page}&page_size=${page_size}`); +} + +async function getNotebookDiaries(id, page, page_size) { + return call('GET', '/notebooks/' + id + '/diaries?page=' + page + '&page_size=' + page_size, null, 30000) + .then((json) => { + json.page = Number(json.page); + json.page_size = Number(json.page_size); + + return json; + }); } @@ -170,6 +180,7 @@ export default { getTodayDiaries, getFollowDiaries, + getNotebookDiaries, getDiaryComments, getSelfNotebooks,