mirror of
https://github.com/timepill/timepill-app.git
synced 2025-04-30 09:59:31 +08:00
1. 空日记列表组件
2. 日记列表尾组件整理 3. 清理不必要组件 4. 照片日记修改保存后跳转
This commit is contained in:
parent
c45b638b79
commit
3c8d338345
18 changed files with 295 additions and 209 deletions
2
App.js
2
App.js
|
@ -87,7 +87,7 @@ const localStyle = StyleSheet.create({
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingTop: 65,
|
paddingTop: '30%',
|
||||||
paddingHorizontal: 15
|
paddingHorizontal: 15
|
||||||
},
|
},
|
||||||
bottom: {
|
bottom: {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {StyleSheet, Text, View} from 'react-native';
|
import {StyleSheet, Text, View, TouchableOpacity, Alert} from 'react-native';
|
||||||
|
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||||
|
import ActionSheet from 'react-native-actionsheet-api';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
import Color from '../../style/color';
|
import Color from '../../style/color';
|
||||||
import UserIcon from '../userIcon';
|
import UserIcon from '../userIcon';
|
||||||
|
|
||||||
import CommentActionIcon from './commentActionIcon';
|
|
||||||
|
|
||||||
|
|
||||||
export default class Comment extends Component {
|
export default class Comment extends Component {
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ export default class Comment extends Component {
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<View style={localStyle.box}>
|
<View style={localStyle.box}>
|
||||||
<UserIcon iconUrl={user.iconUrl}></UserIcon>
|
<UserIcon iconUrl={user.iconUrl} onPress={this.props.onUserIconPress}></UserIcon>
|
||||||
|
|
||||||
<View style={localStyle.body}>
|
<View style={localStyle.body}>
|
||||||
<View style={localStyle.title}>
|
<View style={localStyle.title}>
|
||||||
|
@ -40,7 +40,9 @@ export default class Comment extends Component {
|
||||||
|
|
||||||
{
|
{
|
||||||
editable
|
editable
|
||||||
? <CommentActionIcon onPress={this.props.onCommentAction}></CommentActionIcon>
|
? <TouchableOpacity onPress={this.props.onCommentAction} style={localStyle.moreIcon}>
|
||||||
|
<Ionicons name="ios-more" size={24} color={Color.inactiveText} />
|
||||||
|
</TouchableOpacity>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,5 +93,12 @@ const localStyle = StyleSheet.create({
|
||||||
backgroundColor: Color.line,
|
backgroundColor: Color.line,
|
||||||
marginHorizontal: 16,
|
marginHorizontal: 16,
|
||||||
marginLeft: 56
|
marginLeft: 56
|
||||||
|
},
|
||||||
|
moreIcon: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 0,
|
||||||
|
right: 10,
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
paddingVertical: 5
|
||||||
}
|
}
|
||||||
});
|
});
|
|
@ -1,37 +0,0 @@
|
||||||
import React, {Component} from 'react';
|
|
||||||
import {StyleSheet, Text, View, TouchableOpacity, Alert} from 'react-native';
|
|
||||||
import Icon from 'react-native-vector-icons/Ionicons';
|
|
||||||
import ActionSheet from 'react-native-actionsheet-api';
|
|
||||||
|
|
||||||
import Color from '../../style/color'
|
|
||||||
|
|
||||||
|
|
||||||
export default class CommentActionIcon extends Component {
|
|
||||||
|
|
||||||
_defaultOnPress() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<TouchableOpacity style={localStyle.moreIcon}
|
|
||||||
onPress={this.props.onPress ? this.props.onPress : this._defaultOnPress.bind(this)}
|
|
||||||
>
|
|
||||||
<Icon name="ios-more"
|
|
||||||
size={24}
|
|
||||||
color={Color.inactiveText} />
|
|
||||||
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const localStyle = StyleSheet.create({
|
|
||||||
moreIcon: {
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: 0,
|
|
||||||
right: 10,
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
paddingVertical: 5
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,36 +0,0 @@
|
||||||
import React, {Component} from 'react';
|
|
||||||
import {StyleSheet, Text, View} from 'react-native';
|
|
||||||
import Icon from 'react-native-vector-icons/Ionicons';
|
|
||||||
|
|
||||||
import Color from '../../style/color'
|
|
||||||
|
|
||||||
|
|
||||||
export default class CommentIcon extends Component {
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<View style={localStyle.commentIconBox}>
|
|
||||||
<Icon name="ios-text-outline"
|
|
||||||
size={18}
|
|
||||||
color={Color.inactiveText}
|
|
||||||
style={localStyle.buttonIcon} />
|
|
||||||
|
|
||||||
<Text style={localStyle.commentIconText}>{this.props.count}</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const localStyle = StyleSheet.create({
|
|
||||||
commentIconBox: {
|
|
||||||
flexDirection: "row"
|
|
||||||
},
|
|
||||||
buttonIcon: {
|
|
||||||
marginRight: 8,
|
|
||||||
marginLeft: 2
|
|
||||||
},
|
|
||||||
commentIconIext: {
|
|
||||||
fontSize: 15,
|
|
||||||
color: Color.inactiveText
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
Keyboard,
|
Keyboard,
|
||||||
DeviceEventEmitter
|
DeviceEventEmitter
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
import {Navigation} from 'react-native-navigation';
|
||||||
import {Divider} from "react-native-elements";
|
import {Divider} from "react-native-elements";
|
||||||
|
|
||||||
import Touchable from '../touchable';
|
import Touchable from '../touchable';
|
||||||
|
@ -57,6 +58,26 @@ export default class CommentList extends Component {
|
||||||
DeviceEventEmitter.emit(Event.commentPressed, comment);
|
DeviceEventEmitter.emit(Event.commentPressed, comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onUserIconPress(comment) {
|
||||||
|
Navigation.push(this.props.componentId, {
|
||||||
|
component: {
|
||||||
|
name: 'User',
|
||||||
|
options: {
|
||||||
|
bottomTabs: {
|
||||||
|
visible: false,
|
||||||
|
|
||||||
|
// hide bottom tab for android
|
||||||
|
drawBehind: true,
|
||||||
|
animate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
passProps: {
|
||||||
|
user: comment.user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_onCommentAction(comment) {
|
_onCommentAction(comment) {
|
||||||
ActionSheet.showActionSheetWithOptions({
|
ActionSheet.showActionSheetWithOptions({
|
||||||
options:['删除回复', '取消'],
|
options:['删除回复', '取消'],
|
||||||
|
@ -107,6 +128,7 @@ export default class CommentList extends Component {
|
||||||
return (
|
return (
|
||||||
<Touchable onPress={() => this._onCommentPress(item)}>
|
<Touchable onPress={() => this._onCommentPress(item)}>
|
||||||
<Comment comment={item} editable={this.editable}
|
<Comment comment={item} editable={this.editable}
|
||||||
|
onUserIconPress={() => this._onUserIconPress(item)}
|
||||||
onCommentAction={() => this._onCommentAction(item)}>
|
onCommentAction={() => this._onCommentAction(item)}>
|
||||||
</Comment>
|
</Comment>
|
||||||
</Touchable>
|
</Touchable>
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
import React, {Component} from 'react';
|
|
||||||
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native';
|
|
||||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
|
||||||
|
|
||||||
import Color from '../../style/color'
|
|
||||||
|
|
||||||
|
|
||||||
export default class DiaryActionIcon extends Component {
|
|
||||||
|
|
||||||
_defaultOnPress() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<TouchableOpacity onPress={
|
|
||||||
this.props.onPress ? this.props.onPress : this._defaultOnPress.bind(this)
|
|
||||||
}>
|
|
||||||
<Ionicons name="ios-more"
|
|
||||||
size={24}
|
|
||||||
color={Color.inactiveText}
|
|
||||||
style={localStyle.moreIcon} />
|
|
||||||
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const localStyle = StyleSheet.create({
|
|
||||||
moreIcon: {
|
|
||||||
paddingVertical: 5,
|
|
||||||
paddingHorizontal: 5
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,14 +1,12 @@
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {StyleSheet, Text, View} from 'react-native';
|
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native';
|
||||||
|
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
import Color from '../../style/color';
|
import Color from '../../style/color';
|
||||||
import UserIcon from '../userIcon';
|
import UserIcon from '../userIcon';
|
||||||
import Photo from '../photo';
|
import Photo from '../photo';
|
||||||
|
|
||||||
import CommentIcon from '../comment/commentIcon';
|
|
||||||
import DiaryActionIcon from './diaryActionIcon';
|
|
||||||
|
|
||||||
|
|
||||||
export default class DiaryBrief extends Component {
|
export default class DiaryBrief extends Component {
|
||||||
|
|
||||||
|
@ -70,14 +68,22 @@ export default class DiaryBrief extends Component {
|
||||||
<View style={localStyle.actionBar}>
|
<View style={localStyle.actionBar}>
|
||||||
{
|
{
|
||||||
diary.comment_count > 0
|
diary.comment_count > 0
|
||||||
? <CommentIcon count={diary.comment_count}></CommentIcon>
|
? <View style={localStyle.commentIconBox}>
|
||||||
|
<Ionicons name="ios-text-outline" size={18}
|
||||||
|
color={Color.inactiveText}
|
||||||
|
style={localStyle.buttonIcon} />
|
||||||
|
<Text style={localStyle.commentIconText}>{diary.comment_count}</Text>
|
||||||
|
</View>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
<View style={{flex: 1}} />
|
<View style={{flex: 1}} />
|
||||||
{
|
{
|
||||||
this.editable
|
this.editable
|
||||||
? <DiaryActionIcon diaryId={diary.id}
|
? <TouchableOpacity onPress={this.props.onDiaryAction}>
|
||||||
onPress={this.props.onDiaryAction}></DiaryActionIcon>
|
<Ionicons name="ios-more" size={24}
|
||||||
|
color={Color.inactiveText}
|
||||||
|
style={localStyle.moreIcon} />
|
||||||
|
</TouchableOpacity>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
</View>
|
</View>
|
||||||
|
@ -130,5 +136,20 @@ const localStyle = StyleSheet.create({
|
||||||
height: 30,
|
height: 30,
|
||||||
marginTop: 10,
|
marginTop: 10,
|
||||||
justifyContent: 'space-between'
|
justifyContent: 'space-between'
|
||||||
|
},
|
||||||
|
moreIcon: {
|
||||||
|
paddingVertical: 5,
|
||||||
|
paddingHorizontal: 5
|
||||||
|
},
|
||||||
|
commentIconBox: {
|
||||||
|
flexDirection: "row"
|
||||||
|
},
|
||||||
|
buttonIcon: {
|
||||||
|
marginRight: 8,
|
||||||
|
marginLeft: 2
|
||||||
|
},
|
||||||
|
commentIconIext: {
|
||||||
|
fontSize: 15,
|
||||||
|
color: Color.inactiveText
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -109,6 +109,8 @@ export default class DiaryFull extends Component {
|
||||||
<CommentList ref={(r) => this.commentList = r}
|
<CommentList ref={(r) => this.commentList = r}
|
||||||
diaryId={diary.id}
|
diaryId={diary.id}
|
||||||
editable={this.state.editable}
|
editable={this.state.editable}
|
||||||
|
onUserIconPress={this._onUserIconPress.bind(this)}
|
||||||
|
{...this.props}
|
||||||
></CommentList>
|
></CommentList>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -17,7 +17,12 @@ import Msg from '../../util/msg';
|
||||||
import Api from '../../util/api';
|
import Api from '../../util/api';
|
||||||
|
|
||||||
import Touchable from '../touchable';
|
import Touchable from '../touchable';
|
||||||
import ListFooter from '../listFooter';
|
import {
|
||||||
|
ListFooterLoading,
|
||||||
|
ListFooterEnd,
|
||||||
|
ListFooterFailed
|
||||||
|
} from '../listFooter';
|
||||||
|
import {ListEmptyRefreshable} from '../listEmpty';
|
||||||
import DiaryBrief from './diaryBrief';
|
import DiaryBrief from './diaryBrief';
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +35,7 @@ export default class DiaryList extends Component {
|
||||||
this.dataSource = props.dataSource;
|
this.dataSource = props.dataSource;
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
mounting: true,
|
||||||
diaries: [],
|
diaries: [],
|
||||||
|
|
||||||
refreshing: false,
|
refreshing: false,
|
||||||
|
@ -91,7 +97,6 @@ export default class DiaryList extends Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// to be seperated as diaryAction component
|
|
||||||
_onDiaryAction(diary) {
|
_onDiaryAction(diary) {
|
||||||
ActionSheet.showActionSheetWithOptions({
|
ActionSheet.showActionSheetWithOptions({
|
||||||
options:['修改','删除', '取消'],
|
options:['修改','删除', '取消'],
|
||||||
|
@ -113,10 +118,7 @@ export default class DiaryList extends Component {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
passProps: {
|
passProps: {
|
||||||
diary: diary,
|
diary: diary
|
||||||
onSave: (diary) => {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -152,11 +154,11 @@ export default class DiaryList extends Component {
|
||||||
url: photoUrl
|
url: photoUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async refresh() {
|
async refresh() {
|
||||||
if (this.state.refreshing) {
|
if(this.state.refreshing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,14 +171,6 @@ export default class DiaryList extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
let diaries = this.state.diaries;
|
|
||||||
let newDiaries = result.list;
|
|
||||||
if (diaries.length > 0 && newDiaries.length > 0
|
|
||||||
&& diaries[0].id === newDiaries[0].id) {
|
|
||||||
|
|
||||||
Msg.showMsg('没有新内容');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
diaries: result.list ? result.list : [],
|
diaries: result.list ? result.list : [],
|
||||||
hasMore: result.more,
|
hasMore: result.more,
|
||||||
|
@ -191,6 +185,7 @@ export default class DiaryList extends Component {
|
||||||
|
|
||||||
}).done(() => {
|
}).done(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
mounting: false,
|
||||||
refreshing: false
|
refreshing: false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -231,6 +226,20 @@ export default class DiaryList extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
if(!this.state.mounting && (!this.state.diaries || this.state.diaries.length == 0)) {
|
||||||
|
let message = this.editable
|
||||||
|
? '今天还没有写日记,马上写一篇吧'
|
||||||
|
: '今天还没有人写日记';
|
||||||
|
return (
|
||||||
|
<ListEmptyRefreshable
|
||||||
|
error={this.state.refreshFailed}
|
||||||
|
message={message}
|
||||||
|
onPress={this.refresh.bind(this)}
|
||||||
|
|
||||||
|
></ListEmptyRefreshable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={localStyle.container}>
|
<View style={localStyle.container}>
|
||||||
<FlatList style={localStyle.list}
|
<FlatList style={localStyle.list}
|
||||||
|
@ -266,14 +275,14 @@ export default class DiaryList extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.loadFailed) {
|
if (this.state.loadFailed) {
|
||||||
return ListFooter.renderFooterFailed(this.loadMore.bind(this));
|
return <ListFooterFailed refresh={this.loadMore.bind(this)}></ListFooterFailed>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.state.hasMore) {
|
if (!this.state.hasMore) {
|
||||||
return ListFooter.renderFooterEnd();
|
return <ListFooterEnd></ListFooterEnd>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListFooter.renderFooterLoading();
|
return <ListFooterLoading></ListFooterLoading>;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
refreshing={this.state.refreshing}
|
refreshing={this.state.refreshing}
|
||||||
|
|
|
@ -7,7 +7,11 @@ import Touchable from '../touchable';
|
||||||
import Color from '../../style/color';
|
import Color from '../../style/color';
|
||||||
|
|
||||||
import UserIcon from '../userIcon';
|
import UserIcon from '../userIcon';
|
||||||
import ListFooter from '../listFooter';
|
import {
|
||||||
|
ListFooterLoading,
|
||||||
|
ListFooterEnd,
|
||||||
|
ListFooterFailed
|
||||||
|
} from '../listFooter';
|
||||||
|
|
||||||
|
|
||||||
export default class FollowUserList extends Component {
|
export default class FollowUserList extends Component {
|
||||||
|
@ -157,7 +161,7 @@ export default class FollowUserList extends Component {
|
||||||
return (
|
return (
|
||||||
<Touchable key={item.id} onPress={() => this._onItemPress(item)}>
|
<Touchable key={item.id} onPress={() => this._onItemPress(item)}>
|
||||||
<View style={localStyle.box}>
|
<View style={localStyle.box}>
|
||||||
<UserIcon iconUrl={item.iconUrl}></UserIcon>
|
<UserIcon iconUrl={item.iconUrl} onPress={() => this._onItemPress(item)}></UserIcon>
|
||||||
<Text style={localStyle.userName}>{item.name}</Text>
|
<Text style={localStyle.userName}>{item.name}</Text>
|
||||||
<Touchable onPress={() => this._onDeletePress(item)}>
|
<Touchable onPress={() => this._onDeletePress(item)}>
|
||||||
<Ionicons name="md-close" size={20}
|
<Ionicons name="md-close" size={20}
|
||||||
|
@ -175,14 +179,14 @@ export default class FollowUserList extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.loadFailed) {
|
if (this.state.loadFailed) {
|
||||||
return ListFooter.renderFooterFailed(this.loadMore.bind(this));
|
return <ListFooterFailed refresh={this.loadMore.bind(this)}></ListFooterFailed>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.state.hasMore) {
|
if (!this.state.hasMore) {
|
||||||
return ListFooter.renderFooterEnd();
|
return <ListFooterEnd></ListFooterEnd>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListFooter.renderFooterLoading();
|
return <ListFooterLoading></ListFooterLoading>;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
refreshing={this.state.refreshing}
|
refreshing={this.state.refreshing}
|
||||||
|
|
|
@ -3,11 +3,9 @@ import ImagePicker from 'react-native-image-crop-picker'
|
||||||
import ImageResizer from 'react-native-image-resizer'
|
import ImageResizer from 'react-native-image-resizer'
|
||||||
|
|
||||||
|
|
||||||
async function resize(uri, oWidth, oHeight) {
|
async function resize(uri, oWidth, oHeight, maxPixel) {
|
||||||
let width = oWidth;
|
let width = oWidth;
|
||||||
let height = oHeight;
|
let height = oHeight;
|
||||||
|
|
||||||
let maxPixel = 640 * 640;
|
|
||||||
let oPixel = oWidth * oHeight;
|
let oPixel = oWidth * oHeight;
|
||||||
|
|
||||||
if(oPixel > maxPixel) {
|
if(oPixel > maxPixel) {
|
||||||
|
@ -15,11 +13,11 @@ async function resize(uri, oWidth, oHeight) {
|
||||||
height = Math.sqrt(oHeight * maxPixel / oWidth);
|
height = Math.sqrt(oHeight * maxPixel / oWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newUri = await ImageResizer.createResizedImage(uri, width, height, 'JPEG', 75);
|
const newUri = await ImageResizer.createResizedImage(uri, width, height);
|
||||||
return 'file://' + newUri.uri;
|
return 'file://' + newUri.uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
function action(imageOption, callback) {
|
function action(imageOption, maxSize, maxPixel, callback) {
|
||||||
ActionSheet.showActionSheetWithOptions({
|
ActionSheet.showActionSheetWithOptions({
|
||||||
options: ['拍照', '从相册选择', '取消'],
|
options: ['拍照', '从相册选择', '取消'],
|
||||||
cancelButtonIndex: 2,
|
cancelButtonIndex: 2,
|
||||||
|
@ -37,13 +35,19 @@ function action(imageOption, callback) {
|
||||||
: ImagePicker.openPicker(imageOption)
|
: ImagePicker.openPicker(imageOption)
|
||||||
)
|
)
|
||||||
.then(async (image) => {
|
.then(async (image) => {
|
||||||
let imageUri = await resize(image.path, image.width, image.height);
|
let imageUri = image.path;
|
||||||
if(typeof callback == 'function') {
|
if(image.size > maxSize) {
|
||||||
callback(imageUri);
|
imageUri = await resize(image.path, image.width, image.height, maxPixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callback(null, imageUri);
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
//
|
if(e.message === "User cancelled image selection") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(e);
|
||||||
})
|
})
|
||||||
.done();
|
.done();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {StyleSheet, Text, View} from 'react-native';
|
||||||
|
import {Button} from 'react-native-elements'
|
||||||
|
|
||||||
|
import Color from '../style/color';
|
||||||
|
|
||||||
|
|
||||||
|
const ListEmptyRefreshable = (props) => {
|
||||||
|
let text = props.error ? '出错了 :(' : props.message;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={localStyle.container}>
|
||||||
|
<Text style={localStyle.text}>{text}</Text>
|
||||||
|
<Button fontSize={14} borderRadius={999} backgroundColor={Color.primary}
|
||||||
|
title={'刷新一下'}
|
||||||
|
onPress={() => props.onPress ? props.onPress() : null} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const localStyle = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
alignItems:'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
height: '100%'
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
paddingBottom: 15,
|
||||||
|
color: Color.text
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export {
|
||||||
|
ListEmptyRefreshable
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ const localStyle = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function renderFooterLoading() {
|
const ListFooterLoading = () => {
|
||||||
return (
|
return (
|
||||||
<View style={localStyle.footer}>
|
<View style={localStyle.footer}>
|
||||||
<ActivityIndicator animating={true} color={Color.primary}
|
<ActivityIndicator animating={true} color={Color.primary}
|
||||||
|
@ -29,7 +29,7 @@ function renderFooterLoading() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderFooterEnd() {
|
const ListFooterEnd = () => {
|
||||||
return (
|
return (
|
||||||
<View style={localStyle.footer}>
|
<View style={localStyle.footer}>
|
||||||
<Text style={{color: Color.inactiveText, fontSize: 12}}>
|
<Text style={{color: Color.inactiveText, fontSize: 12}}>
|
||||||
|
@ -39,15 +39,15 @@ function renderFooterEnd() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderFooterFailed(refresh) {
|
const ListFooterFailed = (props) => {
|
||||||
let isRefreshable = refresh && typeof refresh == 'function';
|
let isRefreshable = props.refresh ? true : false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={localStyle.footer}>
|
<View style={localStyle.footer}>
|
||||||
<TouchableOpacity style={{marginTop: 15}}
|
<TouchableOpacity style={{marginTop: 15}}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if(isRefreshable) {
|
if(isRefreshable) {
|
||||||
refresh();
|
props.refresh();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -60,9 +60,9 @@ function renderFooterFailed(refresh) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export {
|
||||||
renderFooterLoading,
|
ListFooterLoading,
|
||||||
renderFooterEnd,
|
ListFooterEnd,
|
||||||
renderFooterFailed
|
ListFooterFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,12 @@ import Color from '../../style/color';
|
||||||
import Touchable from '../touchable';
|
import Touchable from '../touchable';
|
||||||
|
|
||||||
import DiaryBrief from '../diary/diaryBrief';
|
import DiaryBrief from '../diary/diaryBrief';
|
||||||
import ListFooter from '../listFooter';
|
|
||||||
import NotebookDiaryData from '../../dataLoader/notebookDiaryData';
|
import NotebookDiaryData from '../../dataLoader/notebookDiaryData';
|
||||||
|
import {
|
||||||
|
ListFooterLoading,
|
||||||
|
ListFooterEnd,
|
||||||
|
ListFooterFailed
|
||||||
|
} from '../listFooter';
|
||||||
|
|
||||||
|
|
||||||
export default class NotebookDiaryList extends Component {
|
export default class NotebookDiaryList extends Component {
|
||||||
|
@ -200,14 +204,14 @@ export default class NotebookDiaryList extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.loadFailed) {
|
if (this.state.loadFailed) {
|
||||||
return ListFooter.renderFooterFailed(this.loadMore.bind(this));
|
return <ListFooterFailed refresh={this.loadMore.bind(this)}></ListFooterFailed>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.state.hasMore) {
|
if (!this.state.hasMore) {
|
||||||
return ListFooter.renderFooterEnd();
|
return <ListFooterEnd></ListFooterEnd>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListFooter.renderFooterLoading();
|
return <ListFooterLoading></ListFooterLoading>;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
ItemSeparatorComponent={(sectionID, rowID, adjacentRowHighlighted) =>
|
ItemSeparatorComponent={(sectionID, rowID, adjacentRowHighlighted) =>
|
||||||
|
|
|
@ -78,24 +78,7 @@ export default class DiaryDetailPage extends Component {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if(!this.state.diary && this.state.diaryId) {
|
if(!this.state.diary && this.state.diaryId) {
|
||||||
Api.getDiary(this.state.diaryId)
|
this.refreshDiary();
|
||||||
.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()
|
Api.getSelfInfoByStore()
|
||||||
|
@ -106,7 +89,11 @@ export default class DiaryDetailPage extends Component {
|
||||||
|
|
||||||
}).done();
|
}).done();
|
||||||
|
|
||||||
this.listener = DeviceEventEmitter.addListener(Event.updateComments, (param) => {
|
this.diaryListener = DeviceEventEmitter.addListener(Event.updateDiarys, (param) => {
|
||||||
|
this.refreshDiary();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.commentListener = DeviceEventEmitter.addListener(Event.updateComments, (param) => {
|
||||||
this.setState({needScrollToBottom: true});
|
this.setState({needScrollToBottom: true});
|
||||||
this.diaryFull.refreshComment();
|
this.diaryFull.refreshComment();
|
||||||
Keyboard.dismiss();
|
Keyboard.dismiss();
|
||||||
|
@ -114,7 +101,33 @@ export default class DiaryDetailPage extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount(){
|
componentWillUnmount(){
|
||||||
this.listener.remove();
|
this.diaryListener.remove();
|
||||||
|
this.commentListener.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshDiary() {
|
||||||
|
let diaryId = this.state.diaryId;
|
||||||
|
if(!diaryId) {
|
||||||
|
diaryId = this.state.diary.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
Api.getDiary(diaryId)
|
||||||
|
.then(result => {
|
||||||
|
if(!result) {
|
||||||
|
throw {
|
||||||
|
message: 'get diary no result'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
diary: result
|
||||||
|
}, () => {
|
||||||
|
this.diaryFull.refreshDiaryContent();
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.done(() => {
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -126,8 +126,7 @@ export default class NotebookEditPage extends Component {
|
||||||
Msg.showMsg('封面保存成功');
|
Msg.showMsg('封面保存成功');
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
// Msg.showMsg('封面保存失败:' + e.message);
|
Msg.showMsg('封面保存失败');
|
||||||
Alert.alert('封面保存失败:' + e.message);
|
|
||||||
})
|
})
|
||||||
.done(() => {
|
.done(() => {
|
||||||
this.setState({uploading: false});
|
this.setState({uploading: false});
|
||||||
|
@ -139,7 +138,15 @@ export default class NotebookEditPage extends Component {
|
||||||
width: 640,
|
width: 640,
|
||||||
height: 480,
|
height: 480,
|
||||||
cropping: true
|
cropping: true
|
||||||
}, this.uploadCover.bind(this));
|
|
||||||
|
}, -1, 600*600, (e, imageUri) => {
|
||||||
|
|
||||||
|
if(e) {
|
||||||
|
Msg.showMsg('操作失败');
|
||||||
|
} else {
|
||||||
|
this.uploadCover(imageUri);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDelete() {
|
_onDelete() {
|
||||||
|
|
|
@ -6,6 +6,8 @@ import {Navigation} from 'react-native-navigation';
|
||||||
import Color from '../style/color'
|
import Color from '../style/color'
|
||||||
import {Icon} from '../style/icon'
|
import {Icon} from '../style/icon'
|
||||||
|
|
||||||
|
import {ListEmptyRefreshable} from '../component/listEmpty'
|
||||||
|
|
||||||
|
|
||||||
export default class NotificationPage extends Component {
|
export default class NotificationPage extends Component {
|
||||||
|
|
||||||
|
@ -24,7 +26,7 @@ export default class NotificationPage extends Component {
|
||||||
id: 'history',
|
id: 'history',
|
||||||
icon: Icon.navButtonTime,
|
icon: Icon.navButtonTime,
|
||||||
|
|
||||||
color: '#aaa' // android
|
color: Color.primary // android
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -39,13 +41,9 @@ export default class NotificationPage extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<View style={localStyle.container}>
|
<ListEmptyRefreshable message={'没有提醒:)'}></ListEmptyRefreshable>
|
||||||
<Text style={localStyle.text}>没有内容</Text>
|
);
|
||||||
<Button fontSize={14} borderRadius={999} backgroundColor={Color.primary}
|
|
||||||
title={'刷新'} onPress={() => {}} />
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@ import {
|
||||||
Easing,
|
Easing,
|
||||||
TouchableWithoutFeedback,
|
TouchableWithoutFeedback,
|
||||||
DeviceEventEmitter,
|
DeviceEventEmitter,
|
||||||
Alert
|
Alert,
|
||||||
|
Image
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import {Navigation} from 'react-native-navigation';
|
import {Navigation} from 'react-native-navigation';
|
||||||
import KeyboardSpacer from "react-native-keyboard-spacer";
|
import KeyboardSpacer from "react-native-keyboard-spacer";
|
||||||
|
@ -26,6 +27,7 @@ import Token from '../util/token'
|
||||||
import Event from "../util/event";
|
import Event from "../util/event";
|
||||||
|
|
||||||
import NotebookLine from '../component/notebook/notebookLine';
|
import NotebookLine from '../component/notebook/notebookLine';
|
||||||
|
import ImageAction from '../component/image/imageAction'
|
||||||
|
|
||||||
|
|
||||||
export default class WritePage extends Component {
|
export default class WritePage extends Component {
|
||||||
|
@ -42,6 +44,8 @@ export default class WritePage extends Component {
|
||||||
targetbookSubject: diary ? diary.notebook_subject : '',
|
targetbookSubject: diary ? diary.notebook_subject : '',
|
||||||
|
|
||||||
content: diary ? diary.content : '',
|
content: diary ? diary.content : '',
|
||||||
|
photoSource: null,
|
||||||
|
photoUri: null,
|
||||||
|
|
||||||
modalVisible: false,
|
modalVisible: false,
|
||||||
fadeAnimOpacity: new Animated.Value(0),
|
fadeAnimOpacity: new Animated.Value(0),
|
||||||
|
@ -189,19 +193,64 @@ export default class WritePage extends Component {
|
||||||
}).done();
|
}).done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onPickPhoto() {
|
||||||
|
if(this.state.photoUri != null) {
|
||||||
|
ActionSheet.showActionSheetWithOptions({
|
||||||
|
options: ['预览照片', '删除照片', '取消'],
|
||||||
|
destructiveButtonIndex: 1,
|
||||||
|
cancelButtonIndex: 2
|
||||||
|
|
||||||
|
}, (index) => {
|
||||||
|
if(index == 0) {
|
||||||
|
Navigation.push(this.props.componentId, {
|
||||||
|
component: {
|
||||||
|
name: 'Photo',
|
||||||
|
passProps: {
|
||||||
|
url: this.state.photoUri
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} else if(index == 1) {
|
||||||
|
this.setState({
|
||||||
|
photoSource: null,
|
||||||
|
photoUri: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ImageAction.action({
|
||||||
|
cropping: false,
|
||||||
|
mediaType: 'photo'
|
||||||
|
|
||||||
|
}, 1024 * 1024 * 2, 2560 * 1920, (e, imageUri) => {
|
||||||
|
if(e) {
|
||||||
|
Msg.showMsg('操作失败');
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
photoSource: {
|
||||||
|
uri: imageUri,
|
||||||
|
isStatic: true
|
||||||
|
},
|
||||||
|
photoUri: imageUri
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
saveDiary() {
|
saveDiary() {
|
||||||
let photoUri = null;
|
let photoUri = this.state.photoUri;
|
||||||
let topic = this.props.topic ? 1 : 0;
|
let topic = this.props.topic ? 1 : 0;
|
||||||
|
|
||||||
(this.diary
|
(this.diary
|
||||||
? Api.updateDiary(this.diary.id, this.state.targetbookId, this.state.content)
|
? Api.updateDiary(this.diary.id, this.state.targetbookId, this.state.content)
|
||||||
: Api.addDiary(this.state.targetbookId, this.state.content, null, topic)
|
: Api.addDiary(this.state.targetbookId, this.state.content, photoUri, topic)
|
||||||
).then(result => {
|
).then(result => {
|
||||||
Msg.showMsg('日记保存完成');
|
Msg.showMsg('日记保存完成');
|
||||||
DeviceEventEmitter.emit(Event.updateDiarys);
|
DeviceEventEmitter.emit(Event.updateDiarys);
|
||||||
|
|
||||||
this.props.onSave(result);
|
|
||||||
|
|
||||||
if(this.diary) {
|
if(this.diary) {
|
||||||
Navigation.pop(this.props.componentId);
|
Navigation.pop(this.props.componentId);
|
||||||
|
|
||||||
|
@ -220,7 +269,6 @@ export default class WritePage extends Component {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
Msg.showMsg('保存失败');
|
Msg.showMsg('保存失败');
|
||||||
|
@ -266,10 +314,8 @@ export default class WritePage extends Component {
|
||||||
|
|
||||||
<View style={{flex: 1}} />
|
<View style={{flex: 1}} />
|
||||||
|
|
||||||
<TouchableOpacity style={localStyle.photo} onPress={() => {}}>
|
{this.renderPhotoButton()}
|
||||||
<Ionicons name="ios-image-outline" size={30}
|
|
||||||
style={{paddingTop: 4}} color={Color.light} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -282,6 +328,23 @@ export default class WritePage extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderPhotoButton() {
|
||||||
|
if(this.diary) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = !this.state.photoSource
|
||||||
|
? (<Ionicons name="ios-image-outline" size={30} style={{paddingTop: 4}} color={Color.light} />)
|
||||||
|
: (<Image source={this.state.photoSource} style={{width: 30, height: 30, borderRadius: 3}} />);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity style={localStyle.photo}
|
||||||
|
onPress={this._onPickPhoto.bind(this)}>
|
||||||
|
{content}
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderModal() {
|
renderModal() {
|
||||||
return (
|
return (
|
||||||
<Modal animationType='none' transparent={true}
|
<Modal animationType='none' transparent={true}
|
||||||
|
|
Loading…
Reference in a new issue