mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-24 22:03:21 +03:00
Merge pull request #79 from esteemapp/feature/postScreen
[Feature] Post Screen
This commit is contained in:
commit
f43675648c
@ -1,21 +1,27 @@
|
||||
import Card from './view/cardView';
|
||||
// import Card from './view/cardView';
|
||||
import Chip from './view/chipView';
|
||||
import GrayWrapper from './view/grayWrapperView';
|
||||
import LineBreak from './view/lineBreakView';
|
||||
import NoPost from './view/noPostView';
|
||||
import PostCardPlaceHolder from './view/postCardPlaceHolderView';
|
||||
import PostPlaceHolder from './view/postPlaceHolderView';
|
||||
import ProfileSummaryPlaceHolder from './view/profileSummaryPlaceHolder';
|
||||
import Tag from './view/tagView';
|
||||
import TextWithIcon from './view/textWithIconView';
|
||||
import WalletLineItem from './view/walletLineItemView';
|
||||
import Chip from './view/chipView';
|
||||
import ProfileSummaryPlaceHolder from './view/profileSummaryPlaceHolder';
|
||||
import StickyBar from './view/stickyBarView';
|
||||
|
||||
export {
|
||||
Card,
|
||||
GrayWrapper,
|
||||
// Card,
|
||||
StickyBar,
|
||||
Chip,
|
||||
GrayWrapper,
|
||||
LineBreak,
|
||||
NoPost,
|
||||
PostCardPlaceHolder,
|
||||
PostPlaceHolder,
|
||||
ProfileSummaryPlaceHolder,
|
||||
Tag,
|
||||
TextWithIcon,
|
||||
WalletLineItem,
|
||||
ProfileSummaryPlaceHolder,
|
||||
};
|
||||
|
@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import Placeholder from 'rn-placeholder';
|
||||
|
||||
import styles from './postCardPlaceHolderStyles';
|
||||
|
||||
const PostCardPlaceHolder = () => (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.textWrapper}>
|
||||
<Placeholder.Media size={25} hasRadius animate="fade" />
|
||||
<Placeholder.Line width="30%" lastLineWidth="30%" animate="fade" />
|
||||
</View>
|
||||
<Placeholder.Box animate="fade" height={200} width="100%" radius={5} />
|
||||
<View style={styles.paragraphWrapper}>
|
||||
<Placeholder.Paragraph
|
||||
lineNumber={3}
|
||||
textSize={16}
|
||||
lineSpacing={5}
|
||||
width="100%"
|
||||
lastLineWidth="70%"
|
||||
firstLineWidth="50%"
|
||||
animate="fade"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
export default PostCardPlaceHolder;
|
@ -2,18 +2,26 @@ import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import Placeholder from 'rn-placeholder';
|
||||
|
||||
import styles from './postPlaceHolderStyles';
|
||||
import styles from './postCardPlaceHolderStyles';
|
||||
|
||||
const PostPlaceHolder = () => (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.textWrapper}>
|
||||
<Placeholder.Media size={25} hasRadius animate="fade" />
|
||||
<Placeholder.Line width="30%" lastLineWidth="30%" animate="fade" />
|
||||
<View>
|
||||
<View style={styles.paragraphWrapper}>
|
||||
<Placeholder.Paragraph
|
||||
lineNumber={2}
|
||||
textSize={16}
|
||||
lineSpacing={5}
|
||||
width="100%"
|
||||
lastLineWidth="70%"
|
||||
firstLineWidth="50%"
|
||||
animate="fade"
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.paragraphWrapper} />
|
||||
<Placeholder.Box animate="fade" height={200} width="100%" radius={5} />
|
||||
<View style={styles.paragraphWrapper}>
|
||||
<Placeholder.Paragraph
|
||||
lineNumber={3}
|
||||
lineNumber={18}
|
||||
textSize={16}
|
||||
lineSpacing={5}
|
||||
width="100%"
|
||||
|
21
src/components/basicUIElements/view/stickyBarStyles.js
Normal file
21
src/components/basicUIElements/view/stickyBarStyles.js
Normal file
@ -0,0 +1,21 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: '$white',
|
||||
alignItems: 'center',
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'space-between',
|
||||
width: '$deviceWidth',
|
||||
height: 50,
|
||||
shadowOpacity: 0.2,
|
||||
shadowOffset: {
|
||||
height: 1.5,
|
||||
},
|
||||
},
|
||||
fixedFooter: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
},
|
||||
});
|
9
src/components/basicUIElements/view/stickyBarView.js
Normal file
9
src/components/basicUIElements/view/stickyBarView.js
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import styles from './stickyBarStyles';
|
||||
|
||||
const StickyBar = ({ children, isFixedFooter }) => (
|
||||
<View style={[styles.container, isFixedFooter && styles.fixedFooter]}>{children}</View>
|
||||
);
|
||||
|
||||
export default StickyBar;
|
19
src/components/basicUIElements/view/tagStyles.js
Normal file
19
src/components/basicUIElements/view/tagStyles.js
Normal file
@ -0,0 +1,19 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
text: {
|
||||
color: '$white',
|
||||
fontSize: 10,
|
||||
},
|
||||
isPin: {
|
||||
backgroundColor: '$primaryBlue',
|
||||
},
|
||||
textWrapper: {
|
||||
paddingHorizontal: 10,
|
||||
justifyContent: 'center',
|
||||
marginRight: 8,
|
||||
height: 15,
|
||||
backgroundColor: '$iconColor',
|
||||
borderRadius: 50,
|
||||
},
|
||||
});
|
15
src/components/basicUIElements/view/tagView.js
Normal file
15
src/components/basicUIElements/view/tagView.js
Normal file
@ -0,0 +1,15 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { Text, View, TouchableOpacity } from 'react-native';
|
||||
import styles from './tagStyles';
|
||||
|
||||
const Tag = ({ onPress, isPin, value }) => (
|
||||
<Fragment>
|
||||
<TouchableOpacity onPress={() => onPress && onPress(value)}>
|
||||
<View style={[styles.textWrapper, isPin && styles.isPin]}>
|
||||
<Text style={[styles.text]}>{value}</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
export default Tag;
|
@ -10,12 +10,13 @@ export default EStyleSheet.create({
|
||||
alignSelf: 'flex-start',
|
||||
},
|
||||
icon: {
|
||||
color: '#c1c5c7',
|
||||
color: '$iconColor',
|
||||
fontSize: 12,
|
||||
marginRight: 3,
|
||||
},
|
||||
text: {
|
||||
color: '#788187',
|
||||
color: '$primaryDarkGray',
|
||||
alignSelf: 'center',
|
||||
fontSize: 11,
|
||||
},
|
||||
});
|
||||
|
@ -1,22 +1,22 @@
|
||||
import React from 'react';
|
||||
import { View, TouchableHighlight, Text } from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import { Icon } from '../../icon';
|
||||
import styles from './textWithIconStyles';
|
||||
|
||||
const TextWithIcon = ({
|
||||
iconName, text, isClickable, onPress,
|
||||
iconName, text, isClickable, onPress, iconStyle, iconType,
|
||||
}) => (
|
||||
<View style={styles.container}>
|
||||
{isClickable || onPress ? (
|
||||
<TouchableHighlight underlayColor="transparent" onPress={() => onPress && onPress()}>
|
||||
<View style={styles.wrapper}>
|
||||
{text && <Ionicons style={styles.icon} name={iconName} />}
|
||||
<Text style={styles.text}>{text}</Text>
|
||||
<Icon style={[styles.icon, iconStyle]} name={iconName} iconType={iconType} />
|
||||
<Text style={[styles.text]}>{text}</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
) : (
|
||||
<View style={styles.wrapper}>
|
||||
{text && <Ionicons style={styles.icon} name={iconName} />}
|
||||
{text && <Icon style={[styles.icon, iconStyle]} name={iconName} iconType={iconType} />}
|
||||
<Text style={styles.text}>{text}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
65
src/components/comments/container/commentsContainer.js
Normal file
65
src/components/comments/container/commentsContainer.js
Normal file
@ -0,0 +1,65 @@
|
||||
import React, { Component } from 'react';
|
||||
import { getComments } from '../../../providers/steem/dsteem';
|
||||
|
||||
// Services and Actions
|
||||
|
||||
// Middleware
|
||||
|
||||
// Constants
|
||||
|
||||
// Utilities
|
||||
|
||||
// Component
|
||||
import { CommentsView } from '..';
|
||||
|
||||
/*
|
||||
* Props Name Description Value
|
||||
*@props --> props name here description here Value Type Here
|
||||
*
|
||||
*/
|
||||
|
||||
class CommentsContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
comments: [],
|
||||
};
|
||||
}
|
||||
|
||||
// Component Life Cycle Functions
|
||||
componentDidMount() {
|
||||
const { author, permlink } = this.props;
|
||||
|
||||
getComments(author, permlink)
|
||||
.then((comments) => {
|
||||
this.setState({
|
||||
comments,
|
||||
});
|
||||
console.log(comments);
|
||||
})
|
||||
.catch((error) => {
|
||||
alert(error);
|
||||
});
|
||||
}
|
||||
// Component Functions
|
||||
|
||||
_handleOnReplyPress = () => {
|
||||
alert(
|
||||
'Reply functions not working yet. Thank you for your understanding. Your friends at eSteem :)',
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { comments } = this.state;
|
||||
|
||||
return (
|
||||
<CommentsView
|
||||
handleOnReplyPress={this._handleOnReplyPress}
|
||||
comments={comments}
|
||||
{...this.props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CommentsContainer;
|
5
src/components/comments/index.js
Normal file
5
src/components/comments/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
import CommentsView from './view/commentsView';
|
||||
import Comments from './container/commentsContainer';
|
||||
|
||||
export { CommentsView, Comments };
|
||||
export default Comments;
|
8
src/components/comments/view/commentStyles.js
Normal file
8
src/components/comments/view/commentStyles.js
Normal file
@ -0,0 +1,8 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
text: {
|
||||
color: '$primaryBlack',
|
||||
fontSize: 10,
|
||||
},
|
||||
});
|
142
src/components/comments/view/commentsView.js
Normal file
142
src/components/comments/view/commentsView.js
Normal file
@ -0,0 +1,142 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { View, FlatList, Text } from 'react-native';
|
||||
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
import { Comments } from '..';
|
||||
import { PostBody, PostHeaderDescription } from '../../postElements';
|
||||
import { Upvote } from '../../upvote';
|
||||
import { IconButton } from '../../iconButton';
|
||||
|
||||
// Styles
|
||||
// import styles from './commentStyles';
|
||||
|
||||
class CommentsView extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_handleOnDropdownSelect = () => {};
|
||||
|
||||
_keyExtractor = (item, index) => item.permlink;
|
||||
|
||||
render() {
|
||||
const {
|
||||
comments,
|
||||
avatarSize,
|
||||
marginLeft,
|
||||
handleOnUserPress,
|
||||
currentUser,
|
||||
commentNumber,
|
||||
handleOnReplyPress,
|
||||
} = this.props;
|
||||
// commentNumber === 8 && alert('sekkiz:');
|
||||
return (
|
||||
<View>
|
||||
{!!comments && (
|
||||
<FlatList
|
||||
data={comments}
|
||||
keyExtractor={this._keyExtractor}
|
||||
renderItem={({ item, index }) => (
|
||||
<View key={index}>
|
||||
<PostHeaderDescription
|
||||
key={item.permlink}
|
||||
date={item.created}
|
||||
name={item.author}
|
||||
reputation={item.author_reputation}
|
||||
avatar={item.avatar}
|
||||
size={avatarSize || 24}
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
marginLeft: marginLeft || 35,
|
||||
flexDirection: 'column',
|
||||
marginTop: -10,
|
||||
}}
|
||||
>
|
||||
<PostBody isComment handleOnUserPress={handleOnUserPress} body={item.body} />
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
<Upvote isShowpayoutValue content={item} user={currentUser} isLoggedIn />
|
||||
<IconButton
|
||||
iconStyle={{ color: '#c1c5c7' }}
|
||||
style={{ marginLeft: 20 }}
|
||||
name="reply"
|
||||
onPress={() => handleOnReplyPress && handleOnReplyPress()}
|
||||
iconType="FontAwesome"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View style={{ marginLeft: marginLeft || 32 }}>
|
||||
{commentNumber !== 8 && (
|
||||
<Comments
|
||||
commentNumber={commentNumber ? commentNumber * 2 : 1}
|
||||
marginLeft={20}
|
||||
avatarSize={avatarSize || 16}
|
||||
author={item.author}
|
||||
permlink={item.permlink}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{/* {comments
|
||||
&& comments.map((comment, i) => (
|
||||
<View key={i}>
|
||||
<PostHeaderDescription
|
||||
key={item.permlink}
|
||||
date={item.created}
|
||||
name={item.author}
|
||||
reputation={item.author_reputation}
|
||||
avatar={item.avatar}
|
||||
size={avatarSize || 24}
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
marginLeft: marginLeft || 35,
|
||||
flexDirection: 'column',
|
||||
marginTop: -15,
|
||||
}}
|
||||
>
|
||||
<PostBody isComment handleOnUserPress={handleOnUserPress} body={item.body} />
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
<Upvote isShowpayoutValue content={comment} user={currentUser} isLoggedIn />
|
||||
<IconButton
|
||||
iconStyle={{ color: '#c1c5c7' }}
|
||||
style={{ marginLeft: 20 }}
|
||||
name="reply"
|
||||
onPress={() => handleOnReplyPress && handleOnReplyPress()}
|
||||
iconType="FontAwesome"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View style={{ marginLeft: marginLeft || 32 }}>
|
||||
{commentNumber !== 8 && (
|
||||
<Comments
|
||||
commentNumber={commentNumber ? commentNumber * 2 : 1}
|
||||
marginLeft={20}
|
||||
avatarSize={avatarSize || 16}
|
||||
author={item.author}
|
||||
permlink={item.permlink}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
))} */}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CommentsView;
|
@ -0,0 +1,25 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { CommentsDisplayView } from '..';
|
||||
|
||||
/*
|
||||
* Props Name Description Value
|
||||
*@props --> props name here description here Value Type Here
|
||||
*
|
||||
*/
|
||||
|
||||
class CommentsContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycle Functions
|
||||
// Component Functions
|
||||
|
||||
render() {
|
||||
return <CommentsDisplayView {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default CommentsContainer;
|
5
src/components/commentsDisplay/index.js
Normal file
5
src/components/commentsDisplay/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
import CommentsDisplayView from './view/commentsDisplayView';
|
||||
import CommentsDisplay from './container/commentsDisplayContainer';
|
||||
|
||||
export { CommentsDisplayView, CommentsDisplay };
|
||||
export default CommentsDisplay;
|
56
src/components/commentsDisplay/view/commentsDisplayView.js
Normal file
56
src/components/commentsDisplay/view/commentsDisplayView.js
Normal file
@ -0,0 +1,56 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { View } from 'react-native';
|
||||
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
import { FilterBar } from '../../filterBar';
|
||||
import { Comments } from '../../comments';
|
||||
|
||||
// Styles
|
||||
// import styles from './commentsDisplayStyles';
|
||||
|
||||
class CommentsDisplayView extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_handleOnDropdownSelect = () => {
|
||||
alert('This feature not read. Thanks for understanding.');
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
currentUser, author, permlink, commentCount,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{commentCount > 0 && (
|
||||
<Fragment>
|
||||
<FilterBar
|
||||
dropdownIconName="md-arrow-dropdown"
|
||||
options={['NEW COMMENTS', 'VOTES', 'REPLIES', 'MENTIONS', 'FOLLOWS', 'REBLOGS']}
|
||||
defaultText="NEW COMMENTS"
|
||||
onDropdownSelect={this._handleOnDropdownSelect}
|
||||
/>
|
||||
<View style={{ padding: 16 }}>
|
||||
<Comments currentUser={currentUser} author={author} permlink={permlink} />
|
||||
</View>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CommentsDisplayView;
|
@ -72,7 +72,7 @@ export default class TagAreaView extends Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { chipsData, isPreviewActive } = this.props;
|
||||
const { isPreviewActive } = this.props;
|
||||
const { chips } = this.state;
|
||||
|
||||
return (
|
||||
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
|
||||
// Constants
|
||||
import { default as ROUTES } from '../../../constants/routeNames';
|
||||
// import { default as ROUTES } from '../../../constants/routeNames';
|
||||
|
||||
// Components
|
||||
import { EditorHeaderView } from '..';
|
||||
@ -24,7 +24,7 @@ class EditorHeaderContainer extends Component {
|
||||
_handleOnPressBackButton = () => {
|
||||
const { navigation } = this.props;
|
||||
|
||||
navigation.navigate(ROUTES.SCREENS.HOME);
|
||||
navigation.goBack();
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -8,13 +8,18 @@ export default EStyleSheet.create({
|
||||
padding: 16,
|
||||
width: '$deviceWidth',
|
||||
backgroundColor: '$white',
|
||||
alignItems: 'center',
|
||||
},
|
||||
backIcon: {
|
||||
fontSize: 24,
|
||||
color: '$iconColor',
|
||||
},
|
||||
backWrapper: {
|
||||
flexGrow: 2,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
quickTitle: {
|
||||
flexGrow: 1,
|
||||
fontSize: 10,
|
||||
color: '$iconColor',
|
||||
marginLeft: 24,
|
||||
@ -40,4 +45,12 @@ export default EStyleSheet.create({
|
||||
textButtonWrapper: {
|
||||
justifyContent: 'center',
|
||||
},
|
||||
title: {
|
||||
color: '$iconColor',
|
||||
alignSelf: 'center',
|
||||
fontSize: 16,
|
||||
marginLeft: 16,
|
||||
flexGrow: 1,
|
||||
fontWeight: '500',
|
||||
},
|
||||
});
|
||||
|
@ -1,10 +1,11 @@
|
||||
import React, { Component } from 'react';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { View, SafeAreaView, Text } from 'react-native';
|
||||
import { TextButton } from '../..';
|
||||
import { IconButton } from '../../iconButton';
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
import { DropdownButton } from '../../dropdownButton';
|
||||
|
||||
// Styles
|
||||
import styles from './editorHeaderStyles';
|
||||
@ -33,6 +34,8 @@ class EditorHeaderView extends Component {
|
||||
}
|
||||
};
|
||||
|
||||
_handleOnDropdownSelect = () => {};
|
||||
|
||||
render() {
|
||||
const {
|
||||
handleOnPressBackButton,
|
||||
@ -40,39 +43,63 @@ class EditorHeaderView extends Component {
|
||||
isPreviewActive,
|
||||
quickTitle,
|
||||
isFormValid,
|
||||
title,
|
||||
isHasIcons,
|
||||
isHasDropdown,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<View style={styles.container}>
|
||||
<IconButton
|
||||
iconStyle={styles.backIcon}
|
||||
name="md-arrow-back"
|
||||
onPress={() => handleOnPressBackButton()}
|
||||
/>
|
||||
<Text style={styles.quickTitle}>{quickTitle}</Text>
|
||||
<IconButton
|
||||
style={styles.iconButton}
|
||||
iconStyle={styles.rightIcon}
|
||||
size={20}
|
||||
name="ios-timer"
|
||||
/>
|
||||
<IconButton
|
||||
style={styles.iconButton}
|
||||
size={25}
|
||||
onPress={() => handleOnPressPreviewButton()}
|
||||
iconStyle={styles.rightIcon}
|
||||
name={isPreviewActive ? 'ios-eye' : 'ios-eye-off'}
|
||||
/>
|
||||
<TextButton
|
||||
textStyle={[
|
||||
styles.textButton,
|
||||
isFormValid ? styles.textButtonEnable : styles.textButtonDisable,
|
||||
]}
|
||||
onPress={isFormValid && this._handleOnPress}
|
||||
style={styles.textButtonWrapper}
|
||||
text="Publish"
|
||||
/>
|
||||
<View style={styles.backWrapper}>
|
||||
<IconButton
|
||||
iconStyle={styles.backIcon}
|
||||
name="md-arrow-back"
|
||||
onPress={() => handleOnPressBackButton()}
|
||||
/>
|
||||
|
||||
<Text style={[title && styles.title, quickTitle && styles.quickTitle]}>
|
||||
{quickTitle || title}
|
||||
</Text>
|
||||
|
||||
{isHasDropdown && (
|
||||
<View>
|
||||
<DropdownButton
|
||||
isHasChildIcon
|
||||
iconName="md-more"
|
||||
options={['ALL ACTIVITIES', 'VOTES', 'REPLIES', 'MENTIONS', 'FOLLOWS', 'REBLOGS']}
|
||||
onSelect={this._handleOnDropdownSelect}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{isHasIcons && (
|
||||
<Fragment>
|
||||
<IconButton
|
||||
style={styles.iconButton}
|
||||
iconStyle={styles.rightIcon}
|
||||
size={20}
|
||||
name="ios-timer"
|
||||
/>
|
||||
<IconButton
|
||||
style={styles.iconButton}
|
||||
size={25}
|
||||
onPress={() => handleOnPressPreviewButton()}
|
||||
iconStyle={styles.rightIcon}
|
||||
name={isPreviewActive ? 'ios-eye' : 'ios-eye-off'}
|
||||
/>
|
||||
<TextButton
|
||||
textStyle={[
|
||||
styles.textButton,
|
||||
isFormValid ? styles.textButtonEnable : styles.textButtonDisable,
|
||||
]}
|
||||
onPress={isFormValid && this._handleOnPress}
|
||||
style={styles.textButtonWrapper}
|
||||
text="Publish"
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Logo from './logo/logo';
|
||||
import Comment from './comment/comment';
|
||||
// import Comment from './comment/comment';
|
||||
// import PostCard from "./postCard";
|
||||
import Reply from './reply/reply';
|
||||
// import Search from './search/search';
|
||||
@ -12,7 +12,7 @@ import Modal from './modal';
|
||||
|
||||
export {
|
||||
Logo,
|
||||
Comment,
|
||||
// Comment,
|
||||
// PostCard,
|
||||
Reply,
|
||||
// Search,
|
||||
|
@ -17,17 +17,6 @@ export default EStyleSheet.create({
|
||||
inlinePadding: {
|
||||
padding: 8,
|
||||
},
|
||||
editorButtons: {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: '$white',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
height: 50,
|
||||
shadowOpacity: 0.2,
|
||||
shadowOffset: {
|
||||
height: 1.5,
|
||||
},
|
||||
},
|
||||
leftButtonsWrapper: {
|
||||
marginLeft: 16,
|
||||
flexDirection: 'row',
|
||||
@ -41,14 +30,14 @@ export default EStyleSheet.create({
|
||||
},
|
||||
editorButton: {
|
||||
color: '$primaryDarkGray',
|
||||
paddingRight: 22,
|
||||
marginRight: 15,
|
||||
height: 24,
|
||||
},
|
||||
dropdownStyle: {
|
||||
marginRight: 8,
|
||||
},
|
||||
rightIcons: {
|
||||
paddingRight: 21,
|
||||
marginRight: 20,
|
||||
},
|
||||
dropdownIconStyle: {
|
||||
color: '$primaryDarkGray',
|
||||
|
@ -8,6 +8,7 @@ import { MarkdownView } from 'react-native-markdown-view';
|
||||
import Formats from './formats/formats';
|
||||
import { IconButton } from '../../iconButton';
|
||||
import { DropdownButton } from '../../dropdownButton';
|
||||
import { StickyBar } from '../../basicUIElements';
|
||||
|
||||
// Styles
|
||||
import styles from './markdownEditorStyles';
|
||||
@ -85,7 +86,7 @@ export default class MarkdownEditorView extends Component {
|
||||
);
|
||||
|
||||
_renderEditorButtons = ({ getState, setState }) => (
|
||||
<View style={styles.editorButtons}>
|
||||
<StickyBar>
|
||||
<View style={styles.leftButtonsWrapper}>
|
||||
<FlatList
|
||||
data={Formats}
|
||||
@ -111,7 +112,7 @@ export default class MarkdownEditorView extends Component {
|
||||
isHasChildIcon
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</StickyBar>
|
||||
);
|
||||
|
||||
render() {
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
Image, TouchableOpacity, FlatList,
|
||||
Image, TouchableOpacity, FlatList, View, Text,
|
||||
} from 'react-native';
|
||||
import {
|
||||
Card, CardItem, Left, Right, Thumbnail, View, Icon, Body, Text,
|
||||
Card, CardItem, Left, Right, Thumbnail, Icon, Body,
|
||||
} from 'native-base';
|
||||
import Modal from 'react-native-modal';
|
||||
import { PostHeaderDescription } from '../../postElements';
|
||||
|
||||
// STEEM
|
||||
import { Upvote } from '../../upvote';
|
||||
@ -43,14 +44,18 @@ class PostCard extends Component {
|
||||
const { handleOnUserPress, content, user } = this.props;
|
||||
|
||||
if (handleOnUserPress && content && content.author !== user.name) {
|
||||
handleOnUserPress(content.author);
|
||||
handleOnUserPress(content.author, content.author);
|
||||
}
|
||||
};
|
||||
|
||||
_handleOnContentPress = () => {
|
||||
const { handleOnContentPress, content } = this.props;
|
||||
|
||||
handleOnContentPress(content.author, content.permlink);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
content, isLoggedIn, user,
|
||||
} = this.props;
|
||||
const { content, isLoggedIn, user } = this.props;
|
||||
const { isModalVisible } = this.state;
|
||||
|
||||
// TODO: Should seperate bunch of component REFACTOR ME!
|
||||
@ -58,38 +63,26 @@ class PostCard extends Component {
|
||||
<Card style={styles.post}>
|
||||
<CardItem style={styles.header}>
|
||||
<Left>
|
||||
<TouchableOpacity onPress={() => this._handleOnUserPress()}>
|
||||
<Thumbnail style={styles.avatar} source={{ uri: content && content.avatar }} />
|
||||
</TouchableOpacity>
|
||||
<Body style={styles.body}>
|
||||
<View style={styles.author}>
|
||||
<TouchableOpacity
|
||||
onPress={() => this._handleOnUserPress()}
|
||||
>
|
||||
<Text style={styles.authorName}>{content.author}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.badge}>
|
||||
<Text style={styles.text}>{content.author_reputation}</Text>
|
||||
</View>
|
||||
<View style={styles.category}>
|
||||
<Text style={styles.categoryText}>{content.category}</Text>
|
||||
</View>
|
||||
<Text style={styles.timeAgo} note>
|
||||
{content.created}
|
||||
</Text>
|
||||
</Body>
|
||||
<PostHeaderDescription
|
||||
date={content.created}
|
||||
profileOnPress={this._handleOnUserPress}
|
||||
name={content.author}
|
||||
reputation={content.author_reputation}
|
||||
tag={content.category}
|
||||
avatar={content && content.avatar}
|
||||
size={32}
|
||||
/>
|
||||
</Left>
|
||||
<Right>
|
||||
<Icon name="md-more" />
|
||||
</Right>
|
||||
</CardItem>
|
||||
<Image
|
||||
source={{ uri: content && content.image }}
|
||||
defaultSource={require('../../../assets/no_image.png')}
|
||||
style={styles.image}
|
||||
/>
|
||||
<TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => this._handleOnContentPress()}>
|
||||
<Image
|
||||
source={{ uri: content && content.image }}
|
||||
defaultSource={require('../../../assets/no_image.png')}
|
||||
style={styles.image}
|
||||
/>
|
||||
<CardItem>
|
||||
<Body>
|
||||
<Text style={styles.title}>{content.title}</Text>
|
||||
|
56
src/components/postElements/body/view/bodyView.js
Normal file
56
src/components/postElements/body/view/bodyView.js
Normal file
@ -0,0 +1,56 @@
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
View, Text, TouchableOpacity, Dimensions,
|
||||
} from 'react-native';
|
||||
import HTML from 'react-native-html-renderer';
|
||||
// Components
|
||||
|
||||
// Styles
|
||||
import styles from './postBodyStyles';
|
||||
|
||||
// Constants
|
||||
const DEFAULT_IMAGE = require('../../../../assets/esteem.png');
|
||||
|
||||
class BodyView extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
alterNode(node) {
|
||||
if (node.name == 'img') {
|
||||
node.attribs.style = `max-width: ${Dimensions.get('window').width
|
||||
+ 10}px; left: -10px; width: 100% !important`;
|
||||
} else if (node.name == 'iframe') {
|
||||
node.attribs.style = `max-width: ${Dimensions.get('window').width}px; left: -10px`;
|
||||
node.attribs.height = 200;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { body } = this.props;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<HTML
|
||||
html={body}
|
||||
onLinkPress={(evt, href, hrefatr) => this.onLinkPress(evt, href, hrefatr)}
|
||||
containerStyle={{ padding: 10 }}
|
||||
textSelectable
|
||||
tagsStyles={styles}
|
||||
ignoredTags={['script']}
|
||||
debug={false}
|
||||
alterNode={(node) => {
|
||||
this.alterNode(node);
|
||||
}}
|
||||
imagesMaxWidth={Dimensions.get('window').width}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default BodyView;
|
20
src/components/postElements/body/view/postBodyStyles.js
Normal file
20
src/components/postElements/body/view/postBodyStyles.js
Normal file
@ -0,0 +1,20 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
text: {
|
||||
fontSize: 12,
|
||||
color: '$primaryBlack',
|
||||
fontFamily: '$primaryFont',
|
||||
},
|
||||
container: {
|
||||
paddingHorizontal: 0,
|
||||
marginTop: 12,
|
||||
},
|
||||
a: {
|
||||
color: '$primaryBlue',
|
||||
fontFamily: '$primaryFont',
|
||||
},
|
||||
img: {
|
||||
left: -16,
|
||||
},
|
||||
});
|
86
src/components/postElements/body/view/postBodyView.js
Normal file
86
src/components/postElements/body/view/postBodyView.js
Normal file
@ -0,0 +1,86 @@
|
||||
import React, { Component } from 'react';
|
||||
import { View, Dimensions, Linking } from 'react-native';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import HTML from 'react-native-html-renderer';
|
||||
// Styles
|
||||
import styles from './postBodyStyles';
|
||||
|
||||
// Constants
|
||||
import { default as ROUTES } from '../../../../constants/routeNames';
|
||||
// Components
|
||||
|
||||
const WIDTH = Dimensions.get('window').width;
|
||||
|
||||
class PostBody extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
// alterNode(node) {
|
||||
// // if (node.name === 'img') {
|
||||
// // node.attribs.style = `max-width: ${WIDTH + 16}px; left: -16px; width: 100% !important`;
|
||||
// // } else if (node.name == 'iframe') {
|
||||
// // node.attribs.style = `max-width: ${WIDTH}px; left: -20px`;
|
||||
// // node.attribs.height = 216;
|
||||
// // }
|
||||
// // if (node.name === 'a') {
|
||||
// // node.attribs.style = 'text-decoration: underline';
|
||||
// // }
|
||||
// }
|
||||
|
||||
_handleOnLinkPress = (evt, href, hrefatr) => {
|
||||
const { handleOnUserPress } = this.props;
|
||||
|
||||
if (hrefatr.class === 'markdown-author-link') {
|
||||
!handleOnUserPress ? this._handleOnUserPress(href) : handleOnUserPress(href);
|
||||
} else {
|
||||
Linking.canOpenURL(href).then((supported) => {
|
||||
if (supported) {
|
||||
Linking.openURL(href);
|
||||
} else {
|
||||
alert(`Field to open: ${href}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
_handleOnUserPress = (username) => {
|
||||
const { navigation } = this.props;
|
||||
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.PROFILE,
|
||||
params: {
|
||||
username,
|
||||
},
|
||||
key: username + Math.random() * 100,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { body, isComment } = this.props;
|
||||
const _initialDimensions = isComment ? {} : { width: WIDTH, height: 216 };
|
||||
|
||||
return (
|
||||
<View>
|
||||
<HTML
|
||||
html={body}
|
||||
onLinkPress={(evt, href, hrefatr) => this._handleOnLinkPress(evt, href, hrefatr)}
|
||||
containerStyle={isComment ? {} : styles.container}
|
||||
textSelectable
|
||||
tagsStyles={isComment ? {} : styles}
|
||||
ignoredTags={['script']}
|
||||
debug={false}
|
||||
imagesInitialDimensions={_initialDimensions}
|
||||
baseFontStyle={styles.text}
|
||||
imagesMaxWidth={isComment ? null : WIDTH}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withNavigation(PostBody);
|
@ -0,0 +1,72 @@
|
||||
import React, { Component } from 'react';
|
||||
import { View, Text, TouchableOpacity } from 'react-native';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
|
||||
import FastImage from 'react-native-fast-image';
|
||||
|
||||
// Components
|
||||
import { Tag } from '../../../basicUIElements';
|
||||
|
||||
// Styles
|
||||
import styles from './postHeaderDescriptionStyles';
|
||||
|
||||
import { default as ROUTES } from '../../../../constants/routeNames';
|
||||
|
||||
// Constants
|
||||
const DEFAULT_IMAGE = require('../../../../assets/esteem.png');
|
||||
|
||||
class PostHeaderDescription extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_handleOnUserPress = (username) => {
|
||||
const { navigation } = this.props;
|
||||
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.PROFILE,
|
||||
params: {
|
||||
username,
|
||||
},
|
||||
key: username + Math.random() * 100,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
date, avatar, name, reputation, size, tag, profileOnPress, tagOnPress,
|
||||
} = this.props;
|
||||
|
||||
const _reputationText = `(${reputation})`;
|
||||
const _avatar = avatar && { uri: avatar };
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<TouchableOpacity
|
||||
style={styles.avatarNameWrapper}
|
||||
onPress={() => (profileOnPress ? profileOnPress(name) : this._handleOnUserPress(name))}
|
||||
>
|
||||
<FastImage
|
||||
style={[styles.avatar, { width: size, height: size, borderRadius: size / 2 }]}
|
||||
source={_avatar}
|
||||
defaultSource={DEFAULT_IMAGE}
|
||||
/>
|
||||
<Text style={styles.name}>{name}</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={styles.reputation}>{_reputationText}</Text>
|
||||
{tag && (
|
||||
<TouchableOpacity onPress={() => tagOnPress && tagOnPress()}>
|
||||
<Tag isPin value={tag} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
<Text style={styles.date}>{date}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withNavigation(PostHeaderDescription);
|
@ -0,0 +1,33 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
avatar: {
|
||||
borderColor: '$borderColor',
|
||||
borderWidth: 1,
|
||||
},
|
||||
name: {
|
||||
marginHorizontal: 3,
|
||||
fontSize: 10,
|
||||
color: '$primaryBlack',
|
||||
fontFamily: '$primaryFont',
|
||||
fontWeight: 'bold',
|
||||
alignSelf: 'center',
|
||||
},
|
||||
reputation: {
|
||||
fontSize: 10,
|
||||
color: '$primaryDarkGray',
|
||||
marginRight: 8,
|
||||
alignSelf: 'center',
|
||||
},
|
||||
date: {
|
||||
fontSize: 10,
|
||||
color: '$primaryDarkGray',
|
||||
},
|
||||
avatarNameWrapper: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
});
|
5
src/components/postElements/index.js
Normal file
5
src/components/postElements/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
import PostHeaderDescription from './headerDescription/view/postHeaderDescription';
|
||||
import PostBody from './body/view/postBodyView';
|
||||
import Tags from './tags/view/tagsView';
|
||||
|
||||
export { PostHeaderDescription, PostBody, Tags };
|
7
src/components/postElements/tags/view/tagsStyles.js
Normal file
7
src/components/postElements/tags/view/tagsStyles.js
Normal file
@ -0,0 +1,7 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
});
|
38
src/components/postElements/tags/view/tagsView.js
Normal file
38
src/components/postElements/tags/view/tagsView.js
Normal file
@ -0,0 +1,38 @@
|
||||
import React, { Component } from 'react';
|
||||
import { View, FlatList } from 'react-native';
|
||||
|
||||
// Components
|
||||
import { Tag } from '../../../basicUIElements';
|
||||
|
||||
// Styles
|
||||
import styles from './tagsStyles';
|
||||
|
||||
// Constants
|
||||
class TagsView extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
|
||||
render() {
|
||||
const { tags, handleOnTagPress } = this.props;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<FlatList
|
||||
data={tags}
|
||||
horizontal
|
||||
renderItem={({ item, index }) => (
|
||||
<Tag key={index} value={item} isPin={index === 0} onPress={handleOnTagPress} />
|
||||
)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TagsView;
|
38
src/components/postView/container/postDisplayContainer.js
Normal file
38
src/components/postView/container/postDisplayContainer.js
Normal file
@ -0,0 +1,38 @@
|
||||
import React, { Component } from 'react';
|
||||
// import { connect } from 'react-redux';
|
||||
|
||||
// Services and Actions
|
||||
|
||||
// Middleware
|
||||
|
||||
// Constants
|
||||
|
||||
// Utilities
|
||||
|
||||
// Component
|
||||
import { PostDisplayView } from '..';
|
||||
|
||||
/*
|
||||
* Props Name Description Value
|
||||
*@props --> props name here description here Value Type Here
|
||||
*
|
||||
*/
|
||||
|
||||
class PostDisplayContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycle Functions
|
||||
|
||||
// Component Functions
|
||||
|
||||
render() {
|
||||
const { post, currentUser } = this.props;
|
||||
|
||||
return <PostDisplayView currentUser={currentUser} post={post} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default PostDisplayContainer;
|
5
src/components/postView/index.js
Normal file
5
src/components/postView/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
import PostDisplayView from './view/postDisplayView';
|
||||
import PostDisplay from './container/postDisplayContainer';
|
||||
|
||||
export { PostDisplay, PostDisplayView };
|
||||
export default PostDisplayView;
|
67
src/components/postView/view/postDisplayStyles.js
Normal file
67
src/components/postView/view/postDisplayStyles.js
Normal file
@ -0,0 +1,67 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'column',
|
||||
},
|
||||
header: {
|
||||
marginHorizontal: 16,
|
||||
},
|
||||
title: {
|
||||
fontSize: 24,
|
||||
color: '$primaryBlack',
|
||||
fontWeight: '900',
|
||||
fontFamily: '$primaryFont',
|
||||
marginBottom: 11,
|
||||
},
|
||||
description: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
scroll: {
|
||||
height: '$deviceHeight / 1.135',
|
||||
},
|
||||
footer: {
|
||||
flexDirection: 'column',
|
||||
marginTop: 19,
|
||||
marginBottom: 50,
|
||||
},
|
||||
footerText: {
|
||||
fontSize: 10,
|
||||
fontFamily: '$primaryFont',
|
||||
color: '$primaryDarkGray',
|
||||
marginVertical: 12,
|
||||
},
|
||||
footerName: {
|
||||
color: '$primaryBlack',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
stickyWrapper: {
|
||||
flexDirection: 'row',
|
||||
paddingHorizontal: 16,
|
||||
width: '$deviceWidth',
|
||||
marginBottom: 5,
|
||||
alignItems: 'center',
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
barIcons: {
|
||||
color: '$primaryDarkGray',
|
||||
fontSize: 20,
|
||||
marginRight: 8,
|
||||
marginLeft: 25,
|
||||
opacity: 0.7,
|
||||
},
|
||||
barIconRight: {
|
||||
color: '$primaryDarkGray',
|
||||
fontSize: 16,
|
||||
opacity: 0.7,
|
||||
},
|
||||
barIconButton: {
|
||||
marginLeft: 16,
|
||||
},
|
||||
stickyRightWrapper: {
|
||||
flexGrow: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
});
|
154
src/components/postView/view/postDisplayView.js
Normal file
154
src/components/postView/view/postDisplayView.js
Normal file
@ -0,0 +1,154 @@
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
View, Text, ScrollView, Dimensions,
|
||||
} from 'react-native';
|
||||
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
import { PostHeaderDescription, PostBody, Tags } from '../../postElements';
|
||||
import { PostPlaceHolder, StickyBar, TextWithIcon } from '../../basicUIElements';
|
||||
import { Upvote } from '../../upvote';
|
||||
import { IconButton } from '../../iconButton';
|
||||
import { CommentsDisplay } from '../../commentsDisplay';
|
||||
|
||||
// Styles
|
||||
import styles from './postDisplayStyles';
|
||||
|
||||
const HEIGHT = Dimensions.get('window').width;
|
||||
class PostDisplayView extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
postHeight: 0,
|
||||
scrollHeight: 0,
|
||||
};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_handleOnScroll = (event) => {
|
||||
const { y } = event.nativeEvent.contentOffset;
|
||||
|
||||
this.setState({
|
||||
scrollHeight: HEIGHT + y,
|
||||
});
|
||||
};
|
||||
|
||||
_handleOnPostLayout = (event) => {
|
||||
const { height } = event.nativeEvent.layout;
|
||||
|
||||
this.setState({
|
||||
postHeight: height,
|
||||
});
|
||||
};
|
||||
|
||||
_getTabBar = (isFixedFooter = false) => {
|
||||
const {
|
||||
post, currentUser, handleOnReplyPress, handleOnEditPress,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<StickyBar isFixedFooter={isFixedFooter}>
|
||||
<View style={styles.stickyWrapper}>
|
||||
<Upvote isShowpayoutValue content={post} user={currentUser} isLoggedIn={!!currentUser} />
|
||||
<TextWithIcon
|
||||
isClickable
|
||||
iconStyle={styles.barIcons}
|
||||
textMarginLeft={20}
|
||||
text={post && post.vote_count}
|
||||
iconName="ios-people"
|
||||
/>
|
||||
<TextWithIcon
|
||||
isClickable
|
||||
iconStyle={styles.barIcons}
|
||||
textMarginLeft={20}
|
||||
text={post && post.children}
|
||||
iconName="comments"
|
||||
iconType="FontAwesome"
|
||||
/>
|
||||
<View style={styles.stickyRightWrapper}>
|
||||
{post
|
||||
&& currentUser
|
||||
&& currentUser.name === post.author && (
|
||||
<IconButton
|
||||
iconStyle={styles.barIconRight}
|
||||
style={styles.barIconButton}
|
||||
name="pencil"
|
||||
iconType="SimpleLineIcons"
|
||||
onPress={() => handleOnEditPress && handleOnEditPress()}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
iconStyle={styles.barIconRight}
|
||||
style={styles.barIconButton}
|
||||
name="reply"
|
||||
onPress={() => handleOnReplyPress && handleOnReplyPress()}
|
||||
iconType="FontAwesome"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</StickyBar>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { post, currentUser } = this.props;
|
||||
const { postHeight, scrollHeight } = this.state;
|
||||
|
||||
const isPostEnd = scrollHeight > postHeight;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ScrollView style={styles.scroll} onScroll={event => this._handleOnScroll(event)}>
|
||||
<View style={styles.header}>
|
||||
{!post ? (
|
||||
<PostPlaceHolder />
|
||||
) : (
|
||||
<View onLayout={event => this._handleOnPostLayout(event)}>
|
||||
<Text style={styles.title}>{post.title}</Text>
|
||||
<PostHeaderDescription
|
||||
date={post.created}
|
||||
name={post.author}
|
||||
reputation={post.author_reputation}
|
||||
tag={post.category}
|
||||
avatar={post.avatar}
|
||||
size={16}
|
||||
/>
|
||||
{post && post.body && <PostBody body={post.body} />}
|
||||
<View style={styles.footer}>
|
||||
<Tags tags={post.json_metadata && post.json_metadata.tags} />
|
||||
<Text style={styles.footerText}>
|
||||
Posted by
|
||||
{' '}
|
||||
<Text style={styles.footerName}>{post.author}</Text>
|
||||
{' '}
|
||||
{post.created}
|
||||
</Text>
|
||||
{isPostEnd && this._getTabBar()}
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
{post && (
|
||||
<CommentsDisplay
|
||||
currentUser={currentUser}
|
||||
author={post.author}
|
||||
permlink={post.permlink}
|
||||
commentCount={post.children}
|
||||
/>
|
||||
)}
|
||||
</ScrollView>
|
||||
{!isPostEnd && this._getTabBar(true)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PostDisplayView;
|
@ -41,8 +41,29 @@ class PostsContainer extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
_handleOnContentPress = (author, permlink) => {
|
||||
const { navigation } = this.props;
|
||||
|
||||
if (author && permlink) {
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.POST,
|
||||
params: {
|
||||
author,
|
||||
permlink,
|
||||
},
|
||||
key: permlink,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return <PostsView handleOnUserPress={this._handleOnUserPress} {...this.props} />;
|
||||
return (
|
||||
<PostsView
|
||||
handleOnUserPress={this._handleOnUserPress}
|
||||
handleOnContentPress={this._handleOnContentPress}
|
||||
{...this.props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import {
|
||||
FlatList, View, ActivityIndicator,
|
||||
} from 'react-native';
|
||||
import { FlatList, View, ActivityIndicator } from 'react-native';
|
||||
|
||||
// import Placeholder from 'rn-placeholder';
|
||||
|
||||
@ -11,8 +9,7 @@ import { getPosts } from '../../../providers/steem/dsteem';
|
||||
// COMPONENTS
|
||||
import { PostCard } from '../../postCard';
|
||||
import { FilterBar } from '../../filterBar';
|
||||
import { PostPlaceHolder } from '../../basicUIElements';
|
||||
import { NoPost } from '../../basicUIElements';
|
||||
import { PostCardPlaceHolder, NoPost } from '../../basicUIElements';
|
||||
|
||||
// Styles
|
||||
import styles from './postsStyles';
|
||||
@ -32,7 +29,10 @@ class PostsView extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._loadPosts(this.state.user);
|
||||
const { user, isLoggedIn, isLoginMust } = this.state;
|
||||
const isCanLoad = isLoginMust ? isLoggedIn : true;
|
||||
|
||||
isCanLoad && this._loadPosts(user);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
@ -45,7 +45,6 @@ class PostsView extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_loadPosts = (user, _tag = null) => {
|
||||
const { getFor, tag } = this.props;
|
||||
const options = { tag: _tag || tag, limit: 10 };
|
||||
@ -57,8 +56,8 @@ class PostsView extends Component {
|
||||
this.setState({
|
||||
isReady: true,
|
||||
posts: result,
|
||||
startAuthor: result[result.length - 1].author,
|
||||
startPermlink: result[result.length - 1].permlink,
|
||||
startAuthor: result[result.length - 1] && result[result.length - 1].author,
|
||||
startPermlink: result[result.length - 1] && result[result.length - 1].permlink,
|
||||
refreshing: false,
|
||||
});
|
||||
}
|
||||
@ -127,7 +126,14 @@ class PostsView extends Component {
|
||||
const {
|
||||
isReady, refreshing, posts, user,
|
||||
} = this.state;
|
||||
const { componentId, handleOnUserPress, filterOptions } = this.props;
|
||||
const {
|
||||
componentId,
|
||||
handleOnUserPress,
|
||||
filterOptions,
|
||||
isLoginMust,
|
||||
handleOnContentPress,
|
||||
isLoggedIn,
|
||||
} = this.props;
|
||||
|
||||
if (user && posts && posts.length > 0) {
|
||||
return (
|
||||
@ -148,8 +154,9 @@ class PostsView extends Component {
|
||||
componentId={componentId}
|
||||
content={item}
|
||||
user={user}
|
||||
isLoggedIn
|
||||
isLoggedIn={isLoggedIn}
|
||||
handleOnUserPress={handleOnUserPress}
|
||||
handleOnContentPress={handleOnContentPress}
|
||||
/>
|
||||
)}
|
||||
keyExtractor={(post, index) => index.toString()}
|
||||
@ -177,10 +184,14 @@ class PostsView extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
// if (isLoginMust && !isLoggedIn) {
|
||||
// return <NoPost defaultText="Login to see!" />;
|
||||
// }
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<PostPlaceHolder />
|
||||
<PostPlaceHolder />
|
||||
<PostCardPlaceHolder />
|
||||
<PostCardPlaceHolder />
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
@ -57,4 +57,10 @@ export default EStyleSheet.create({
|
||||
overlay: {
|
||||
backgroundColor: '#403c4449',
|
||||
},
|
||||
payoutValue: {
|
||||
alignSelf: 'center',
|
||||
fontSize: 10,
|
||||
color: '$primaryDarkGray',
|
||||
marginLeft: 8,
|
||||
},
|
||||
});
|
||||
|
@ -103,7 +103,7 @@ class UpvoteView extends Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { isLoggedIn } = this.props;
|
||||
const { isLoggedIn, isShowpayoutValue, content } = this.props;
|
||||
const {
|
||||
isVoting, isModalVisible, amount, value, isVoted,
|
||||
} = this.state;
|
||||
@ -126,11 +126,14 @@ class UpvoteView extends Component {
|
||||
{isVoting ? (
|
||||
<ActivityIndicator />
|
||||
) : (
|
||||
<Icon
|
||||
style={[styles.upvoteIcon, { color: '#007ee5' }]}
|
||||
active={!isLoggedIn}
|
||||
name={isVoted ? 'ios-arrow-dropup-circle' : 'ios-arrow-dropup-outline'}
|
||||
/>
|
||||
<Fragment>
|
||||
<Icon
|
||||
style={[styles.upvoteIcon, { color: '#007ee5' }]}
|
||||
active={!isLoggedIn}
|
||||
name={isVoted ? 'ios-arrow-dropup-circle' : 'ios-arrow-dropup-outline'}
|
||||
/>
|
||||
{isShowpayoutValue && <Text style={styles.payoutValue}>$ {content && content.pending_payout_value}</Text> }
|
||||
</Fragment>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
||||
|
@ -1,16 +1,27 @@
|
||||
import { DrawerNavigator, SwitchNavigator, createStackNavigator } from 'react-navigation';
|
||||
import {
|
||||
createDrawerNavigator,
|
||||
createSwitchNavigator,
|
||||
createStackNavigator,
|
||||
} from 'react-navigation';
|
||||
import { BaseNavigator } from '../navigation';
|
||||
import { default as ROUTES } from '../constants/routeNames';
|
||||
|
||||
// Screens
|
||||
import {
|
||||
Splash, Login, PinCode, SteemConnect, Editor, Profile, RootComponent,
|
||||
Splash,
|
||||
Login,
|
||||
PinCode,
|
||||
SteemConnect,
|
||||
Editor,
|
||||
Profile,
|
||||
Post,
|
||||
RootComponent,
|
||||
} from '../screens';
|
||||
|
||||
// Components
|
||||
import { SideMenu } from '../components';
|
||||
|
||||
const mainNavigation = DrawerNavigator(
|
||||
const mainNavigation = createDrawerNavigator(
|
||||
{
|
||||
[ROUTES.SCREENS.HOME]: {
|
||||
screen: BaseNavigator,
|
||||
@ -29,13 +40,18 @@ const stackNavigatior = createStackNavigator(
|
||||
header: () => null,
|
||||
},
|
||||
},
|
||||
|
||||
[ROUTES.SCREENS.PROFILE]: {
|
||||
screen: RootComponent()(Profile),
|
||||
navigationOptions: {
|
||||
header: () => null,
|
||||
},
|
||||
},
|
||||
[ROUTES.SCREENS.POST]: {
|
||||
screen: Post,
|
||||
navigationOptions: {
|
||||
header: () => null,
|
||||
},
|
||||
},
|
||||
[ROUTES.SCREENS.EDITOR]: {
|
||||
screen: RootComponent()(Editor),
|
||||
navigationOptions: {
|
||||
@ -50,7 +66,7 @@ const stackNavigatior = createStackNavigator(
|
||||
},
|
||||
);
|
||||
|
||||
export default SwitchNavigator({
|
||||
export default createSwitchNavigator({
|
||||
stackNavigatior,
|
||||
[ROUTES.SCREENS.LOGIN]: { screen: RootComponent()(Login) },
|
||||
[ROUTES.SCREENS.PINCODE]: { screen: RootComponent()(PinCode) },
|
||||
|
@ -7,6 +7,7 @@ export default {
|
||||
HOME: `Home${SCREEN_SUFFIX}`,
|
||||
LOGIN: `Login${SCREEN_SUFFIX}`,
|
||||
PINCODE: `PinCode${SCREEN_SUFFIX}`,
|
||||
POST: `Post${SCREEN_SUFFIX}`,
|
||||
PROFILE: `Profile${SCREEN_SUFFIX}`,
|
||||
SPLASH: `Splash${SCREEN_SUFFIX}`,
|
||||
STEEM_CONNECT: `SteemConnect${SCREEN_SUFFIX}`,
|
||||
|
@ -22,7 +22,7 @@ EStyleSheet.build({
|
||||
$primaryBlack: '#3c4449',
|
||||
|
||||
// General Colors
|
||||
$borderColor: '#CED0CE',
|
||||
$borderColor: '#c5c5c5',
|
||||
$bubblesBlue: '#5CCDFF',
|
||||
$iconColor: '#c1c5c7',
|
||||
$dangerColor: '#fff',
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
import { Client, PrivateKey } from 'dsteem';
|
||||
import { AsyncStorage } from 'react-native';
|
||||
import { parsePosts, parseComments } from '../../utils/postParser';
|
||||
import { parsePosts, parsePost, parseComments } from '../../utils/postParser';
|
||||
|
||||
let rewardFund = null;
|
||||
let medianPrice = null;
|
||||
@ -140,8 +140,7 @@ export const isFolllowing = (author, user) => new Promise((resolve, reject) => {
|
||||
export const getPosts = async (by, query, user) => {
|
||||
try {
|
||||
let posts = await client.database.getDiscussions(by, query);
|
||||
console.log('comments');
|
||||
console.log(posts);
|
||||
|
||||
posts = await parsePosts(posts, user);
|
||||
return posts;
|
||||
} catch (error) {
|
||||
@ -165,14 +164,16 @@ export const getUserComments = async (query) => {
|
||||
* @param user post author
|
||||
* @param permlink post permlink
|
||||
*/
|
||||
export const getPost = (user, permlink) => new Promise((resolve, reject) => {
|
||||
export const getPost = async (user, permlink) => {
|
||||
try {
|
||||
const post = client.database.call('get_content', [user, permlink]);
|
||||
resolve(post);
|
||||
let posts = await client.database.call('get_content', [user, permlink]);
|
||||
|
||||
posts = await parsePost(posts, user);
|
||||
return posts;
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
return error;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @method getUser get user data
|
||||
|
@ -13,15 +13,11 @@ import {
|
||||
View,
|
||||
} from 'native-base';
|
||||
import ScrollableTabView from '@esteemapp/react-native-scrollable-tab-view';
|
||||
//import { Navigation } from 'react-native-navigation';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
|
||||
// Internal Components
|
||||
import { TabBar } from '../../../components/tabBar';
|
||||
import { PostCard } from '../../../components/postCard';
|
||||
|
||||
import Comment from '../../../components/comment/comment';
|
||||
|
||||
import { getTimeFromNow } from '../../../utils/time';
|
||||
|
||||
// Styles
|
||||
|
@ -99,6 +99,7 @@ export class EditorScreen extends Component {
|
||||
quickTitle={wordsCount > 0 && `${wordsCount} words`}
|
||||
handleOnPressPreviewButton={this._handleOnPressPreviewButton}
|
||||
isFormValid={isFormValid}
|
||||
isHasIcons
|
||||
handleOnSubmit={this._handleOnSubmit}
|
||||
/>
|
||||
<PostForm
|
||||
|
@ -78,7 +78,7 @@ export default class HomeScreen extends PureComponent {
|
||||
const { componentId } = this.props;
|
||||
return (
|
||||
<Fragment>
|
||||
<Header userName={user.name} reputation={user && user.reputation} />
|
||||
<Header userName={user && user.name} reputation={user && user.reputation} />
|
||||
<View style={styles.root} key="overlay">
|
||||
<ScrollableTabView
|
||||
style={styles.tabView}
|
||||
@ -94,26 +94,15 @@ export default class HomeScreen extends PureComponent {
|
||||
)}
|
||||
>
|
||||
<View tabLabel="Feed" style={styles.tabbarItem}>
|
||||
{isLoggedIn ? (
|
||||
<Posts
|
||||
filterOptions={[
|
||||
'NEW POSTS',
|
||||
'VOTES',
|
||||
'REPLIES',
|
||||
'MENTIONS',
|
||||
'FOLLOWS',
|
||||
'REBLOGS',
|
||||
]}
|
||||
isLoginMust
|
||||
getFor="feed"
|
||||
tag={user.name}
|
||||
user={user}
|
||||
isLoggedIn={isLoggedIn}
|
||||
componentId={componentId}
|
||||
/>
|
||||
) : (
|
||||
<Text>Login to see your Feed</Text>
|
||||
)}
|
||||
<Posts
|
||||
filterOptions={['NEW POSTS', 'VOTES', 'REPLIES', 'MENTIONS', 'FOLLOWS', 'REBLOGS']}
|
||||
isLoginMust
|
||||
getFor="feed"
|
||||
tag={user.name}
|
||||
user={user}
|
||||
isLoggedIn={isLoggedIn}
|
||||
componentId={componentId}
|
||||
/>
|
||||
</View>
|
||||
<View tabLabel="Hot" style={styles.tabbarItem}>
|
||||
<Posts
|
||||
|
@ -1,10 +1,11 @@
|
||||
import PinCode from './pinCode';
|
||||
import Splash from './splash';
|
||||
import SteemConnect from './steem-connect/steemConnect';
|
||||
import { Editor } from './editor';
|
||||
import { Home } from './home';
|
||||
import { Login } from './login';
|
||||
import { Notification } from './notification';
|
||||
import SteemConnect from './steem-connect/steemConnect';
|
||||
import { Post } from './post';
|
||||
import { Profile } from './profile';
|
||||
import RootComponent from './root';
|
||||
|
||||
@ -29,6 +30,7 @@ export {
|
||||
Profile,
|
||||
SteemConnect,
|
||||
Splash,
|
||||
Post,
|
||||
RootComponent,
|
||||
// Author,
|
||||
// SideMenu,
|
||||
|
88
src/screens/post/container/postContainer.js
Normal file
88
src/screens/post/container/postContainer.js
Normal file
@ -0,0 +1,88 @@
|
||||
import React, { Component } from 'react';
|
||||
// import { connect } from 'react-redux';
|
||||
|
||||
// Services and Actions
|
||||
import { getUserData, getAuthStatus } from '../../../realm/realm';
|
||||
import { getPost, getUser } from '../../../providers/steem/dsteem';
|
||||
|
||||
// Middleware
|
||||
|
||||
// Constants
|
||||
|
||||
// Utilities
|
||||
// Component
|
||||
import { PostScreen } from '..';
|
||||
|
||||
/*
|
||||
* Props Name Description Value
|
||||
*@props --> content which is include all post data Object
|
||||
*
|
||||
*/
|
||||
|
||||
class PostContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
post: null,
|
||||
error: null,
|
||||
currentUser: null,
|
||||
};
|
||||
}
|
||||
|
||||
// Component Life Cycle Functions
|
||||
componentDidMount() {
|
||||
const { navigation } = this.props;
|
||||
const { author, permlink } = navigation.state && navigation.state.params;
|
||||
|
||||
this._loadPost(author, permlink);
|
||||
this._getUser();
|
||||
}
|
||||
|
||||
// Component Functions
|
||||
|
||||
_loadPost = (author, permlink) => {
|
||||
const { currentUser } = this.state;
|
||||
// TODO: get from redux for cureentUser
|
||||
getPost(author, permlink)
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
this.setState({ post: result });
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
this.setState({ error: err });
|
||||
});
|
||||
};
|
||||
|
||||
async _getUser() {
|
||||
let _currentUser;
|
||||
let userData;
|
||||
let isLoggedIn;
|
||||
|
||||
await getAuthStatus().then((res) => {
|
||||
isLoggedIn = res;
|
||||
});
|
||||
|
||||
if (isLoggedIn) {
|
||||
await getUserData().then((res) => {
|
||||
_currentUser = Array.from(res);
|
||||
});
|
||||
|
||||
userData = _currentUser && (await getUser(_currentUser[0].username));
|
||||
|
||||
await this.setState({
|
||||
currentUser: userData,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { post, error, currentUser } = this.state;
|
||||
|
||||
return (
|
||||
<PostScreen currentUser={currentUser} key={Math.random * 100} post={post} error={error} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PostContainer;
|
5
src/screens/post/index.js
Normal file
5
src/screens/post/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
import PostScreen from './screen/postScreen';
|
||||
import Post from './container/postContainer';
|
||||
|
||||
export { PostScreen, Post };
|
||||
export default Post;
|
39
src/screens/post/screen/postScreen.js
Normal file
39
src/screens/post/screen/postScreen.js
Normal file
@ -0,0 +1,39 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
import { EditorHeader } from '../../../components/editorHeader';
|
||||
import { PostDisplay } from '../../../components/postView';
|
||||
// Styles
|
||||
// eslint-disable-next-line
|
||||
//import styles from './_styles';
|
||||
|
||||
class PostScreen extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
|
||||
render() {
|
||||
const { post, currentUser } = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<EditorHeader isHasDropdown title="Post" />
|
||||
<PostDisplay post={post} currentUser={currentUser} />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PostScreen;
|
@ -13,7 +13,7 @@ import ScrollableTabView from "@esteemapp/react-native-scrollable-tab-view";
|
||||
import { TabBar } from "../../components/tabBar";
|
||||
import DiscoverPage from "../discover/discover";
|
||||
import { PostCard } from "../../components/postCard";
|
||||
import Comment from "../../components/comment/comment";
|
||||
//import Comment from "../../components/comment/comment";
|
||||
|
||||
|
||||
import { getUserData, getAuthStatus } from '../../realm/realm';
|
||||
|
@ -5,7 +5,13 @@ import { ProfileScreen } from '..';
|
||||
|
||||
// Utilitites
|
||||
import {
|
||||
getFollows, getPosts, getUser, getUserComments,
|
||||
followUser,
|
||||
unfollowUser,
|
||||
getFollows,
|
||||
getPosts,
|
||||
getUserComments,
|
||||
getUser,
|
||||
isFolllowing,
|
||||
} from '../../../providers/steem/dsteem';
|
||||
import { getUserData, getAuthStatus } from '../../../realm/realm';
|
||||
|
||||
@ -14,8 +20,8 @@ class ProfileContainer extends Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
user: null,
|
||||
posts: [],
|
||||
commments: [],
|
||||
currentUser: null,
|
||||
comments: [],
|
||||
replies: [],
|
||||
about: {},
|
||||
follows: {},
|
||||
@ -51,7 +57,7 @@ class ProfileContainer extends Component {
|
||||
.then((result) => {
|
||||
this.setState({
|
||||
isReady: true,
|
||||
commments: result,
|
||||
comments: result,
|
||||
refreshing: false,
|
||||
isLoading: false,
|
||||
});
|
||||
@ -61,6 +67,79 @@ class ProfileContainer extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
// _unfollow = async () => {
|
||||
// let userData;
|
||||
// let privateKey;
|
||||
|
||||
// await this.setState({
|
||||
// follow_loader: true,
|
||||
// });
|
||||
|
||||
// await getUserData().then((result) => {
|
||||
// userData = Array.from(result);
|
||||
// });
|
||||
|
||||
// console.log(userData);
|
||||
// privateKey = decryptKey(userData[0].postingKey, '1234');
|
||||
|
||||
// unfollowUser(
|
||||
// {
|
||||
// follower: userData[0].username,
|
||||
// following: this.state.author.name,
|
||||
// },
|
||||
// privateKey,
|
||||
// )
|
||||
// .then((result) => {
|
||||
// this.setState({
|
||||
// follow_loader: false,
|
||||
// isFolllowing: false,
|
||||
// });
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// this.setState({
|
||||
// follow_loader: false,
|
||||
// });
|
||||
// });
|
||||
// };
|
||||
|
||||
// _follow = async () => {
|
||||
// let userData;
|
||||
// let privateKey;
|
||||
|
||||
// await this.setState({
|
||||
// follow_loader: true,
|
||||
// });
|
||||
|
||||
// await getUserData().then((result) => {
|
||||
// userData = Array.from(result);
|
||||
// });
|
||||
|
||||
// console.log(userData);
|
||||
// privateKey = decryptKey(userData[0].postingKey, '1234');
|
||||
|
||||
// followUser(
|
||||
// {
|
||||
// follower: userData[0].username,
|
||||
// following: this.state.author.name,
|
||||
// },
|
||||
// privateKey,
|
||||
// )
|
||||
// .then((result) => {
|
||||
// console.log(result);
|
||||
// this.setState({
|
||||
// follow_loader: false,
|
||||
// isFolllowing: true,
|
||||
// });
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// console.log(err);
|
||||
// this.setState({
|
||||
// follow_loader: false,
|
||||
// isFolllowing: false,
|
||||
// });
|
||||
// });
|
||||
// };
|
||||
|
||||
async _loadProfile(selectedUser = null) {
|
||||
// TODO: use from redux store.
|
||||
let isLoggedIn;
|
||||
@ -111,7 +190,7 @@ class ProfileContainer extends Component {
|
||||
render() {
|
||||
const {
|
||||
about,
|
||||
commments,
|
||||
comments,
|
||||
follows,
|
||||
isReverseHeader,
|
||||
isLoading,
|
||||
@ -127,7 +206,7 @@ class ProfileContainer extends Component {
|
||||
isReady={isReady}
|
||||
about={about}
|
||||
isReverseHeader={isReverseHeader}
|
||||
commments={commments}
|
||||
comments={comments}
|
||||
follows={follows}
|
||||
isLoading={isLoading}
|
||||
isLoggedIn={isLoggedIn}
|
||||
|
@ -1,10 +1,10 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { FlatList, ActivityIndicator, View } from 'react-native';
|
||||
import { View, ScrollView } from 'react-native';
|
||||
|
||||
// Components
|
||||
import ScrollableTabView from '@esteemapp/react-native-scrollable-tab-view';
|
||||
import Comment from '../../../components/comment/comment';
|
||||
import { Comments } from '../../../components/comments';
|
||||
import { CollapsibleCard } from '../../../components/collapsibleCard';
|
||||
import { Header } from '../../../components/header';
|
||||
import { NoPost, ProfileSummaryPlaceHolder } from '../../../components/basicUIElements';
|
||||
@ -28,7 +28,7 @@ class ProfileScreen extends Component {
|
||||
render() {
|
||||
const {
|
||||
about,
|
||||
commments,
|
||||
comments,
|
||||
follows,
|
||||
isLoading,
|
||||
isLoggedIn,
|
||||
@ -131,15 +131,10 @@ class ProfileScreen extends Component {
|
||||
)}
|
||||
</View>
|
||||
<View tabLabel="Comments" style={styles.commentsTabBar}>
|
||||
{commments && commments.length > 0 ? (
|
||||
<FlatList
|
||||
data={commments}
|
||||
showsVerticalScrollIndicator={false}
|
||||
renderItem={({ item }) => <Comment comment={item} isLoggedIn user={user} />}
|
||||
keyExtractor={(post, index) => index.toString()}
|
||||
onEndThreshold={0}
|
||||
bounces={false}
|
||||
/>
|
||||
{comments && comments.length > 0 ? (
|
||||
<ScrollView>
|
||||
<Comments comments={comments} />
|
||||
</ScrollView>
|
||||
) : (
|
||||
<NoPost
|
||||
name={username}
|
||||
|
@ -1,17 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
// Components
|
||||
import { SinglePostScreen } from '..';
|
||||
|
||||
class SinglePostContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
render() {
|
||||
return <SinglePostScreen {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default SinglePostContainer;
|
@ -1,5 +0,0 @@
|
||||
import SinglePost from './container/singlePostContainer';
|
||||
import SinglePostScreen from './screen/singlePostScreen';
|
||||
|
||||
export { SinglePost, SinglePostScreen };
|
||||
export default SinglePost;
|
@ -1,189 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
/* eslint-disable no-unused-vars */
|
||||
import React from 'react';
|
||||
import {
|
||||
Dimensions,
|
||||
ActivityIndicator,
|
||||
StatusBar,
|
||||
FlatList,
|
||||
BackHandler,
|
||||
ScrollView,
|
||||
TextInput,
|
||||
Image,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {
|
||||
Card, Button, Icon, Text, Title,
|
||||
} from 'native-base';
|
||||
import HTML from 'react-native-html-renderer';
|
||||
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import styles from './singlePostStyles';
|
||||
/* eslint-enable no-unused-vars */
|
||||
|
||||
class SinglePostScreen extends React.Component {
|
||||
static get options() {
|
||||
return {
|
||||
_statusBar: {
|
||||
visible: true,
|
||||
drawBehind: false,
|
||||
},
|
||||
topBar: {
|
||||
animate: true,
|
||||
hideOnScroll: false,
|
||||
drawBehind: false,
|
||||
leftButtons: {
|
||||
id: 'back',
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
backgroundColor: '#f5fcff',
|
||||
},
|
||||
bottomTabs: {
|
||||
visible: false,
|
||||
drawBehind: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
Navigation.events().bindComponent(this);
|
||||
this.state = {
|
||||
comments: [],
|
||||
comment: '',
|
||||
isLoading: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
BackHandler.addEventListener('hardwareBackPress', () => {
|
||||
Navigation.pop(this.props.componentId);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
BackHandler.removeEventListener('hardwareBackPress');
|
||||
}
|
||||
|
||||
onLinkPress(evt, href, attribs) {}
|
||||
|
||||
alterNode(node) {
|
||||
if (node.name == 'img') {
|
||||
node.attribs.style = `max-width: ${Dimensions.get('window').width
|
||||
+ 10}px; left: -10px; width: 100% !important`;
|
||||
} else if (node.name == 'iframe') {
|
||||
node.attribs.style = `max-width: ${
|
||||
Dimensions.get('window').width
|
||||
}px; left: -10px`;
|
||||
node.attribs.height = 200;
|
||||
}
|
||||
}
|
||||
|
||||
navigationButtonPressed({ buttonId }) {
|
||||
// will be called when "buttonOne" is clicked
|
||||
if (buttonId === 'back') {
|
||||
Navigation.pop(this.props.componentId);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
<ScrollView style={{ flex: 1 }}>
|
||||
<View style={{ flexDirection: 'row' }}>
|
||||
<View style={{ flex: 0.2 }}>
|
||||
<Image
|
||||
style={{
|
||||
height: 40,
|
||||
width: 40,
|
||||
borderWidth: 1,
|
||||
borderColor: 'lightgray',
|
||||
}}
|
||||
source={{
|
||||
uri: this.props.content.avatar,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<View style={{ flex: 0.4 }}>
|
||||
<Text>{this.props.content.author}</Text>
|
||||
<Text note>
|
||||
#
|
||||
{this.props.content.category}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={{ flex: 0.4, alignItems: 'flex-end' }}>
|
||||
<Text note>{this.props.content.created}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View>
|
||||
<Text style={{ fontWeight: 'bold' }}>
|
||||
{this.props.content.title}
|
||||
</Text>
|
||||
</View>
|
||||
<HTML
|
||||
html={this.props.content.body}
|
||||
onLinkPress={(evt, href, hrefatr) => this.onLinkPress(evt, href, hrefatr)
|
||||
}
|
||||
containerStyle={{ padding: 10 }}
|
||||
textSelectable
|
||||
tagsStyles={styles}
|
||||
ignoredTags={['script']}
|
||||
debug={false}
|
||||
alterNode={(node) => {
|
||||
this.alterNode(node);
|
||||
}}
|
||||
imagesMaxWidth={Dimensions.get('window').width}
|
||||
/>
|
||||
|
||||
<View style={{ padding: 10 }}>
|
||||
<TextInput
|
||||
style={{
|
||||
borderWidth: 1,
|
||||
borderColor: 'lightgray',
|
||||
borderRadius: 5,
|
||||
padding: 10,
|
||||
minHeight: 100,
|
||||
}}
|
||||
multiline
|
||||
numberOfLines={4}
|
||||
placeholder="What do you think about this story?"
|
||||
onChangeText={comment => this.setState({ comment })}
|
||||
value={this.state.comment}
|
||||
/>
|
||||
<View style={{ flexDirection: 'row-reverse' }}>
|
||||
<Button
|
||||
onPress={this.postComment}
|
||||
style={{
|
||||
alignSelf: 'flex-end',
|
||||
marginTop: 10,
|
||||
borderRadius: 20,
|
||||
}}
|
||||
>
|
||||
{this.state.isLoading ? (
|
||||
<ActivityIndicator
|
||||
style={{ marginHorizontal: 50 }}
|
||||
/>
|
||||
) : (
|
||||
<Text>Post a Comment</Text>
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
style={{
|
||||
alignSelf: 'flex-end',
|
||||
marginRight: 10,
|
||||
borderRadius: 50,
|
||||
}}
|
||||
>
|
||||
<Icon name="images" />
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SinglePostScreen;
|
@ -1,13 +0,0 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
comments: {
|
||||
flex: 1,
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
});
|
1
src/utils/post.js
Normal file
1
src/utils/post.js
Normal file
@ -0,0 +1 @@
|
||||
// ^ (http: \/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$
|
@ -107,8 +107,10 @@ export const parsePost = (post) => {
|
||||
|
||||
const voteRshares = post.active_votes.reduce((a, b) => a + parseFloat(b.rshares), 0);
|
||||
const ratio = totalPayout / voteRshares;
|
||||
//post.is_voted = false;
|
||||
|
||||
for (const i in post.active_votes) {
|
||||
// post.is_voted = post.active_votes[i].voter === "u-e" && post.active_votes[i].percent > 0;
|
||||
post.active_votes[i].value = (post.active_votes[i].rshares * ratio).toFixed(2);
|
||||
post.active_votes[i].reputation = getReputation(post.active_votes[i].reputation);
|
||||
post.active_votes[i].avatar = `https://steemitimages.com/u/${
|
||||
|
Loading…
Reference in New Issue
Block a user