From d862735d6fdb890881f0a72a01dd26904bf95c3c Mon Sep 17 00:00:00 2001 From: xuwenyang Date: Wed, 22 May 2019 01:27:37 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E5=86=99=E6=97=A5=E8=AE=B0=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E9=80=89=E6=8B=A9=E6=97=A5=E8=AE=B0=E6=9C=AC=E6=A8=A1?= =?UTF-8?q?=E6=80=81=E6=A1=86=202.=20=E5=85=B3=E6=B3=A8/=E8=A2=AB=E5=85=B3?= =?UTF-8?q?=E6=B3=A8=E7=94=A8=E6=88=B7=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/follow/followUserList.js | 42 +++++++- src/component/notebook/notebook.js | 2 +- src/component/notebook/notebookLine.js | 92 ++++++++++++++++++ src/page/FollowUserPage.js | 10 +- src/page/WritePage.js | 128 ++++++++++++++++++++++++- src/util/api.js | 20 +++- 6 files changed, 282 insertions(+), 12 deletions(-) create mode 100644 src/component/notebook/notebookLine.js diff --git a/src/component/follow/followUserList.js b/src/component/follow/followUserList.js index eeda3f6..b3e6594 100644 --- a/src/component/follow/followUserList.js +++ b/src/component/follow/followUserList.js @@ -1,5 +1,6 @@ import React, {Component} from 'react'; -import {StyleSheet, Text, View, InteractionManager, FlatList} from 'react-native'; +import {StyleSheet, Text, View, InteractionManager, FlatList, Alert} from 'react-native'; +import {Navigation} from 'react-native-navigation'; import Ionicons from 'react-native-vector-icons/Ionicons'; import Touchable from '../touchable'; @@ -35,6 +36,41 @@ export default class FollowUserList extends Component { }); } + _onItemPress(user) { + Navigation.push(this.props.componentId, { + component: { + name: 'User', + options: { + bottomTabs: { + visible: false, + + // hide bottom tab for android + drawBehind: true, + animate: true + } + }, + passProps: { + user: user + } + } + }); + } + + _onDeletePress(user) { + Alert.alert('提示', '确定删除关注?', [ + {text: '删除', style: 'destructive', onPress: () => { + this.props.onDeletePress(user.id) + .done(() => { + let filterUsers = this.state.users.filter((it) => it.id !== user.id); + this.setState({ + users: filterUsers + }); + }); + }}, + {text: '取消', onPress: () => {}} + ]); + } + refresh() { if (this.state.refreshing) { return; @@ -119,11 +155,11 @@ export default class FollowUserList extends Component { renderItem={({item}) => { return ( - {}}> + this._onItemPress(item)}> {item.name} - {}}> + this._onDeletePress(item)}> diff --git a/src/component/notebook/notebook.js b/src/component/notebook/notebook.js index 09785c9..49bef66 100644 --- a/src/component/notebook/notebook.js +++ b/src/component/notebook/notebook.js @@ -1,5 +1,5 @@ import React, {Component} from 'react'; -import {View, StyleSheet, Text, Image, ImageBackground, TouchableOpacity} from 'react-native'; +import {View, StyleSheet, Text, Image, ImageBackground} from 'react-native'; import Api from '../../util/api'; import Color from '../../style/color' diff --git a/src/component/notebook/notebookLine.js b/src/component/notebook/notebookLine.js new file mode 100644 index 0000000..3a4aa5d --- /dev/null +++ b/src/component/notebook/notebookLine.js @@ -0,0 +1,92 @@ +import React, { Component } from 'react'; +import { + View, + Text, + ScrollView, + StyleSheet, + Alert, + InteractionManager, + TouchableOpacity +} from 'react-native'; + +import Api from '../../util/api'; +import Notebook from './notebook' + + +export default class NotebookLine extends Component { + + constructor(props) { + super(props); + + this.state = { + notebooks: [] + }; + } + + componentDidMount(){ + InteractionManager.runAfterInteractions(() => { + this.load(); + }); + } + + load() { + Api.getSelfNotebooks() + .then(notebooks => { + if(!notebooks || !notebooks.filter) { + notebooks = []; + } + + const unExpiredBooks = notebooks.filter(it => !it.isExpired); + if(unExpiredBooks.length === 0) { + Alert.alert('提示', '没有可用日记本,无法写日记', [ + {text: '取消', onPress: () => {}}, + {text: '创建一个', onPress: () => {}} + ]); + } + + this.setState({ + notebooks: unExpiredBooks + }); + + }).done(() => {}); + } + + render() { + return ( + + { + this.state.notebooks.map((notebook) => { + return ( + + + + + ); + }) + } + + + ); + } +} + +const localStyle = StyleSheet.create({ + container: { + padding: 10, + paddingRight: 0, + paddingBottom:0 + } +}); \ No newline at end of file diff --git a/src/page/FollowUserPage.js b/src/page/FollowUserPage.js index 500d551..97cf47d 100644 --- a/src/page/FollowUserPage.js +++ b/src/page/FollowUserPage.js @@ -14,7 +14,7 @@ import FollowingUserData from '../dataLoader/followingUserData' import FollowedByUserData from '../dataLoader/followedByUserData' -export default class FollowPage extends Component { +export default class FollowUserPage extends Component { constructor(props) { super(props); @@ -70,9 +70,17 @@ export default class FollowPage extends Component { _renderScene = SceneMap({ following: () => { + return Api.deleteFollow(id); + }} + {...this.props} />, followedBy: () => { + return Api.deleteFollowBy(id); + }} + {...this.props} /> }); diff --git a/src/page/WritePage.js b/src/page/WritePage.js index acb752a..76c11e2 100644 --- a/src/page/WritePage.js +++ b/src/page/WritePage.js @@ -1,5 +1,16 @@ import React, {Component} from 'react'; -import {Platform, StyleSheet, Text, View, ScrollView, TextInput, TouchableOpacity} from 'react-native'; +import { + StyleSheet, + Text, + View, + ScrollView, + TextInput, + TouchableOpacity, + Modal, + Animated, + Easing, + TouchableWithoutFeedback +} from 'react-native'; import {Navigation} from 'react-native-navigation'; import Ionicons from 'react-native-vector-icons/Ionicons'; @@ -7,6 +18,8 @@ import {Icon} from '../style/icon' import Color from '../style/color' import Api from '../util/api' +import NotebookLine from '../component/notebook/notebookLine' + export default class WritePage extends Component { @@ -15,7 +28,11 @@ export default class WritePage extends Component { Navigation.events().bindComponent(this); this.state = { - content: '' + content: '', + + modalVisible: false, + fadeAnimOpacity: new Animated.Value(0), + fadeAnimHeight: new Animated.Value(0) } } @@ -44,6 +61,40 @@ export default class WritePage extends Component { }; } + openModal() { + this.setState({modalVisible: true}); + } + + closeModal(showKeyboard = true) { + this.contentInput.blur(); + Animated.parallel([ + Animated.timing( + this.state.fadeAnimOpacity, + { + toValue: 0, + duration: 350, + easing: Easing.out(Easing.cubic) + } + ), + Animated.timing( + this.state.fadeAnimHeight, + { + toValue: 0, + duration: 350, + easing: Easing.out(Easing.cubic) + } + ) + ]).start(({finished}) => { + this.setState({modalVisible: false}); + if(!finished) { + return; + } + if(showKeyboard) { + setTimeout(() => this.contentInput.focus(), 100); + } + }); + } + render() { return ( - {}}> + @@ -88,9 +139,63 @@ export default class WritePage extends Component { + {this.renderModal()} + ); } + + renderModal() { + return ( + { + Animated.parallel([ + Animated.timing( + this.state.fadeAnimOpacity, + { + toValue: 0.4, + duration: 350, + easing: Easing.out(Easing.cubic) + } + ), + Animated.timing( + this.state.fadeAnimHeight, + { + toValue: Api.IS_IOS + ? (Api.IS_IPHONEX ? 280 : 250) + : 260, + duration: 350, + easing: Easing.out(Easing.cubic) + } + ) + ]).start(); + }} + onRequestClose={() => {}} + > + + + + + + + + {}} style={localStyle.modalButton}> + 新添 + + 选择日记本 + + 取消 + + + + {}}> + + + + + ); + } } const localStyle = StyleSheet.create({ @@ -138,5 +243,22 @@ const localStyle = StyleSheet.create({ height: 40, alignItems: "center", justifyContent: 'center' + }, + + modalBanner: { + flexDirection: 'row', + justifyContent: 'space-between', + borderTopColor: '#e2e2e2', + borderTopWidth: StyleSheet.hairlineWidth, + borderBottomColor: '#e2e2e2', + borderBottomWidth: StyleSheet.hairlineWidth + }, + modalButton: { + paddingHorizontal: 15, + paddingVertical: 10 + }, + modalButtonText: { + color: Color.light, + fontSize: 15, } }); diff --git a/src/util/api.js b/src/util/api.js index 7b6d0a4..6687cf7 100644 --- a/src/util/api.js +++ b/src/util/api.js @@ -6,6 +6,7 @@ import TokenManager from './token' const IS_ANDROID = Platform.OS === 'android'; +const IS_IOS = Platform.OS === 'ios'; const DEVICE_WINDOW = Dimensions.get('window') const OS = DeviceInfo.getSystemName(); @@ -45,6 +46,14 @@ async function getSelfInfo() { return call('GET', '/users/my'); } +async function getSelfInfoByStore() { + return await TokenManager.getUserInfo(); +} + +async function getUserInfo(id) { + return call('GET', '/users/' + id) +} + async function getTodayDiaries(page = 1, page_size = 20, first_id = '') { return call('GET', '/diaries/today?page=' + page + '&page_size=' + page_size + `&first_id=${first_id}`) .then((json) => { @@ -99,12 +108,12 @@ async function getRelationReverseUsers(page, page_size) { return call('GET', `/relation/reverse?page=${page}&page_size=${page_size}`); } -async function getSelfInfoByStore() { - return await TokenManager.getUserInfo(); +async function deleteFollow(user_id) { + return call('DELETE', '/relation/' + user_id); } -async function getUserInfo(id) { - return call('GET', '/users/' + id) +async function deleteFollowBy(user_id) { + return call('DELETE', '/relation/reverse/' + user_id); } async function getMessagesHistory() { @@ -191,6 +200,7 @@ function handleCatch(err) { export default { IS_ANDROID, + IS_IOS, DEVICE_WINDOW, OS, OS_VERSION, @@ -214,6 +224,8 @@ export default { getRelationUsers, getRelationReverseUsers, + deleteFollow, + deleteFollowBy, getMessagesHistory } \ No newline at end of file