1. 评论,评论列表组件

2. 日记详情页初步成形
This commit is contained in:
xuwenyang 2019-05-10 20:42:14 +08:00
parent 5f29da8612
commit 5930b52474
12 changed files with 302 additions and 49 deletions

View file

@ -3,13 +3,13 @@
*/ */
import {Navigation} from 'react-native-navigation'; import {Navigation} from 'react-native-navigation';
import {Icon, loadIcon} from './src/style/icon' import {Icon, loadIcon} from './src/style/icon';
import App from './App'; import App from './App';
import Token from './src/util/token' import Token from './src/util/token';
import PageList from './src/page/_list' import PageList from './src/page/_list';
import BottomNav from './src/nav/bottomNav' import BottomNav from './src/nav/bottomNav';
async function init() { async function init() {

View file

@ -0,0 +1,95 @@
import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';
import moment from 'moment';
import Color from '../../style/color';
import UserIcon from '../userIcon';
import CommentActionIcon from './commentActionIcon';
export default class Comment extends Component {
render() {
let comment = this.props.comment;
let user = comment.user;
let editable = this.props.editable || true;
return (
<View>
<View style={localStyle.box}>
<UserIcon iconUrl={user.iconUrl}></UserIcon>
<View style={localStyle.body}>
<View style={localStyle.title}>
<Text style={localStyle.titleName}>{user.name}</Text>
<Text style={[localStyle.titleText]}>{moment(comment.created).format('H:mm')}</Text>
</View>
{
comment.recipient == null
? <Text style={localStyle.content}>{comment.content}</Text>
: (
<Text style={localStyle.content}>
<Text style={{color: Color.primary}}>@{comment.recipient.name} </Text>
{comment.content}
</Text>
)
}
</View>
</View>
{
editable
? <CommentActionIcon></CommentActionIcon>
: null
}
<View style={localStyle.line}/>
</View>
);
}
}
const localStyle = StyleSheet.create({
box: {
paddingVertical: 15,
paddingHorizontal: 15,
flexDirection: 'row'
},
body: {
flexDirection: 'column',
flexGrow: 1,
flexShrink: 1,
paddingTop: 2
},
title: {
flexDirection: 'row',
paddingBottom: 5,
alignItems: 'flex-end'
},
titleName: {
flexGrow: 1,
fontWeight: 'bold',
color: Color.text,
fontSize: 14,
marginRight: 5
},
titleText: {
fontSize: 12,
color: Color.inactiveText
},
content: {
flexGrow: 1,
lineHeight: 26,
color: Color.text,
fontSize: 15,
marginBottom: 10
},
line: {
height: StyleSheet.hairlineWidth,
backgroundColor: Color.line,
marginHorizontal: 16,
marginLeft: 56
}
});

View file

@ -0,0 +1,37 @@
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
}
});

View file

@ -0,0 +1,84 @@
import React, {Component} from 'react';
import {
InteractionManager,
ActivityIndicator,
StyleSheet,
FlatList,
Text, View
} from 'react-native';
import {Divider} from "react-native-elements";
import Touchable from '../touchable';
import Color from '../../style/color';
import Api from '../../util/api';
import Comment from './comment';
export default class CommentList extends Component {
constructor(props) {
super(props);
this.diaryId = props.diaryId;
this.state = {
comments: []
};
}
componentDidMount() {
InteractionManager.runAfterInteractions(() => {
this.loadMore();
});
}
async loadMore() {
console.log('commentList:', this.diaryId);
let comments = await Api.getDiaryComments(this.diaryId);
console.log('comments:', comments);
if(comments && comments.length > 0) {
if (comments.length > 1) {
comments = comments.reverse();
}
this.setState({
comments
});
}
}
render() {
return (
<View style={localStyle.container}>
<FlatList
data={this.state.comments}
keyExtractor={(item, index) => {
return item.id.toString()
}}
renderItem={({item}) => {
return (
<Touchable onPress={() => {}}>
<Comment comment={item}></Comment>
</Touchable>
)
}}
>
</FlatList>
</View>
);
}
}
const localStyle = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Color.navBackground,
justifyContent: 'space-between',
paddingBottom: Api.IS_IPHONEX ? 30 : 0
}
});

View file

