Merge branch 'bugfix/more-comment' of github.com:esteemapp/esteem-mobile into development

This commit is contained in:
Mustafa Buyukcelebi 2019-12-09 17:21:29 +03:00
commit 468e08f849
12 changed files with 360 additions and 287 deletions

View File

@ -37,6 +37,7 @@ export default EStyleSheet.create({
position: 'absolute',
right: 0,
bottom: -10,
padding: 10,
},
voteCountText: {
alignSelf: 'center',

View File

@ -1,7 +1,7 @@
import React, { PureComponent, Fragment } from 'react';
import React, { Fragment, useState, useRef } from 'react';
import { View, TouchableWithoutFeedback } from 'react-native';
import ActionSheet from 'react-native-actionsheet';
import { injectIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import get from 'lodash/get';
import { getTimeFromNow } from '../../../utils/time';
@ -17,176 +17,162 @@ import { TextWithIcon } from '../../basicUIElements';
// Styles
import styles from './commentStyles';
class CommentView extends PureComponent {
/* Props
* ------------------------------------------------
* @prop { type } name - Description....
*/
constructor(props) {
super(props);
this.state = {
isShowSubComments: props.isShowSubComments || false,
isPressedShowButton: false,
};
}
// Component Life Cycles
// Component Functions
_showSubCommentsToggle = () => {
const { isShowSubComments } = this.state;
this.setState({ isShowSubComments: !isShowSubComments, isPressedShowButton: true });
const CommentView = ({
avatarSize,
comment,
commentNumber,
currentAccountUsername,
fetchPost,
handleDeleteComment,
handleOnEditPress,
handleOnLongPress,
handleOnReplyPress,
handleOnUserPress,
handleOnVotersPress,
isLoggedIn,
isShowComments,
isShowMoreButton,
marginLeft,
voteCount,
mainAuthor = { mainAuthor },
isHideImage,
showAllComments,
isShowSubComments,
hideManyCommentsButton,
}) => {
const [_isShowSubComments, setIsShowSubComments] = useState(isShowSubComments || false);
const [isPressedShowButton, setIsPressedShowButton] = useState(false);
const intl = useIntl();
const actionSheet = useRef(null);
const _showSubCommentsToggle = () => {
setIsShowSubComments(!_isShowSubComments);
setIsPressedShowButton(true);
};
render() {
const {
avatarSize,
comment,
commentNumber,
currentAccountUsername,
fetchPost,
handleDeleteComment,
handleOnEditPress,
handleOnLongPress,
handleOnReplyPress,
handleOnUserPress,
handleOnVotersPress,
isLoggedIn,
isShowComments,
isShowMoreButton,
marginLeft,
voteCount,
intl,
mainAuthor = { mainAuthor },
isHideImage,
} = this.props;
const { isShowSubComments, isPressedShowButton } = this.state;
return (
<TouchableWithoutFeedback onLongPress={handleOnLongPress}>
<View>
<PostHeaderDescription
key={comment.permlink}
date={getTimeFromNow(comment.created)}
name={comment.author}
reputation={comment.author_reputation}
size={avatarSize || 24}
currentAccountUsername={currentAccountUsername}
isShowOwnerIndicator={mainAuthor === comment.author}
isHideImage={isHideImage}
return (
<TouchableWithoutFeedback onLongPress={handleOnLongPress}>
<View>
<PostHeaderDescription
key={comment.permlink}
date={getTimeFromNow(comment.created)}
name={comment.author}
reputation={comment.author_reputation}
size={avatarSize || 24}
currentAccountUsername={currentAccountUsername}
isShowOwnerIndicator={mainAuthor === comment.author}
isHideImage={isHideImage}
/>
<View style={[{ marginLeft: marginLeft || 29 }, styles.bodyWrapper]}>
<PostBody
isComment
commentDepth={comment.depth}
handleOnUserPress={handleOnUserPress}
body={comment.body}
textSelectable={false}
/>
<View style={[{ marginLeft: marginLeft || 29 }, styles.bodyWrapper]}>
<PostBody
isComment
commentDepth={comment.depth}
handleOnUserPress={handleOnUserPress}
body={comment.body}
textSelectable={false}
/>
<View style={styles.footerWrapper}>
{isLoggedIn && (
<Fragment>
<Upvote isShowPayoutValue content={comment} />
<TextWithIcon
iconName="people"
iconSize={20}
wrapperStyle={styles.leftButton}
iconType="MaterialIcons"
isClickable
onPress={() =>
handleOnVotersPress &&
voteCount > 0 &&
handleOnVotersPress(get(comment, 'active_votes'))
}
text={voteCount}
textMarginLeft={20}
textStyle={styles.voteCountText}
/>
<IconButton
size={20}
iconStyle={styles.leftIcon}
style={styles.leftButton}
name="reply"
onPress={() => handleOnReplyPress && handleOnReplyPress(comment)}
iconType="MaterialIcons"
/>
{currentAccountUsername === comment.author && (
<Fragment>
<IconButton
size={20}
iconStyle={styles.leftIcon}
style={styles.leftButton}
name="create"
onPress={() => handleOnEditPress && handleOnEditPress(comment)}
iconType="MaterialIcons"
/>
{!comment.children && !voteCount && (
<Fragment>
<IconButton
size={20}
iconStyle={styles.leftIcon}
style={styles.leftButton}
name="delete-forever"
onPress={() => this.ActionSheet.show()}
iconType="MaterialIcons"
/>
<ActionSheet
ref={o => (this.ActionSheet = o)}
options={[
intl.formatMessage({ id: 'alert.delete' }),
intl.formatMessage({ id: 'alert.cancel' }),
]}
title={intl.formatMessage({ id: 'alert.delete' })}
destructiveButtonIndex={0}
cancelButtonIndex={1}
onPress={index => {
index === 0 ? handleDeleteComment(comment.permlink) : null;
}}
/>
</Fragment>
)}
</Fragment>
)}
</Fragment>
)}
{isShowMoreButton && (
<View style={styles.rightButtonWrapper}>
<TextWithIcon
wrapperStyle={styles.rightButton}
iconName={isShowSubComments ? 'keyboard-arrow-up' : 'keyboard-arrow-down'}
textStyle={!isPressedShowButton && styles.moreText}
iconType="MaterialIcons"
isClickable
iconStyle={styles.iconStyle}
iconSize={16}
onPress={() => this._showSubCommentsToggle()}
text={!isPressedShowButton ? `${comment.children} more replies` : ''}
/>
</View>
)}
</View>
{isShowSubComments && commentNumber > 0 && (
<Comments
isShowComments={isShowComments}
commentNumber={commentNumber && commentNumber * 2}
marginLeft={20}
isShowSubComments={isShowSubComments}
avatarSize={avatarSize || 16}
author={comment.author}
permlink={comment.permlink}
commentCount={comment.children}
isShowMoreButton={false}
fetchPost={fetchPost}
mainAuthor={mainAuthor}
/>
<View style={styles.footerWrapper}>
{isLoggedIn && (
<Fragment>
<Upvote isShowPayoutValue content={comment} />
<TextWithIcon
iconName="people"
iconSize={20}
wrapperStyle={styles.leftButton}
iconType="MaterialIcons"
isClickable
onPress={() =>
handleOnVotersPress &&
voteCount > 0 &&
handleOnVotersPress(get(comment, 'active_votes'))
}
text={voteCount}
textMarginLeft={20}
textStyle={styles.voteCountText}
/>
<IconButton
size={20}
iconStyle={styles.leftIcon}
style={styles.leftButton}
name="reply"
onPress={() => handleOnReplyPress && handleOnReplyPress(comment)}
iconType="MaterialIcons"
/>
{currentAccountUsername === comment.author && (
<Fragment>
<IconButton
size={20}
iconStyle={styles.leftIcon}
style={styles.leftButton}
name="create"
onPress={() => handleOnEditPress && handleOnEditPress(comment)}
iconType="MaterialIcons"
/>
{!comment.children && !voteCount && (
<Fragment>
<IconButton
size={20}
iconStyle={styles.leftIcon}
style={styles.leftButton}
name="delete-forever"
onPress={() => actionSheet.current.show()}
iconType="MaterialIcons"
/>
<ActionSheet
ref={actionSheet}
options={[
intl.formatMessage({ id: 'alert.delete' }),
intl.formatMessage({ id: 'alert.cancel' }),
]}
title={intl.formatMessage({ id: 'alert.delete' })}
destructiveButtonIndex={0}
cancelButtonIndex={1}
onPress={index => {
index === 0 ? handleDeleteComment(comment.permlink) : null;
}}
/>
</Fragment>
)}
</Fragment>
)}
</Fragment>
)}
{!showAllComments && isShowMoreButton && (
<View style={styles.rightButtonWrapper}>
<TextWithIcon
wrapperStyle={styles.rightButton}
iconName={_isShowSubComments ? 'keyboard-arrow-up' : 'keyboard-arrow-down'}
textStyle={!isPressedShowButton && styles.moreText}
iconType="MaterialIcons"
isClickable
iconStyle={styles.iconStyle}
iconSize={16}
onPress={() => _showSubCommentsToggle()}
text={!isPressedShowButton ? `${comment.children} more replies` : ''}
/>
</View>
)}
</View>
{_isShowSubComments && commentNumber > 0 && (
<Comments
isShowComments={isShowComments}
commentNumber={commentNumber + 1}
marginLeft={20}
isShowSubComments={true}
avatarSize={avatarSize || 16}
author={comment.author}
permlink={comment.permlink}
commentCount={comment.children}
isShowMoreButton={false}
hasManyComments={commentNumber === 5 && get(comment, 'children') > 0}
fetchPost={fetchPost}
hideManyCommentsButton={hideManyCommentsButton}
mainAuthor={mainAuthor}
/>
)}
</View>
</TouchableWithoutFeedback>
);
}
}
</View>
</TouchableWithoutFeedback>
);
};
export default injectIntl(CommentView);
export default CommentView;

View File

@ -261,11 +261,16 @@ class CommentsContainer extends Component {
isOwnProfile,
isHideImage,
isShowSubComments,
hasManyComments,
showAllComments,
hideManyCommentsButton,
} = this.props;
return (
<CommentsView
key={selectedFilter}
hasManyComments={hasManyComments}
hideManyCommentsButton={hideManyCommentsButton}
selectedFilter={selectedFilter}
selectedPermlink={_selectedPermlink || selectedPermlink}
author={author}
@ -285,6 +290,7 @@ class CommentsContainer extends Component {
isHideImage={isHideImage}
handleOnVotersPress={this._handleOnVotersPress}
isShowSubComments={isShowSubComments}
showAllComments={showAllComments}
/>
);
}

View File

@ -4,4 +4,18 @@ export default EStyleSheet.create({
list: {
marginBottom: 20,
},
moreRepliesButtonWrapper: {
backgroundColor: '$iconColor',
height: 18,
justifyContent: 'center',
alignItems: 'center',
borderRadius: 20,
marginTop: 15,
minWidth: 40,
maxWidth: 170,
},
moreRepliesText: {
color: '$white',
fontSize: 10,
},
});

View File

@ -1,114 +1,122 @@
import React, { Component, Fragment } from 'react';
import React, { useState, Fragment, useRef } from 'react';
import { FlatList } from 'react-native';
import ActionSheet from 'react-native-actionsheet';
import get from 'lodash/get';
import { injectIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { navigate } from '../../../navigation/service';
// Components
// eslint-disable-next-line import/no-cycle
import { Comment } from '../../comment';
import { Comment, TextButton } from '../..';
// Constants
import ROUTES from '../../../constants/routeNames';
// Styles
import styles from './commentStyles';
class CommentsView extends Component {
/* Props
* ------------------------------------------------
* @prop { type } name - Description....
*/
const CommentsView = ({
avatarSize,
commentCount,
commentNumber,
comments,
currentAccountUsername,
fetchPost,
handleDeleteComment,
handleOnEditPress,
handleOnPressCommentMenu,
handleOnReplyPress,
handleOnUserPress,
handleOnVotersPress,
hasManyComments,
isHideImage,
isLoggedIn,
isOwnProfile,
isShowSubComments,
mainAuthor,
marginLeft,
isShowMoreButton,
showAllComments,
hideManyCommentsButton,
}) => {
const [selectedComment, setSelectedComment] = useState(null);
const intl = useIntl();
const commentMenu = useRef();
constructor(props) {
super(props);
this.state = {
selectedComment: null,
};
this.commentMenu = React.createRef();
}
const _keyExtractor = item => get(item, 'permlink');
// Component Life Cycles
// Component Functions
_keyExtractor = item => item.permlink;
_openCommentMenu = item => {
this.setState({ selectedComment: item });
this.commentMenu.current.show();
const _openCommentMenu = item => {
setSelectedComment(item);
commentMenu.current.show();
};
render() {
const {
mainAuthor,
avatarSize,
commentCount,
commentNumber,
comments,
currentAccountUsername,
fetchPost,
handleOnEditPress,
handleOnReplyPress,
handleOnUserPress,
isLoggedIn,
isShowSubComments,
marginLeft,
handleDeleteComment,
handleOnPressCommentMenu,
handleOnVotersPress,
intl,
isOwnProfile,
isHideImage,
} = this.props;
const { selectedComment } = this.state;
const _readMoreComments = () => {
navigate({
routeName: ROUTES.SCREENS.COMMENTS,
params: { comments, fetchPost, handleOnVotersPress },
});
};
const menuItems = isOwnProfile
? [
intl.formatMessage({ id: 'post.copy_link' }),
intl.formatMessage({ id: 'post.open_thread' }),
intl.formatMessage({ id: 'alert.cancel' }),
]
: [intl.formatMessage({ id: 'post.copy_link' }), intl.formatMessage({ id: 'alert.cancel' })];
const menuItems = isOwnProfile
? [
intl.formatMessage({ id: 'post.copy_link' }),
intl.formatMessage({ id: 'post.open_thread' }),
intl.formatMessage({ id: 'alert.cancel' }),
]
: [intl.formatMessage({ id: 'post.copy_link' }), intl.formatMessage({ id: 'alert.cancel' })];
if (!hideManyCommentsButton && hasManyComments) {
return (
<Fragment>
<FlatList
style={styles.list}
data={comments}
keyExtractor={this._keyExtractor}
renderItem={({ item }) => (
<Comment
mainAuthor={mainAuthor}
avatarSize={avatarSize}
comment={item}
commentCount={commentCount || get(item.children)}
commentNumber={commentNumber}
handleDeleteComment={handleDeleteComment}
currentAccountUsername={currentAccountUsername}
fetchPost={fetchPost}
handleOnEditPress={handleOnEditPress}
handleOnReplyPress={handleOnReplyPress}
handleOnUserPress={handleOnUserPress}
handleOnVotersPress={handleOnVotersPress}
isHideImage={isHideImage}
isLoggedIn={isLoggedIn}
isShowMoreButton={commentNumber === 1 && get(item, 'children') > 0}
voteCount={get(item, 'vote_count')}
isShowSubComments={isShowSubComments}
key={item.permlink}
marginLeft={marginLeft}
handleOnLongPress={() => this._openCommentMenu(item)}
/>
)}
/>
<ActionSheet
ref={this.commentMenu}
options={menuItems}
title={get(selectedComment, 'summary')}
cancelButtonIndex={isOwnProfile ? 2 : 1}
onPress={index => handleOnPressCommentMenu(index, selectedComment)}
/>
</Fragment>
<TextButton
style={styles.moreRepliesButtonWrapper}
textStyle={styles.moreRepliesText}
onPress={() => _readMoreComments()}
text="Read more comments"
/>
);
}
}
export default injectIntl(CommentsView);
return (
<Fragment>
<FlatList
style={styles.list}
data={comments}
keyExtractor={_keyExtractor}
renderItem={({ item }) => (
<Comment
mainAuthor={mainAuthor}
avatarSize={avatarSize}
hideManyCommentsButton={hideManyCommentsButton}
comment={item}
commentCount={commentCount || get(item, 'children')}
commentNumber={commentNumber}
handleDeleteComment={handleDeleteComment}
currentAccountUsername={currentAccountUsername}
fetchPost={fetchPost}
handleOnEditPress={handleOnEditPress}
handleOnReplyPress={handleOnReplyPress}
handleOnUserPress={handleOnUserPress}
handleOnVotersPress={handleOnVotersPress}
isHideImage={isHideImage}
isLoggedIn={isLoggedIn}
isShowMoreButton={commentNumber === 1 && get(item, 'children') > 0}
showAllComments={showAllComments}
voteCount={get(item, 'vote_count')}
isShowSubComments={isShowSubComments}
key={get(item, 'permlink')}
marginLeft={marginLeft}
handleOnLongPress={() => _openCommentMenu(item)}
/>
)}
/>
<ActionSheet
ref={commentMenu}
options={menuItems}
title={get(selectedComment, 'summary')}
cancelButtonIndex={isOwnProfile ? 2 : 1}
onPress={index => handleOnPressCommentMenu(index, selectedComment)}
/>
</Fragment>
);
};
export default CommentsView;

View File

@ -221,25 +221,29 @@ class ProfileView extends PureComponent {
/>
)}
</View>
<View
tabLabel={
estimatedWalletValue
? `${currencySymbol} ${(estimatedWalletValue * currencyRate).toFixed()}`
: intl.formatMessage({
id: 'profile.wallet',
})
}
>
{selectedUser ? (
<Wallet
setEstimatedWalletValue={value => this.setState({ estimatedWalletValue: value })}
selectedUser={selectedUser}
handleOnScroll={isSummaryOpen ? this._handleOnScroll : null}
/>
) : (
<WalletDetailsPlaceHolder />
)}
</View>
{!isOwnProfile && (
<View
tabLabel={
estimatedWalletValue
? `${currencySymbol} ${(estimatedWalletValue * currencyRate).toFixed()}`
: intl.formatMessage({
id: 'profile.wallet',
})
}
>
{selectedUser ? (
<Wallet
setEstimatedWalletValue={value =>
this.setState({ estimatedWalletValue: value })
}
selectedUser={selectedUser}
handleOnScroll={isSummaryOpen ? this._handleOnScroll : null}
/>
) : (
<WalletDetailsPlaceHolder />
)}
</View>
)}
</ScrollableTabView>
</SafeAreaView>
</Fragment>

View File

@ -413,5 +413,8 @@
"current_time": "Current time;",
"information": "We noticed that your device has incorrect date or time. Please fix Date & Time or Set Automatically and try again."
}
},
"comments": {
"title": "Comments"
}
}
}

View File

@ -24,6 +24,7 @@ export default {
STEEM_CONNECT: `SteemConnect${SCREEN_SUFFIX}`,
TRANSFER: `Transfer${SCREEN_SUFFIX}`,
VOTERS: `Voters${SCREEN_SUFFIX}`,
COMMENTS: `Comments${SCREEN_SUFFIX}`,
},
DRAWER: {
MAIN: `Main${DRAWER_SUFFIX}`,

View File

@ -24,6 +24,7 @@ import {
SteemConnect,
Transfer,
Voters,
Comments,
} from '../screens';
// Components
@ -138,6 +139,12 @@ const stackNavigator = createStackNavigator(
header: () => null,
},
},
[ROUTES.SCREENS.COMMENTS]: {
screen: Comments,
navigationOptions: {
header: () => null,
},
},
},
{
headerMode: 'none',

View File

@ -0,0 +1,41 @@
import React from 'react';
import { View } from 'react-native';
import { useIntl } from 'react-intl';
import { BasicHeader, Comments } from '../../../components';
// Styles
import globalStyles from '../../../globalStyles';
const CommentsScreen = ({ navigation }) => {
const intl = useIntl();
const comments = navigation.getParam('comments', [{}])[0];
return (
<View style={globalStyles.container}>
<BasicHeader
title={intl.formatMessage({
id: 'comments.title',
})}
/>
<View style={globalStyles.containerHorizontal16}>
<Comments
isShowComments
author={comments.author}
mainAuthor={comments.author}
permlink={comments.permlink}
commentCount={comments.children}
isShowMoreButton={true}
isShowSubComments
showAllComments
fetchPost={navigation.getParam('fetchPost', null)}
handleOnVotersPress={navigation.getParam('handleOnVotersPress', null)}
hasManyComments={false}
hideManyCommentsButton
/>
</View>
</View>
);
};
export { CommentsScreen as Comments };

View File

@ -1,17 +1,18 @@
import { Bookmarks } from './bookmarks';
import { Comments } from './comments/screen/commentsScreen';
import { Drafts } from './drafts';
import { Editor } from './editor';
import { Follows } from './follows';
import { Feed } from './feed';
import { Follows } from './follows';
import { Launch } from './launch';
import { Login } from './login';
import { Notification } from './notification';
import { PinCode } from './pinCode';
import { Wallet } from './wallet';
import { Post } from './post';
import { SearchResult } from './searchResult';
import { Settings } from './settings';
import { SpinGame } from './spinGame/screen/spinGameScreen';
import { Wallet } from './wallet';
import Boost from './boost/screen/boostScreen';
import Profile from './profile/screen/profileScreen';
import ProfileEdit from './profileEdit/screen/profileEditScreen';
@ -24,15 +25,15 @@ import Voters from './voters';
export {
Bookmarks,
Boost,
Comments,
Drafts,
Editor,
Follows,
Feed,
Follows,
Launch,
Login,
Notification,
PinCode,
Wallet,
Post,
Profile,
ProfileEdit,
@ -44,4 +45,5 @@ export {
SteemConnect,
Transfer,
Voters,
Wallet,
};