diff --git a/App.js b/App.js index e9791be..32248fd 100644 --- a/App.js +++ b/App.js @@ -87,7 +87,7 @@ const localStyle = StyleSheet.create({ }, content: { flex: 1, - paddingTop: 100, + paddingTop: 65, paddingHorizontal: 15 }, bottom: { diff --git a/index.js b/index.js index 1b42474..60f42be 100644 --- a/index.js +++ b/index.js @@ -35,7 +35,12 @@ Navigation.events().registerAppLaunchedListener(async () => { stack: { children: [{ component: { - name: 'Timepill' + name: 'Timepill', + options: { + topBar: { + visible: false + } + } } }] } diff --git a/src/component/diary/diaryFull.js b/src/component/diary/diaryFull.js index 3b5cdf7..ad310f9 100644 --- a/src/component/diary/diaryFull.js +++ b/src/component/diary/diaryFull.js @@ -14,12 +14,21 @@ export default class DiaryFull extends Component { constructor(props) { super(props); - this.diary = props.diary; - this.editable = props.editable || false; + this.state = { + diary: props.diary, + editable: props.editable || false + } } refreshDiaryContent() { - // empty + if(!this.props.refreshData) { + return; + } + + let diary = this.props.refreshData(); + if(diary) { + this.setState({diary}) + } } async refreshComment() { @@ -27,7 +36,7 @@ export default class DiaryFull extends Component { } render() { - let diary = this.diary; + let diary = this.state.diary; if(!diary) { return null; } @@ -66,7 +75,7 @@ export default class DiaryFull extends Component { this.commentList = r} diaryId={diary.id} - editable={this.editable} + editable={this.state.editable} > diff --git a/src/component/image/imageAction.js b/src/component/image/imageAction.js index e69de29..a31b832 100644 --- a/src/component/image/imageAction.js +++ b/src/component/image/imageAction.js @@ -0,0 +1,55 @@ +import ActionSheet from 'react-native-actionsheet-api'; +import ImagePicker from 'react-native-image-crop-picker' +import ImageResizer from 'react-native-image-resizer' + + +async function resize(uri, oWidth, oHeight) { + let width = oWidth; + let height = oHeight; + + let maxPixel = 640 * 640; + let oPixel = oWidth * oHeight; + + if(oPixel > maxPixel) { + width = Math.sqrt(oWidth * maxPixel / oHeight); + height = Math.sqrt(oHeight * maxPixel / oWidth); + } + + const newUri = await ImageResizer.createResizedImage(uri, width, height, 'JPEG', 75); + return 'file://' + newUri.uri; +} + +function action(imageOption, callback) { + ActionSheet.showActionSheetWithOptions({ + options: ['拍照', '从相册选择', '取消'], + cancelButtonIndex: 2, + title: '选择图片' + + }, (index) => { + if(index == 0 || index == 1) { + if(!imageOption) { + return; + } + + ( + index == 0 + ? ImagePicker.openCamera(imageOption) + : ImagePicker.openPicker(imageOption) + ) + .then(async (image) => { + let imageUri = await resize(image.path, image.width, image.height); + if(typeof callback == 'function') { + callback(imageUri); + } + }) + .catch(e => { + // + }) + .done(); + } + }); +} + +export default { + action +} \ No newline at end of file diff --git a/src/component/listEmpty.js b/src/component/listEmpty.js new file mode 100644 index 0000000..e69de29 diff --git a/src/component/loginForm.js b/src/component/loginForm.js index ada9012..eb2ad0d 100644 --- a/src/component/loginForm.js +++ b/src/component/loginForm.js @@ -25,7 +25,6 @@ export default class LoginForm extends Component { try { isLoginSucc = await Api.login(this.state.username, this.state.password); } catch (err) { - console.log(err); errMsg = err.message; } diff --git a/src/component/notebook/notebookDiaryList.js b/src/component/notebook/notebookDiaryList.js index eb6d437..2b141ce 100644 --- a/src/component/notebook/notebookDiaryList.js +++ b/src/component/notebook/notebookDiaryList.js @@ -68,7 +68,6 @@ export default class NotebookDiaryList extends Component { return maplist; }, {}); - console.log('reduce result:', reducedDiaries); let result = []; for(let key in reducedDiaries) { diff --git a/src/component/notebook/notebookLine.js b/src/component/notebook/notebookLine.js index a3518fe..3140102 100644 --- a/src/component/notebook/notebookLine.js +++ b/src/component/notebook/notebookLine.js @@ -24,7 +24,7 @@ export default class NotebookLine extends Component { } componentDidMount() { - notebooks = this.props.refreshData() + let notebooks = this.props.refreshData() if(notebooks && notebooks.length > 0) { this.setState({ diff --git a/src/component/notification/notification.js b/src/component/notification/notification.js index 81def5a..015ec28 100644 --- a/src/component/notification/notification.js +++ b/src/component/notification/notification.js @@ -6,18 +6,58 @@ import Touchable from '../touchable'; import Color from '../../style/color' +function unique(array) { + let n = []; + for(let i=0; i it.content.author.name)).join('、'); + const body = `${users} 回复了你`; + return ( - {}}> + this.props.onCommentPress(msg)}> - - {'XXX 回复了你|关注了你'} + + {body} - ); + ) + } + + renderFollow(msg) { + const body = `${msg.content.user.name} 关注了你`; + + return ( + this.props.onFollowPress(msg)}> + + + {body} + + + ) } } diff --git a/src/component/notification/notificationList.js b/src/component/notification/notificationList.js index b7d11f9..5e3cfd1 100644 --- a/src/component/notification/notificationList.js +++ b/src/component/notification/notificationList.js @@ -1,5 +1,6 @@ import React, {Component} from 'react'; import {StyleSheet, Text, View, FlatList, InteractionManager} from 'react-native'; +import {Navigation} from 'react-native-navigation'; import Api from '../../util/api'; import Notification from './notification'; @@ -26,17 +27,83 @@ export default class NotificationList extends Component { this.setState({refreshing: true}); Api.getMessagesHistory() .then(notifications => { - console.log('notifications:', notifications); + if(notifications) { + let reducedNoti = notifications.reduce((ret, v) => { + if(v.type == 1) { + let items = ret.filter(x => x.type === 1 && x.link_id === v.link_id); + if(items.length > 0) { + items[0].list.push(v); - this.setState({ - notifications - }); + } else { + ret.push({ + type: 1, + link_id: v.link_id, + created: v.created, + list: [v] + }); + } + + } else if (v.type == 2) { + ret.push(v); + } + + return ret; + + }, []); + + console.log('notifications:', reducedNoti); + + this.setState({ + notifications: reducedNoti + }); + } }).done(() => { this.setState({refreshing: false}); }); } + _onCommentPress(msg) { + Navigation.push(this.props.componentId, { + component: { + name: 'DiaryDetail', + options: { + bottomTabs: { + visible: false, + + // hide bottom tab for android + drawBehind: true, + animate: true + } + }, + passProps: { + diaryId: msg.link_id, + editable: true + } + } + }); + } + + _onFollowPress(msg) { + Navigation.push(this.props.componentId, { + component: { + name: 'User', + options: { + bottomTabs: { + visible: false, + + // hide bottom tab for android + drawBehind: true, + animate: true + } + }, + passProps: { + user: msg.content.user + } + } + }); + } + render() { let hasData = this.state.notifications && this.state.notifications.length > 0; return hasData ? ( @@ -44,12 +111,15 @@ export default class NotificationList extends Component { data={this.state.notifications} keyExtractor={(item, index) => { - return item.id ? item.id.toString() : index + return item.id ? item.id.toString() : `${index}` }} renderItem={({item}) => { return ( - + ); }} @@ -63,4 +133,7 @@ export default class NotificationList extends Component { const localStyle = StyleSheet.create({ -}); \ No newline at end of file +}); + + + diff --git a/src/component/registerForm.js b/src/component/registerForm.js index e894ad4..eecee3a 100644 --- a/src/component/registerForm.js +++ b/src/component/registerForm.js @@ -22,14 +22,11 @@ export default class RegisterForm extends Component { async register() { let isRegisterSucc, errMsg = '注册失败'; - this.props.setLoading(true); try { isRegisterSucc = await Api.register(this.state.nickname, this.state.username, this.state.password); } catch (err) { - console.log(err); errMsg = err.message; } - this.props.setLoading(false); return { isRegisterSucc, @@ -40,12 +37,7 @@ export default class RegisterForm extends Component { _checkResult(result) { InteractionManager.runAfterInteractions(() => { if(result.isRegisterSucc) { - Navigation.startSingleScreenApp({ - screen: { - screen: 'Home', - title: 'Home Title', - } - }); + Navigation.setRoot(BottomNav.config()); } else { Alert.alert( @@ -61,7 +53,23 @@ export default class RegisterForm extends Component { } _clickRegister() { - this.register().then(this._checkResult); + this.props.setLoading(true); + this.register().then(result => { + this.props.setLoading(false); + this._checkResult(result); + }); + } + + _nicknameSubmit() { + this.refs.inputEmail.focus(); + } + + _usernameSubmit() { + this.refs.registerPw.focus(); + } + + _passwordSubmit() { + this._clickRegister(); } render() {return ( @@ -74,7 +82,7 @@ export default class RegisterForm extends Component { selectionColor={Color.primary} underlineColorAndroid='transparent' keyboardType='email-address' - value={''} + value={this.state.nickname} autoCorrect={false} autoFocus={false} @@ -84,35 +92,35 @@ export default class RegisterForm extends Component { placeholder='名字' returnKeyType='next' - onChangeText={() => {}} - onSubmitEditing={() => {}} + onChangeText={(text) => this.setState({nickname: text})} + onSubmitEditing={this._nicknameSubmit.bind(this)} /> - {}} + onChangeText={(text) => this.setState({username: text})} onSubmitEditing={() => {}} /> - {}} - onSubmitEditing={() => {}} + onChangeText={(text) => this.setState({password: text})} + onSubmitEditing={this._passwordSubmit.bind(this)} /> diff --git a/src/page/DiaryDetailPage.js b/src/page/DiaryDetailPage.js index 67bfa7c..3b3dade 100644 --- a/src/page/DiaryDetailPage.js +++ b/src/page/DiaryDetailPage.js @@ -30,6 +30,7 @@ export default class DiaryDetailPage extends Component { this.state = { selfInfo: null, + diaryId: props.diaryId, diary: props.diary, user: props.user, @@ -76,6 +77,27 @@ export default class DiaryDetailPage extends Component { } componentDidMount() { + if(!this.state.diary && this.state.diaryId) { + Api.getDiary(this.state.diaryId) + .then(result => { + console.log('get diary:', result); + if(!result) { + throw { + message: 'get diary no result' + } + } + + this.setState({ + diary: result + }, () => { + this.diaryFull.refreshDiaryContent(); + }) + }) + .done(() => { + + }); + } + Api.getSelfInfoByStore() .then(user => { this.setState({ @@ -110,13 +132,14 @@ export default class DiaryDetailPage extends Component { this.diaryFull = r} diary={this.state.diary} + refreshData={() => this.state.diary} editable={this.state.editable} > { - this.state.selfInfo ? ( + this.state.selfInfo && this.state.diary ? ( this.commentInput = r} diary={this.state.diary} selfInfo={this.state.selfInfo} diff --git a/src/page/NotebookEditPage.js b/src/page/NotebookEditPage.js index d7f568c..aa893f5 100644 --- a/src/page/NotebookEditPage.js +++ b/src/page/NotebookEditPage.js @@ -24,6 +24,7 @@ import Event from "../util/event"; import Loading from '../component/loading' import DateInput from '../component/dateInput' +import ImageAction from '../component/image/imageAction' export default class NotebookEditPage extends Component { @@ -111,71 +112,34 @@ export default class NotebookEditPage extends Component { this.setState({saving: false}); } - - async resizePhoto(uri, oWidth, oHeight) { - let width = 0; - let height = 0; - - let maxPixel = 640 * 640; - let oPixel = oWidth * oHeight; - - if(oPixel > maxPixel) { - width = Math.sqrt(oWidth * maxPixel / oHeight); - height = Math.sqrt(oHeight * maxPixel / oWidth); - - } else { - width = oWidth; - height = oHeight; - } - - const newUri = await ImageResizer.createResizedImage(uri, width, height, 'JPEG', 75); - return 'file://' + newUri.uri; - } - - async _uploadCover(uri, width, height) { - const newUri = await this.resizePhoto(uri, width, height); - - try { - this.setState({uploading: true}); - let result = await Api.updateNotebookCover(this.props.notebook.id, newUri); - if(result) { - Msg.showMsg('封面保存成功'); - - } else { - throw { - message: 'upload notebook cover failed' + uploadCover(uri) { + this.setState({uploading: true}); + Api.updateNotebookCover(this.props.notebook.id, uri) + .then(result => { + if(!result) { + throw { + message: 'upload notebook cover failed' + } } - } - } catch (e) { - Msg.showMsg('封面保存失败'); - } - - this.setState({uploading: false}); + DeviceEventEmitter.emit(Event.updateNotebooks); + Msg.showMsg('封面保存成功'); + }) + .catch(e => { + // Msg.showMsg('封面保存失败:' + e.message); + Alert.alert('封面保存失败:' + e.message); + }) + .done(() => { + this.setState({uploading: false}); + }); } _onEditCover() { - ActionSheet.showActionSheetWithOptions({ - options: ['拍照', '从相册选择', '取消'], - cancelButtonIndex: 2, - title: '设置封面' - - }, (index) => { - if (index != 2) { - let imageOption = { - width: 640, - height: 480, - cropping: true - }; - - let imageSelect = index == 0 - ? ImagePicker.openCamera(imageOption) : ImagePicker.openPicker(imageOption); - - imageSelect.then(image => { - this._uploadCover(image.path, image.width, image.height); - }) - } - }); + ImageAction.action({ + width: 640, + height: 480, + cropping: true + }, this.uploadCover.bind(this)); } _onDelete() { diff --git a/src/page/NotificationHistoryPage.js b/src/page/NotificationHistoryPage.js index 627c4bd..283b8be 100644 --- a/src/page/NotificationHistoryPage.js +++ b/src/page/NotificationHistoryPage.js @@ -28,7 +28,7 @@ export default class NotificationHistoryPage extends Component { render() { return ( - + ); } diff --git a/src/util/api.js b/src/util/api.js index e88a899..9f6ba98 100644 --- a/src/util/api.js +++ b/src/util/api.js @@ -141,6 +141,10 @@ async function getMessagesHistory() { return call('GET', '/tip/history'); } +async function getDiary(id) { + return call('GET', '/diaries/' + id); +} + async function deleteDiary(id) { return call('DELETE', '/diaries/' + id); } @@ -214,7 +218,7 @@ async function report(user_id, diary_id) { async function upload(method, api, body) { - let token = await TokenManager.getToken(); + let token = await TokenManager.getUserToken(); let formData = new FormData(); for(let prop of Object.keys(body)) { formData.append(prop, body[prop]); @@ -335,6 +339,8 @@ export default { getFollowDiaries, getNotebookDiaries, getUserTodayDiaries, + + getDiary, deleteDiary, getDiaryComments,