@ -1,13 +1,13 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native'; import {StyleSheet, Text, View} from 'react-native';
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 CommentIcon from '../comment/commentIcon';
import DiaryActionIcon from './diaryActionIcon' import DiaryActionIcon from './diaryActionIcon';
export default class DiaryBrief extends Component { export default class DiaryBrief extends Component {

View file

@ -1,54 +1,68 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native'; import {Platform, StyleSheet, Text, View} from 'react-native';
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 CommentList from '../comment/commentList';
export default class DiaryFull extends Component { export default class DiaryFull extends Component {
render() { render() {
let diary = this.props.diary; let diary = this.props.diary;
let user = diary.user; let user = diary.user;
let editable = this.props.editable;
return ( return (
<View style={localStyle.box}> <View>
<UserIcon iconUrl={user.iconUrl}></UserIcon> <View style={localStyle.box}>
<View style={localStyle.body}> <UserIcon iconUrl={user.iconUrl}></UserIcon>
<View style={localStyle.title}> <View style={localStyle.body}>
<Text style={localStyle.titleName} numberOfLines={1}> <View style={localStyle.title}>
{user.name} <Text style={localStyle.titleName} numberOfLines={1}>
</Text> {user.name}
<Text style={[localStyle.titleText, {flex: 1}]} numberOfLines={1}> </Text>
{diary.notebook_subject} <Text style={[localStyle.titleText, {flex: 1}]} numberOfLines={1}>
</Text> {diary.notebook_subject}
<Text style={localStyle.titleText}> </Text>
{moment(diary.created).format('H:mm')} <Text style={localStyle.titleText}>
</Text> {moment(diary.created).format('H:mm')}
</Text>
</View>
<Text style={localStyle.content}>
{diary.content.trim()}
</Text>
<Photo uri={diary.photoThumbUrl}></Photo>
</View>
</View> </View>
<Text style={localStyle.content}> <CommentList diaryId={diary.id}></CommentList>
{diary.content}
</Text>
</View> </View>
</View> );
);
} }
} }
const localStyle = StyleSheet.create({ const localStyle = StyleSheet.create({
box: { box: {
flexDirection: "row", flexDirection: "row",
overflow: "hidden", overflow: "hidden",
paddingHorizontal: 15, paddingHorizontal: 15,
paddingTop: 15 paddingTop: 15,
marginBottom: 30
}, },
body: { body: {
flexDirection: "column", flexDirection: "column",
flexGrow: 1, flexGrow: 1,
flexShrink: 1, flexShrink: 1,
paddingTop: 2 paddingTop: 2,
paddingBottom: 5
}, },
title: { title: {
flexDirection: "row", flexDirection: "row",
@ -69,7 +83,6 @@ const localStyle = StyleSheet.create({
lineHeight: 24, lineHeight: 24,
color: Color.text, color: Color.text,
fontSize: 15, fontSize: 15,
textAlignVertical: 'bottom', textAlignVertical: 'bottom'
paddingBottom: 15
} }
}); });

View file

@ -8,12 +8,12 @@ import {
} from 'react-native'; } from 'react-native';
import {Divider} from "react-native-elements"; import {Divider} from "react-native-elements";
import Color from '../../style/color' import Color from '../../style/color';
import Msg from '../../util/msg' import Msg from '../../util/msg';
import Api from '../../util/api' import Api from '../../util/api';
import Touchable from '../touchable' import Touchable from '../touchable';
import DiaryBrief from './diaryBrief' import DiaryBrief from './diaryBrief';
export default class DiaryList extends Component { export default class DiaryList extends Component {
@ -34,7 +34,6 @@ export default class DiaryList extends Component {
} }
componentDidMount() { componentDidMount() {
console.log('diaryList mounted.');
InteractionManager.runAfterInteractions(() => { InteractionManager.runAfterInteractions(() => {
this.refresh(); this.refresh();
}); });
@ -101,13 +100,13 @@ export default class DiaryList extends Component {
} }
_onDiaryPress(diary) { _onDiaryPress(diary) {
/*
this.props.navigator.push({ this.props.navigator.push({
screen: 'DiaryDetail', screen: 'DiaryDetail',
title: '日记详情', title: '日记详情',
passProps: { diary: diary } passProps: { diary: diary }
}); });
*/
} }
render() { render() {

View file

@ -0,0 +1,21 @@
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, ScrollView} from 'react-native';
import Color from '../style/color';
import DiaryFull from '../component/diary/diaryFull';
export default class DiaryDetailPage extends Component {
render() {
return (
<ScrollView style={{flex: 1}}>
<DiaryFull diary={this.props.diary}></DiaryFull>
</ScrollView>
);
}
}
const localStyle = StyleSheet.create({
});

View file

@ -1,7 +1,7 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native'; import {StyleSheet, Text, View} from 'react-native';
import Api from '../util/api' import Api from '../util/api';
import DiaryList from '../component/diary/diaryList' import DiaryList from '../component/diary/diaryList'
import HomeListData from '../dataLoader/homeListData'; import HomeListData from '../dataLoader/homeListData';

View file

@ -1,4 +1,5 @@
export default { export default {
DiaryDetail: require("./DiaryDetailPage.js").default,
Follow: require("./FollowPage.js").default, Follow: require("./FollowPage.js").default,
Home: require("./HomePage.js").default, Home: require("./HomePage.js").default,
Notification: require("./NotificationPage.js").default, Notification: require("./NotificationPage.js").default,

View file

@ -64,7 +64,9 @@ async function getFollowDiaries(page = 1, page_size = 20, first_id = '') {
}); });
} }
async function getDiaryComments(diaryId) {
return call('GET', '/diaries/' + diaryId + '/comments')
}
async function call(method, api, body, _timeout = 10000) { async function call(method, api, body, _timeout = 10000) {
@ -154,5 +156,6 @@ export default {
login, login,
getTodayDiaries, getTodayDiaries,
getFollowDiaries getFollowDiaries,
getDiaryComments
} }