mirror of
https://github.com/timepill/timepill-app.git
synced 2025-04-30 09:59:31 +08:00
1. 评论,回复
2. 写日记,隐藏底栏问题(太耗时!) 3. 其他细节补充
This commit is contained in:
parent
44187ec26b
commit
6ff2670a3c
17 changed files with 551 additions and 108 deletions
|
@ -1,11 +1,21 @@
|
|||
import React, {Component} from 'react';
|
||||
import {StyleSheet, Text, View, ActivityIndicator, TextInput, TouchableOpacity} from 'react-native';
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
ActivityIndicator,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
Alert,
|
||||
DeviceEventEmitter
|
||||
} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/Ionicons';
|
||||
import KeyboardSpacer from "react-native-keyboard-spacer";
|
||||
|
||||
import Touchable from '../touchable';
|
||||
import Color from '../../style/color';
|
||||
import Api from '../../util/api';
|
||||
import Event from '../../util/event';
|
||||
|
||||
|
||||
export default class CommentInput extends Component {
|
||||
|
@ -13,13 +23,89 @@ export default class CommentInput extends Component {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.selfInfo = props.selfInfo;
|
||||
this.diary = props.diary;
|
||||
|
||||
this.state = {
|
||||
sending: false
|
||||
sending: false,
|
||||
|
||||
content: '',
|
||||
replyUserId: 0,
|
||||
replyUserName: ''
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.listener = DeviceEventEmitter.addListener(Event.commentPressed, (comment) => {
|
||||
if(this.selfInfo && comment.user.id === this.selfInfo.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let content = this.state.content;
|
||||
if(this.state.replyUserName) {
|
||||
content = content.replace('@' + this.state.replyUserName, '@' + comment.user.name);
|
||||
} else {
|
||||
content = '@' + comment.user.name + ' ' + content;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
content: content,
|
||||
replyUserId: comment.user.id,
|
||||
replyUserName: comment.user.name
|
||||
});
|
||||
|
||||
if(this.refs.commentInput) {
|
||||
// this.refs.commentInput.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
this.listener.remove();
|
||||
}
|
||||
|
||||
sendComment() {
|
||||
this.setState({sending: true});
|
||||
let content = this.state.content;
|
||||
let replyUserId = this.state.replyUserId;
|
||||
let replyUserName = this.state.replyUserName;
|
||||
|
||||
if(replyUserId && content.startsWith('@' + replyUserName + ' ')) {
|
||||
content = content.substr(replyUserName.length + 2);
|
||||
|
||||
} else {
|
||||
replyUserId = 0;
|
||||
replyUserName = '';
|
||||
}
|
||||
|
||||
if(!content) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({comment_sending: true});
|
||||
Api.addComment(this.diary.id, content, replyUserId)
|
||||
.then(result => {
|
||||
if(!result) {
|
||||
throw {
|
||||
message: 'comment failed'
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
content: '',
|
||||
replyUserId: 0,
|
||||
replyUserName: ''
|
||||
|
||||
}, () => {
|
||||
DeviceEventEmitter.emit(Event.updateComments);
|
||||
});
|
||||
|
||||
})
|
||||
.catch(e => {
|
||||
Alert.alert('回复失败');
|
||||
})
|
||||
.done(() => {
|
||||
this.setState({comment_sending: false});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -31,14 +117,18 @@ export default class CommentInput extends Component {
|
|||
ref="commentInput"
|
||||
|
||||
placeholder="回复日记"
|
||||
value={this.state.comment_content}
|
||||
value={this.state.content}
|
||||
|
||||
autoCorrect={false}
|
||||
maxLength={500} multiline={true}
|
||||
showsVerticalScrollIndicator={false}
|
||||
underlineColorAndroid="transparent"
|
||||
|
||||
onChangeText={() => {}}
|
||||
onChangeText={(text) => {
|
||||
this.setState({
|
||||
content: text
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<TouchableOpacity style={localStyle.buttonWrap}
|
||||
onPress={this.sendComment.bind(this)}>
|
||||
|
@ -75,17 +165,17 @@ const localStyle = StyleSheet.create({
|
|||
borderTopWidth: StyleSheet.hairlineWidth
|
||||
},
|
||||
input: {
|
||||
flexGrow: 1,
|
||||
borderColor: '#bbb',
|
||||
backgroundColor: '#fff',
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderRadius: 19,
|
||||
paddingRight: 40,
|
||||
paddingLeft: 15,
|
||||
paddingTop: 12,
|
||||
paddingBottom: 12,
|
||||
fontSize: 12,
|
||||
lineHeight: 24,
|
||||
paddingTop: 10,
|
||||
paddingBottom: 10,
|
||||
height: 39,
|
||||
lineHeight: 20,
|
||||
fontSize: 16,
|
||||
margin: 8
|
||||
},
|
||||
buttonWrap: {
|
||||
|
|
|
@ -6,13 +6,16 @@ import {
|
|||
FlatList,
|
||||
Text,
|
||||
View,
|
||||
Alert
|
||||
Alert,
|
||||
Keyboard,
|
||||
DeviceEventEmitter
|
||||
} from 'react-native';
|
||||
import {Divider} from "react-native-elements";
|
||||
|
||||
import Touchable from '../touchable';
|
||||
import Color from '../../style/color';
|
||||
import Api from '../../util/api';
|
||||
import Event from '../../util/event';
|
||||
import Msg from '../../util/msg'
|
||||
|
||||
import Comment from './comment';
|
||||
|
@ -33,11 +36,11 @@ export default class CommentList extends Component {
|
|||
|
||||
componentDidMount() {
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
this.loadMore();
|
||||
this.refresh();
|
||||
});
|
||||
}
|
||||
|
||||
async loadMore() {
|
||||
async refresh() {
|
||||
let comments = await Api.getDiaryComments(this.diaryId);
|
||||
if(comments && comments.length > 0) {
|
||||
if (comments.length > 1) {
|
||||
|
@ -50,6 +53,10 @@ export default class CommentList extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
_onCommentPress(comment) {
|
||||
DeviceEventEmitter.emit(Event.commentPressed, comment);
|
||||
}
|
||||
|
||||
_onCommentAction(comment) {
|
||||
ActionSheet.showActionSheetWithOptions({
|
||||
options:['删除回复', '取消'],
|
||||
|
@ -88,7 +95,7 @@ export default class CommentList extends Component {
|
|||
render() {
|
||||
return (
|
||||
<View style={localStyle.container}>
|
||||
<FlatList
|
||||
<FlatList ref={(r) => this.list = r}
|
||||
|
||||
data={this.state.comments}
|
||||
|
||||
|
@ -98,7 +105,7 @@ export default class CommentList extends Component {
|
|||
|
||||
renderItem={({item}) => {
|
||||
return (
|
||||
<Touchable onPress={() => {}}>
|
||||
<Touchable onPress={() => this._onCommentPress(item)}>
|
||||
<Comment comment={item} editable={this.editable}
|
||||
onCommentAction={() => this._onCommentAction(item)}>
|
||||
</Comment>
|
||||
|
|
|
@ -62,7 +62,7 @@ export default class DiaryBrief extends Component {
|
|||
</View>
|
||||
|
||||
<Text style={localStyle.content} numberOfLines={5}>
|
||||
{diary.content.trim()}
|
||||
{diary.content}
|
||||
</Text>
|
||||
|
||||
<Photo uri={diary.photoThumbUrl}></Photo>
|
||||
|
|
|
@ -18,6 +18,14 @@ export default class DiaryFull extends Component {
|
|||
this.editable = props.editable || false;
|
||||
}
|
||||
|
||||
refreshDiaryContent() {
|
||||
// empty
|
||||
}
|
||||
|
||||
async refreshComment() {
|
||||
await this.commentList.refresh();
|
||||
}
|
||||
|
||||
render() {
|
||||
let diary = this.diary;
|
||||
if(!diary) {
|
||||
|
@ -56,7 +64,10 @@ export default class DiaryFull extends Component {
|
|||
</View>
|
||||
</View>
|
||||
|
||||
<CommentList diaryId={diary.id} editable={this.editable}></CommentList>
|
||||
<CommentList ref={(r) => this.commentList = r}
|
||||
diaryId={diary.id}
|
||||
editable={this.editable}
|
||||
></CommentList>
|
||||
|
||||
</View>
|
||||
);
|
||||
|
|
|
@ -91,6 +91,7 @@ export default class DiaryList extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
// to be seperated as diaryAction component
|
||||
_onDiaryAction(diary) {
|
||||
ActionSheet.showActionSheetWithOptions({
|
||||
options:['修改','删除', '取消'],
|
||||
|
@ -99,7 +100,26 @@ export default class DiaryList extends Component {
|
|||
|
||||
}, (index) => {
|
||||
if(index === 0) {
|
||||
Navigation.push(this.props.componentId, {
|
||||
component: {
|
||||
name: 'Write',
|
||||
options: {
|
||||
bottomTabs: {
|
||||
visible: false,
|
||||
|
||||
// hide bottom tab for android
|
||||
drawBehind: true,
|
||||
animate: true
|
||||
}
|
||||
},
|
||||
passProps: {
|
||||
diary: diary,
|
||||
onSave: (diary) => {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} else if (index === 1) {
|
||||
Alert.alert('提示', '确认删除日记?', [
|
||||
|
@ -132,7 +152,6 @@ export default class DiaryList extends Component {
|
|||
this.setState({refreshing: true, refreshFailed: false});
|
||||
this.dataSource.refresh()
|
||||
.then(result => {
|
||||
console.log('diary list result:', result);
|
||||
if(!result) {
|
||||
throw {
|
||||
message: 'refresh diary no result'
|
||||
|
@ -208,7 +227,7 @@ export default class DiaryList extends Component {
|
|||
data={this.state.diaries}
|
||||
|
||||
keyExtractor={(item, index) => {
|
||||
return item.id.toString() + item.comment_count;
|
||||
return item.id + item.updated + item.comment_count;
|
||||
}}
|
||||
|
||||
renderItem={({item}) => {
|
||||
|
|
|
@ -25,8 +25,9 @@ export default class NotebookDiaryList extends Component {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.dataSource = new NotebookDiaryData();
|
||||
this.editable = props.editable || false;
|
||||
this.notebook = props.notebook;
|
||||
this.dataSource = new NotebookDiaryData();
|
||||
|
||||
this.state = {
|
||||
diaries: [],
|
||||
|
@ -164,7 +165,8 @@ export default class NotebookDiaryList extends Component {
|
|||
}
|
||||
},
|
||||
passProps: {
|
||||
diary: diary
|
||||
diary: diary,
|
||||
editable: this.editable
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -19,36 +19,18 @@ export default class NotebookLine extends Component {
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
notebooks: []
|
||||
notebooks: props.notebooks || []
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
this.load();
|
||||
});
|
||||
}
|
||||
componentDidMount() {
|
||||
notebooks = this.props.refreshData()
|
||||
|
||||
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(() => {});
|
||||
if(notebooks && notebooks.length > 0) {
|
||||
this.setState({
|
||||
notebooks
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -69,7 +51,7 @@ export default class NotebookLine extends Component {
|
|||
this.state.notebooks.map((notebook) => {
|
||||
return (
|
||||
<TouchableOpacity key={notebook.id} activeOpacity={0.7}
|
||||
onPress={this.props.onNotebookPress}>
|
||||
onPress={() => this.props.onNotebookPress(notebook)}>
|
||||
|
||||
<Notebook key={notebook.id} style={{paddingRight: 10}}
|
||||
notebook={notebook} />
|
||||
|
|
|
@ -85,7 +85,8 @@ export default class NotebookList extends Component {
|
|||
}
|
||||
},
|
||||
passProps: {
|
||||
notebook: notebook
|
||||
notebook: notebook,
|
||||
editable: !this.state.user
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,8 +5,10 @@ function config() {
|
|||
return {
|
||||
root: {
|
||||
bottomTabs: {
|
||||
id: 'MainBottomTab',
|
||||
options: {
|
||||
bottomTabs: {
|
||||
currentTabIndex: 0,
|
||||
titleDisplayMode: 'alwaysShow' // android
|
||||
}
|
||||
},
|
||||
|
@ -64,15 +66,13 @@ function config() {
|
|||
stack: {
|
||||
children: [{
|
||||
component: {
|
||||
name: 'Write',
|
||||
name: 'Empty',
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: '写日记',
|
||||
alignment: 'center' // android
|
||||
}
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}],
|
||||
options: {
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
import React, {Component} from 'react';
|
||||
import {Platform, StyleSheet, Text, View, ScrollView} from 'react-native';
|
||||
import {
|
||||
Platform,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
ScrollView,
|
||||
DeviceEventEmitter,
|
||||
Keyboard
|
||||
} from 'react-native';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
import KeyboardSpacer from "react-native-keyboard-spacer";
|
||||
|
||||
import Color from '../style/color';
|
||||
import {Icon} from '../style/icon';
|
||||
import Msg from '../util/msg';
|
||||
import Api from '../util/api'
|
||||
import Event from '../util/event';
|
||||
|
||||
import DiaryFull from '../component/diary/diaryFull';
|
||||
import CommentInput from '../component/comment/commentInput'
|
||||
|
@ -17,10 +27,16 @@ export default class DiaryDetailPage extends Component {
|
|||
super(props);
|
||||
Navigation.events().bindComponent(this);
|
||||
|
||||
this.diary = props.diary;
|
||||
this.user = props.user;
|
||||
this.state = {
|
||||
selfInfo: null,
|
||||
|
||||
diary: props.diary,
|
||||
user: props.user,
|
||||
|
||||
editable: props.editable || false,
|
||||
needScrollToBottom: false
|
||||
}
|
||||
|
||||
this.editable = props.editable || false;
|
||||
this.onDiaryAction = props.onDiaryAction || (() => {});
|
||||
}
|
||||
|
||||
|
@ -41,8 +57,8 @@ export default class DiaryDetailPage extends Component {
|
|||
}
|
||||
|
||||
navigationButtonPressed({buttonId}) {
|
||||
if(this.editable) {
|
||||
this.onDiaryAction();
|
||||
if(this.state.editable) {
|
||||
this.onDiaryAction(this.state.diary);
|
||||
|
||||
} else {
|
||||
ActionSheet.showActionSheetWithOptions({
|
||||
|
@ -52,22 +68,65 @@ export default class DiaryDetailPage extends Component {
|
|||
|
||||
}, (index) => {
|
||||
if(index == 0) {
|
||||
// Api.report(this.diary.user_id, this.diary.id).done();
|
||||
Api.report(this.state.diary.user_id, this.state.diary.id).done();
|
||||
Msg.showMsg('举报成功,感谢你的贡献 :)');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
Api.getSelfInfoByStore()
|
||||
.then(user => {
|
||||
this.setState({
|
||||
selfInfo: user
|
||||
});
|
||||
|
||||
}).done();
|
||||
|
||||
this.listener = DeviceEventEmitter.addListener(Event.updateComments, (param) => {
|
||||
this.setState({needScrollToBottom: true});
|
||||
this.diaryFull.refreshComment();
|
||||
Keyboard.dismiss();
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
this.listener.remove();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={localStyle.wrap}>
|
||||
<ScrollView style={{flex: 1}}>
|
||||
<DiaryFull diary={this.props.diary} editable={this.editable}></DiaryFull>
|
||||
<ScrollView ref={(r)=>this.scroll = r}
|
||||
style={{flex: 1}}
|
||||
onContentSizeChange={(width, height) => {
|
||||
if(this.state.needScrollToBottom) {
|
||||
this.scroll.scrollTo({y: height});
|
||||
this.setState({needScrollToBottom: false});
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
<DiaryFull ref={(r) => this.diaryFull = r}
|
||||
diary={this.state.diary}
|
||||
editable={this.state.editable}
|
||||
></DiaryFull>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<CommentInput></CommentInput>
|
||||
{
|
||||
this.state.selfInfo ? (
|
||||
<CommentInput ref={(r) => this.commentInput = r}
|
||||
diary={this.state.diary}
|
||||
selfInfo={this.state.selfInfo}
|
||||
></CommentInput>
|
||||
) : null
|
||||
}
|
||||
|
||||
{
|
||||
Api.IS_IOS ? <KeyboardSpacer topSpacing={Api.IS_IPHONEX ? -30 : 0} /> : null
|
||||
}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
74
src/page/EmptyPage.js
Normal file
74
src/page/EmptyPage.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
import React, {Component} from 'react';
|
||||
import {Platform, StyleSheet, Text, View, Alert} from 'react-native';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
|
||||
|
||||
export default class EmptyPage extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
from: props.from
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.navigationEventListener = Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.navigationEventListener.remove();
|
||||
}
|
||||
|
||||
|
||||
componentDidAppear() {
|
||||
let forword = true;
|
||||
if(this.state.from == 'write') {
|
||||
forword = false;
|
||||
this.setState({from: ''});
|
||||
}
|
||||
|
||||
if(!forword) {
|
||||
|
||||
Navigation.mergeOptions(this.props.componentId, {
|
||||
bottomTabs: {
|
||||
currentTabIndex: 4
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
} else {
|
||||
Navigation.push(this.props.componentId, {
|
||||
component: {
|
||||
name: 'Write',
|
||||
options: {
|
||||
animations: {
|
||||
push: {
|
||||
enabled: false
|
||||
},
|
||||
pop: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
bottomTabs: {
|
||||
visible: false,
|
||||
|
||||
// hide bottom tab for android
|
||||
drawBehind: true,
|
||||
animate: true
|
||||
}
|
||||
},
|
||||
passProps: {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -15,18 +15,23 @@ export default class NotebookDetailPage extends Component {
|
|||
}
|
||||
|
||||
static options(passProps) {
|
||||
return {
|
||||
topBar: {
|
||||
title: {
|
||||
text: '《' + passProps.notebook.subject + '》'
|
||||
},
|
||||
rightButtons: [{
|
||||
id: 'navButtonNotebookSetting',
|
||||
icon: Icon.navButtonNotebookSetting,
|
||||
|
||||
color: Color.primary
|
||||
}]
|
||||
let topBar = {
|
||||
title: {
|
||||
text: '《' + passProps.notebook.subject + '》'
|
||||
}
|
||||
}
|
||||
|
||||
if(passProps.editable) {
|
||||
topBar.rightButtons = [{
|
||||
id: 'navButtonNotebookSetting',
|
||||
icon: Icon.navButtonNotebookSetting,
|
||||
|
||||
color: Color.primary
|
||||
}];
|
||||
}
|
||||
|
||||
return {
|
||||
topBar
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {Component} from 'react';
|
||||
import {StyleSheet, Text, View, Animated, DeviceEventEmitter, Alert} from 'react-native';
|
||||
import {
|
||||
PagerScroll,
|
||||
PagerPan,
|
||||
TabView,
|
||||
TabBar,
|
||||
SceneMap
|
||||
|
@ -30,7 +30,7 @@ export default class UserPage extends Component {
|
|||
this.dataSource = new UserDiaryData(this.userId);
|
||||
|
||||
this.state = {
|
||||
index: 0,
|
||||
index: 1,
|
||||
routes: [
|
||||
{ key: 'userIntro', title: '简介' },
|
||||
{ key: 'diary', title: '日记' },
|
||||
|
@ -104,7 +104,7 @@ export default class UserPage extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
componentDidMount() {
|
||||
if(this.userId) {
|
||||
Api.getRelation(this.userId)
|
||||
.then(re => {
|
||||
|
@ -120,15 +120,21 @@ export default class UserPage extends Component {
|
|||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
this.listener = DeviceEventEmitter.addListener(Event.updateNotebooks, (param) => {
|
||||
this.notebookListener = DeviceEventEmitter.addListener(Event.updateNotebooks, (param) => {
|
||||
this.notebookList.refresh();
|
||||
});
|
||||
|
||||
this.diaryListener = DeviceEventEmitter.addListener(Event.updateDiarys, (param) => {
|
||||
this.diaryList.refresh();
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
this.listener.remove();
|
||||
componentWillUnmount() {
|
||||
this.notebookListener.remove();
|
||||
this.diaryListener.remove();
|
||||
}
|
||||
|
||||
_renderLabel = props => ({route}) => {
|
||||
|
@ -163,6 +169,7 @@ export default class UserPage extends Component {
|
|||
user={this.user}
|
||||
/>,
|
||||
diary: () => <DiaryList
|
||||
ref={(r) => this.diaryList = r}
|
||||
dataSource={this.dataSource}
|
||||
editable={!this.user}
|
||||
{...this.props}
|
||||
|
@ -182,7 +189,7 @@ export default class UserPage extends Component {
|
|||
width: Api.DEVICE_WINDOW.width
|
||||
}}
|
||||
|
||||
renderPager={(props) => <PagerScroll {...props}/>} /* android */
|
||||
renderPager = {props => <PagerPan {...props} />} /* android */
|
||||
|
||||
renderTabBar={this._renderTabBar}
|
||||
renderScene={this._renderScene}
|
||||
|
|
|
@ -9,16 +9,23 @@ import {
|
|||
Modal,
|
||||
Animated,
|
||||
Easing,
|
||||
TouchableWithoutFeedback
|
||||
TouchableWithoutFeedback,
|
||||
DeviceEventEmitter,
|
||||
Alert
|
||||
} from 'react-native';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
import KeyboardSpacer from "react-native-keyboard-spacer";
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
|
||||
import {Icon} from '../style/icon'
|
||||
import Color from '../style/color'
|
||||
import Api from '../util/api'
|
||||
import BottomNav from '../nav/bottomNav';
|
||||
import {Icon} from '../style/icon';
|
||||
import Color from '../style/color';
|
||||
import Api from '../util/api';
|
||||
import Msg from '../util/msg';
|
||||
import Token from '../util/token'
|
||||
import Event from "../util/event";
|
||||
|
||||
import NotebookLine from '../component/notebook/notebookLine'
|
||||
import NotebookLine from '../component/notebook/notebookLine';
|
||||
|
||||
|
||||
export default class WritePage extends Component {
|
||||
|
@ -27,8 +34,14 @@ export default class WritePage extends Component {
|
|||
super(props);
|
||||
Navigation.events().bindComponent(this);
|
||||
|
||||
let diary = this.diary = props.diary;
|
||||
this.state = {
|
||||
content: '',
|
||||
notebooks: [],
|
||||
|
||||
targetbookId: diary ? diary.notebook_id : 0,
|
||||
targetbookSubject: diary ? diary.notebook_subject : '',
|
||||
|
||||
content: diary ? diary.content : '',
|
||||
|
||||
modalVisible: false,
|
||||
fadeAnimOpacity: new Animated.Value(0),
|
||||
|
@ -50,19 +63,57 @@ export default class WritePage extends Component {
|
|||
id: 'save',
|
||||
icon: Icon.navButtonSave
|
||||
}]
|
||||
},
|
||||
bottomTabs: {
|
||||
visible: false,
|
||||
|
||||
// hide bottom tab for android
|
||||
drawBehind: true,
|
||||
animate: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
navigationButtonPressed({buttonId}) {
|
||||
if(buttonId == 'cancel') {
|
||||
|
||||
if(this.diary) {
|
||||
Navigation.pop(this.props.componentId);
|
||||
|
||||
} else {
|
||||
Navigation.setStackRoot(this.props.componentId, {
|
||||
component: {
|
||||
name: 'Empty',
|
||||
options: {
|
||||
bottomTabs: {
|
||||
visible: true
|
||||
}
|
||||
},
|
||||
passProps: {
|
||||
from: 'write'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} else if(buttonId == 'save') {
|
||||
this.saveDiary();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.loadNotebook();
|
||||
|
||||
this.notebookListener = DeviceEventEmitter.addListener(Event.updateNotebooks, (param) => {
|
||||
this.loadNotebook(true);
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
this.notebookListener.remove();
|
||||
}
|
||||
|
||||
openModal() {
|
||||
this.setState({modalVisible: true});
|
||||
|
||||
if(this.state.notebooks.length == 0) {
|
||||
Alert.alert('提示', '没有可用日记本,无法写日记', [
|
||||
{text: '确定', onPress: () => {}}
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
closeModal(showKeyboard = true) {
|
||||
|
@ -95,6 +146,88 @@ export default class WritePage extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
_onCreateNotebook() {
|
||||
this.closeModal(false);
|
||||
Navigation.push(this.props.componentId, {
|
||||
component: {
|
||||
name: 'NotebookEdit'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_onNotebookSelected(notebook) {
|
||||
this.setState({
|
||||
targetbookId: notebook.id,
|
||||
targetbookSubject: notebook.subject
|
||||
|
||||
}, () => {
|
||||
this.closeModal();
|
||||
});
|
||||
}
|
||||
|
||||
loadNotebook(resetTargetbook = false) {
|
||||
Api.getSelfNotebooks()
|
||||
.then(notebooks => {
|
||||
if(!notebooks || !notebooks.filter) {
|
||||
notebooks = [];
|
||||
}
|
||||
|
||||
let unExpiredBooks = notebooks.filter(it => !it.isExpired);
|
||||
if(unExpiredBooks.length > 0) {
|
||||
let st = {
|
||||
notebooks: unExpiredBooks
|
||||
}
|
||||
|
||||
if(resetTargetbook || this.state.targetbookId == 0) {
|
||||
st.targetbookId = unExpiredBooks[0].id;
|
||||
st.targetbookSubject = unExpiredBooks[0].subject;
|
||||
}
|
||||
|
||||
this.setState(st);
|
||||
}
|
||||
|
||||
}).done();
|
||||
}
|
||||
|
||||
saveDiary() {
|
||||
let photoUri = null;
|
||||
let topic = this.props.topic ? 1 : 0;
|
||||
|
||||
(this.diary
|
||||
? Api.updateDiary(this.diary.id, this.state.targetbookId, this.state.content)
|
||||
: Api.addDiary(this.state.targetbookId, this.state.content, null, topic)
|
||||
).then(result => {
|
||||
Msg.showMsg('日记保存完成');
|
||||
DeviceEventEmitter.emit(Event.updateDiarys);
|
||||
|
||||
this.props.onSave(result);
|
||||
|
||||
if(this.diary) {
|
||||
Navigation.pop(this.props.componentId);
|
||||
|
||||
} else {
|
||||
Navigation.setStackRoot(this.props.componentId, {
|
||||
component: {
|
||||
name: 'Empty',
|
||||
options: {
|
||||
bottomTabs: {
|
||||
visible: true
|
||||
}
|
||||
},
|
||||
passProps: {
|
||||
from: 'write'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})
|
||||
.catch(e => {
|
||||
Msg.showMsg('保存失败');
|
||||
})
|
||||
.done();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ScrollView style={localStyle.container}
|
||||
|
@ -112,7 +245,9 @@ export default class WritePage extends Component {
|
|||
placeholder='记录点滴生活'
|
||||
value={this.state.content}
|
||||
|
||||
onChangeText={() => {}}
|
||||
onChangeText={(text) => {
|
||||
this.setState({content: text});
|
||||
}}
|
||||
|
||||
autoCorrect={false}
|
||||
autoCapitalize='none'
|
||||
|
@ -123,22 +258,24 @@ export default class WritePage extends Component {
|
|||
<View style={localStyle.notebookButton}>
|
||||
<Ionicons name='ios-bookmarks-outline' size={16}
|
||||
color={Color.text} style={{marginTop: 2, marginRight: 6}} />
|
||||
<Text style={{fontSize: 13, color: Color.text }}>{'日记本名'}</Text>
|
||||
<Text style={{fontSize: 13, color: Color.text }}>
|
||||
{this.state.targetbookSubject ? this.state.targetbookSubject : '..'}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={{flex: 1}} />
|
||||
|
||||
<TouchableOpacity>
|
||||
<Text style={localStyle.topic}># {'话题名'}</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={localStyle.photo} onPress={() => {}}>
|
||||
<Ionicons name="ios-image-outline" size={30}
|
||||
style={{paddingTop: 4}} color={Color.light} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{
|
||||
Api.IS_IOS ? <KeyboardSpacer topSpacing={Api.IS_IPHONEX ? -30 : 0} /> : null
|
||||
}
|
||||
|
||||
{this.renderModal()}
|
||||
|
||||
</ScrollView>
|
||||
|
@ -180,7 +317,7 @@ export default class WritePage extends Component {
|
|||
|
||||
<Animated.View style={{height: this.state.fadeAnimHeight, backgroundColor: '#fff'}}>
|
||||
<View style={localStyle.modalBanner}>
|
||||
<TouchableOpacity onPress={() => {}} style={localStyle.modalButton}>
|
||||
<TouchableOpacity onPress={this._onCreateNotebook.bind(this)} style={localStyle.modalButton}>
|
||||
<Text style={localStyle.modalButtonText}>新添</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={{padding: 10, color: Color.text}}>选择日记本</Text>
|
||||
|
@ -189,7 +326,10 @@ export default class WritePage extends Component {
|
|||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<NotebookLine onNotebookPress={() => {}}></NotebookLine>
|
||||
<NotebookLine
|
||||
refreshData={() => this.state.notebooks}
|
||||
onNotebookPress={this._onNotebookSelected.bind(this)}
|
||||
></NotebookLine>
|
||||
|
||||
</Animated.View>
|
||||
</View>
|
||||
|
@ -259,6 +399,6 @@ const localStyle = StyleSheet.create({
|
|||
},
|
||||
modalButtonText: {
|
||||
color: Color.light,
|
||||
fontSize: 15,
|
||||
fontSize: 15
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export default {
|
||||
DiaryDetail: require("./DiaryDetailPage.js").default,
|
||||
Empty: require("./EmptyPage.js").default,
|
||||
Follow: require("./FollowPage.js").default,
|
||||
FollowUser: require("./FollowUserPage.js").default,
|
||||
Home: require("./HomePage.js").default,
|
||||
|
|
|
@ -89,13 +89,21 @@ async function getUserTodayDiaries(userId) {
|
|||
}
|
||||
|
||||
async function getDiaryComments(diaryId) {
|
||||
return call('GET', '/diaries/' + diaryId + '/comments')
|
||||
return call('GET', '/diaries/' + diaryId + '/comments');
|
||||
}
|
||||
|
||||
async function deleteComment(id) {
|
||||
return call('DELETE', '/comments/' + id)
|
||||
return call('DELETE', '/comments/' + id);
|
||||
}
|
||||
|
||||
async function addComment(diaryId, content, recipient_id) {
|
||||
return call('POST', '/diaries/' + diaryId + '/comments', {
|
||||
content: content,
|
||||
recipient_id: recipient_id,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async function getSelfNotebooks() {
|
||||
return call('GET', '/notebooks/my')
|
||||
}
|
||||
|
@ -169,6 +177,34 @@ async function deleteNotebook(id) {
|
|||
return call('DELETE', '/notebooks/' + id)
|
||||
}
|
||||
|
||||
async function addDiary(bookId, content, photoUri = null, join_topic = null) {
|
||||
if(!photoUri) {
|
||||
return call('POST', '/notebooks/' + bookId + '/diaries', {
|
||||
content,
|
||||
join_topic
|
||||
});
|
||||
|
||||
} else {
|
||||
return upload('POST', '/notebooks/' + bookId + '/diaries', {
|
||||
content,
|
||||
join_topic,
|
||||
photo: {
|
||||
uri: photoUri,
|
||||
name: 'image.jpg',
|
||||
type: 'image/jpg'
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function updateDiary(id, bookId, content) {
|
||||
return call('PUT', '/diaries/' + id, {
|
||||
content,
|
||||
notebook_id: bookId
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async function report(user_id, diary_id) {
|
||||
return call('POST', '/reports/', {
|
||||
user_id: user_id,
|
||||
|
@ -303,6 +339,7 @@ export default {
|
|||
|
||||
getDiaryComments,
|
||||
deleteComment,
|
||||
addComment,
|
||||
|
||||
getSelfNotebooks,
|
||||
getUserNotebooks,
|
||||
|
@ -321,5 +358,8 @@ export default {
|
|||
updateNotebook,
|
||||
deleteNotebook,
|
||||
|
||||
addDiary,
|
||||
updateDiary,
|
||||
|
||||
report
|
||||
}
|
|
@ -1,4 +1,9 @@
|
|||
export default {
|
||||
updateNotebooks: 'updateNotebooks'
|
||||
|
||||
updateNotebooks: 'updateNotebooks',
|
||||
updateDiarys: 'updateDiarys',
|
||||
updateComments: 'updateComments',
|
||||
|
||||
commentPressed: 'commentPressed'
|
||||
|
||||
}
|
Loading…
Reference in a new issue