Merge remote-tracking branch 'upstream/development' into nt/navigation

# Conflicts:
#	src/screens/register/registerScreen.js
This commit is contained in:
Nouman Tahir 2022-09-08 11:59:46 +05:00
commit 6580f79153
33 changed files with 761 additions and 486 deletions

View File

@ -144,7 +144,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode versionMajor * 10000 + versionMinor * 100 + versionPatch versionCode versionMajor * 10000 + versionMinor * 100 + versionPatch
versionName "3.0.33" versionName "3.0.34"
resValue "string", "build_config_package", "app.esteem.mobile.android" resValue "string", "build_config_package", "app.esteem.mobile.android"
multiDexEnabled true multiDexEnabled true
// react-native-image-crop-picker // react-native-image-crop-picker

View File

@ -10,6 +10,16 @@ public class SplashActivity extends AppCompatActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Intent intent = new Intent(this, MainActivity.class); Intent intent = new Intent(this, MainActivity.class);
//workaround for getInitialNotification and onNotificationOpenedApp returning null always
//TOOD: use react-native-bootsplash instead of react-native-splash-screen as recommended by firebase
//firebase issue ref: https://github.com/invertase/react-native-firebase/issues/3469
//ecency project card ref: https://github.com/orgs/ecency/projects/2#card-85455956
Bundle extras = getIntent().getExtras();
if (extras != null) {
intent.putExtras(extras);
}
startActivity(intent); startActivity(intent);
finish(); finish();
} }

View File

@ -15,11 +15,11 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.33</string> <string>3.0.34</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2812</string> <string>2813</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true /> <true />
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>

View File

@ -15,10 +15,10 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>BNDL</string> <string>BNDL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.33</string> <string>3.0.34</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2812</string> <string>2813</string>
</dict> </dict>
</plist> </plist>

View File

@ -1132,7 +1132,7 @@
CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_IDENTITY = "iPhone Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2812; CURRENT_PROJECT_VERSION = 2813;
DEAD_CODE_STRIPPING = NO; DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = 75B6RXTKGT; DEVELOPMENT_TEAM = 75B6RXTKGT;
EXCLUDED_ARCHS = ""; EXCLUDED_ARCHS = "";
@ -1211,7 +1211,7 @@
CODE_SIGN_ENTITLEMENTS = Ecency/Ecency.entitlements; CODE_SIGN_ENTITLEMENTS = Ecency/Ecency.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2812; CURRENT_PROJECT_VERSION = 2813;
DEAD_CODE_STRIPPING = NO; DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = 75B6RXTKGT; DEVELOPMENT_TEAM = 75B6RXTKGT;
EXCLUDED_ARCHS = ""; EXCLUDED_ARCHS = "";

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.33</string> <string>3.0.34</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>
@ -62,6 +62,8 @@
</dict> </dict>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>
<string>To access your photos, Ecency needs your permission to help you share your photos.</string> <string>To access your photos, Ecency needs your permission to help you share your photos.</string>
<key>NSFaceIDUsageDescription</key>
<string>Ecency requires FaceID access to allow you quick and secure access.</string>
<key>NSLocationAlwaysUsageDescription</key> <key>NSLocationAlwaysUsageDescription</key>
<string>To get accurate location for sharing</string> <string>To get accurate location for sharing</string>
<key>NSLocationWhenInUseUsageDescription</key> <key>NSLocationWhenInUseUsageDescription</key>
@ -74,8 +76,6 @@
<string>Photo Library Access for allowing user to download and upload photos</string> <string>Photo Library Access for allowing user to download and upload photos</string>
<key>NSPhotoLibraryUsageDescription</key> <key>NSPhotoLibraryUsageDescription</key>
<string>Photo Usage Access for allowing user to upload photos</string> <string>Photo Usage Access for allowing user to upload photos</string>
<key>NSFaceIDUsageDescription</key>
<string>Ecency requires FaceID access to allow you quick and secure access.</string>
<key>UIAppFonts</key> <key>UIAppFonts</key>
<array> <array>
<string>Entypo.ttf</string> <string>Entypo.ttf</string>

View File

@ -15,10 +15,10 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>BNDL</string> <string>BNDL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.33</string> <string>3.0.34</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2812</string> <string>2813</string>
</dict> </dict>
</plist> </plist>

View File

@ -17,9 +17,9 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.33</string> <string>3.0.34</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2812</string> <string>2813</string>
<key>NSExtension</key> <key>NSExtension</key>
<dict> <dict>
<key>NSExtensionAttributes</key> <key>NSExtensionAttributes</key>

View File

@ -1,6 +1,6 @@
{ {
"name": "ecency", "name": "ecency",
"version": "3.0.33", "version": "3.0.34",
"displayName": "Ecency", "displayName": "Ecency",
"private": true, "private": true,
"rnpm": { "rnpm": {

View File

@ -45,14 +45,15 @@ const CommentView = ({
incrementRepliesCount incrementRepliesCount
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
const actionSheet = useRef(null);
const dispatch = useDispatch(); const dispatch = useDispatch();
const actionSheet = useRef(null);
const repliesContainerRef = useRef<AnimatedView>(null);
const isMuted = useAppSelector(state => state.account.currentAccount.mutes?.indexOf(comment.author) > -1); const isMuted = useAppSelector(state => state.account.currentAccount.mutes?.indexOf(comment.author) > -1);
const lastCacheUpdate = useAppSelector((state) => state.cache.lastUpdate); const lastCacheUpdate = useAppSelector((state) => state.cache.lastUpdate);
const cachedComments = useAppSelector((state) => state.cache.comments); const cachedComments = useAppSelector((state) => state.cache.comments);
const [_isShowSubComments, setIsShowSubComments] = useState(isShowSubComments || false); const [_isShowSubComments, setIsShowSubComments] = useState(false);
const [isPressedShowButton, setIsPressedShowButton] = useState(false); const [isPressedShowButton, setIsPressedShowButton] = useState(false);
const [activeVotes, setActiveVotes] = useState([]); const [activeVotes, setActiveVotes] = useState([]);
const [cacheVoteIcrement, setCacheVoteIcrement] = useState(0); const [cacheVoteIcrement, setCacheVoteIcrement] = useState(0);
@ -61,6 +62,16 @@ const CommentView = ({
const [replies, setReplies] = useState(comment.replies); const [replies, setReplies] = useState(comment.replies);
useEffect(()=>{
if(isShowSubComments){
setTimeout(()=>{
if(repliesContainerRef.current){
setIsShowSubComments(true);
repliesContainerRef.current.slideInRight(300);
}
},150)
}
},[])
useEffect(() => { useEffect(() => {
if (comment) { if (comment) {
@ -81,71 +92,86 @@ const CommentView = ({
) { ) {
//TODO: update comment count and show sub comment if required; //TODO: update comment count and show sub comment if required;
const cachedComment = cachedComments.get(postPath); const cachedComment = cachedComments.get(postPath);
if(cachedComment.updated === cachedComment.created){ if (cachedComment.updated === cachedComment.created) {
if(commentNumber > 1 && incrementRepliesCount){ if (commentNumber > 1 && incrementRepliesCount) {
incrementRepliesCount(); incrementRepliesCount();
} }
setChildCount(childCount + 1); setChildCount(childCount + 1);
setReplies(replies ? [...replies, cachedComment] : [cachedComment]); setReplies(replies ? [...replies, cachedComment] : [cachedComment]);
} }
if(!_isShowSubComments){ if (!_isShowSubComments) {
_showSubCommentsToggle(true); _showSubCommentsToggle(true);
} }
} }
}, [lastCacheUpdate]); }, [lastCacheUpdate]);
const _showSubCommentsToggle = (force) => { const _showSubCommentsToggle = (force) => {
if(((replies && replies.length > 0) || force)){ if (((replies && replies.length > 0) || force)) {
setIsShowSubComments(!_isShowSubComments);
setIsPressedShowButton(true);
} else if(openReplyThread) {
openReplyThread();
}
}; if (repliesContainerRef.current) {
if (_isShowSubComments) {
const _handleCacheVoteIncrement = () => { repliesContainerRef.current.slideOutRight(300).then(()=>{
//fake increment vote using based on local change setIsShowSubComments(false);
setCacheVoteIcrement(1); });
}; } else {
setIsShowSubComments(true);
const _incrementRepliesCount = () => { repliesContainerRef.current.slideInRight(300);
if(commentNumber > 1 && incrementRepliesCount){ }
incrementRepliesCount();
}
setChildCount(childCount + 1);
}
const _handleOnReplyPress = () => {
if (isLoggedIn) {
dispatch(showReplyModal(comment));
} else {
console.log('Not LoggedIn');
}
}
const _renderReadMoreButton = () => (
<TextWithIcon
wrapperStyle={styles.rightButton}
textStyle={!isPressedShowButton && styles.moreText}
iconType="MaterialIcons"
isClickable
iconStyle={styles.iconStyle}
iconSize={16}
onPress={() => openReplyThread && openReplyThread()}
text={
!isPressedShowButton
? intl.formatMessage({ id: 'comments.read_more' })
: ''
} }
/>
) setIsPressedShowButton(true);
const _renderReplies = () => { } else if (openReplyThread) {
return ( openReplyThread();
<AnimatedView animation="zoomIn" duration={300}> }
};
const _handleCacheVoteIncrement = () => {
//fake increment vote using based on local change
setCacheVoteIcrement(1);
};
const _incrementRepliesCount = () => {
if (commentNumber > 1 && incrementRepliesCount) {
incrementRepliesCount();
}
setChildCount(childCount + 1);
}
const _handleOnReplyPress = () => {
if (isLoggedIn) {
dispatch(showReplyModal(comment));
} else {
console.log('Not LoggedIn');
}
}
const _renderReadMoreButton = () => (
<TextWithIcon
wrapperStyle={styles.rightButton}
textStyle={!isPressedShowButton && styles.moreText}
iconType="MaterialIcons"
isClickable
iconStyle={styles.iconStyle}
iconSize={16}
onPress={() => openReplyThread && openReplyThread()}
text={
!isPressedShowButton
? intl.formatMessage({ id: 'comments.read_more' })
: ''
}
/>
)
const _renderReplies = () => {
return (
<AnimatedView ref={repliesContainerRef}>
{_isShowSubComments &&
<Comments <Comments
isShowComments={isShowComments} isShowComments={isShowComments}
commentNumber={commentNumber + 1} commentNumber={commentNumber + 1}
@ -163,163 +189,163 @@ const CommentView = ({
fetchedAt={fetchedAt} fetchedAt={fetchedAt}
incrementRepliesCount={_incrementRepliesCount} incrementRepliesCount={_incrementRepliesCount}
handleOnReplyPress={_handleOnReplyPress} handleOnReplyPress={_handleOnReplyPress}
/> />}
</AnimatedView> </AnimatedView>
) )
} }
const _renderComment = () => { const _renderComment = () => {
return (( return ((
<View style={[{ marginLeft: 2, marginTop: -6 }]}> <View style={[{ marginLeft: 2, marginTop: -6 }]}>
<CommentBody <CommentBody
commentDepth={comment.depth} commentDepth={comment.depth}
reputation={comment.author_reputation} reputation={comment.author_reputation}
handleOnUserPress={handleOnUserPress} handleOnUserPress={handleOnUserPress}
handleOnLongPress={handleOnLongPress} handleOnLongPress={handleOnLongPress}
body={comment.body} body={comment.body}
created={comment.created} created={comment.created}
key={`key-${comment.permlink}`} key={`key-${comment.permlink}`}
isMuted={isMuted} isMuted={isMuted}
/> />
<Fragment> <Fragment>
<View style={styles.footerWrapper}> <View style={styles.footerWrapper}>
{_renderActionPanel()} {_renderActionPanel()}
</View> </View>
{ commentNumber > 1 && {commentNumber > 1 &&
childCount > 0 && childCount > 0 &&
!replies?.length && !replies?.length &&
_renderReadMoreButton() _renderReadMoreButton()
} }
</Fragment> </Fragment>
</View> </View>
)) ))
} }
const _renderActionPanel = () => { const _renderActionPanel = () => {
return ( return (
<> <>
<Upvote <Upvote
activeVotes={activeVotes} activeVotes={activeVotes}
isShowPayoutValue isShowPayoutValue
content={comment} content={comment}
handleCacheVoteIncrement={_handleCacheVoteIncrement} handleCacheVoteIncrement={_handleCacheVoteIncrement}
parentType={postTypes.COMMENT} parentType={postTypes.COMMENT}
/> />
<TextWithIcon <TextWithIcon
iconName="heart-outline" iconName="heart-outline"
iconSize={20} iconSize={20}
wrapperStyle={styles.leftButton} wrapperStyle={styles.leftButton}
iconType="MaterialCommunityIcons"
isClickable
onPress={() =>
handleOnVotersPress &&
activeVotes.length > 0 &&
handleOnVotersPress(activeVotes, comment)
}
text={activeVotes.length + cacheVoteIcrement}
textStyle={styles.voteCountText}
/>
{isLoggedIn && (
<IconButton
size={20}
iconStyle={styles.leftIcon}
style={styles.leftButton}
name="comment-outline"
onPress={_handleOnReplyPress}
iconType="MaterialCommunityIcons" iconType="MaterialCommunityIcons"
isClickable
onPress={() =>
handleOnVotersPress &&
activeVotes.length > 0 &&
handleOnVotersPress(activeVotes, comment)
}
text={activeVotes.length + cacheVoteIcrement}
textStyle={styles.voteCountText}
/> />
)}
{isLoggedIn && (
{currentAccountUsername === comment.author && (
<Fragment>
<IconButton <IconButton
size={20} size={20}
iconStyle={styles.leftIcon} iconStyle={styles.leftIcon}
style={styles.leftButton} style={styles.leftButton}
name="comment-outline" name="create"
onPress={_handleOnReplyPress} onPress={() => handleOnEditPress && handleOnEditPress(comment)}
iconType="MaterialCommunityIcons" iconType="MaterialIcons"
/> />
)} {!childCount && !activeVotes.length && comment.isDeletable && (
<Fragment>
<IconButton
size={20}
iconStyle={styles.leftIcon}
style={styles.leftButton}
name="delete-forever"
onPress={() => actionSheet.current.show()}
iconType="MaterialIcons"
/>
<OptionsModal
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>
)}
{currentAccountUsername === comment.author && ( {commentNumber === 1 && childCount > 0 && (
<Fragment> <View style={styles.rightButtonWrapper}>
<IconButton <TextWithIcon
size={20} wrapperStyle={styles.rightButton}
iconStyle={styles.leftIcon} iconName={_isShowSubComments ? 'keyboard-arrow-up' : 'keyboard-arrow-down'}
style={styles.leftButton} textStyle={styles.moreText}
name="create" iconType="MaterialIcons"
onPress={() => handleOnEditPress && handleOnEditPress(comment)} isClickable
iconType="MaterialIcons" iconStyle={styles.iconStyle}
/> iconSize={16}
{!childCount && !activeVotes.length && comment.isDeletable && ( onPress={() => _showSubCommentsToggle()}
<Fragment> text={`${childCount} ${intl.formatMessage({ id: 'comments.more_replies' })}`}
<IconButton />
size={20} </View>
iconStyle={styles.leftIcon} )}
style={styles.leftButton}
name="delete-forever"
onPress={() => actionSheet.current.show()}
iconType="MaterialIcons"
/>
<OptionsModal
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>
)}
</>
)
}
{commentNumber === 1 && childCount > 0 && ( const customContainerStyle = commentNumber > 2 ? { marginLeft: 44 } : null
<View style={styles.rightButtonWrapper}>
<TextWithIcon
wrapperStyle={styles.rightButton}
iconName={_isShowSubComments ? 'keyboard-arrow-up' : 'keyboard-arrow-down'}
textStyle={styles.moreText}
iconType="MaterialIcons"
isClickable
iconStyle={styles.iconStyle}
iconSize={16}
onPress={() => _showSubCommentsToggle()}
text={`${childCount} ${intl.formatMessage({ id: 'comments.more_replies' })}`}
/>
</View>
)}
</> return (
) <Fragment>
} <View style={{ ...styles.commentContainer, ...customContainerStyle }}>
<PostHeaderDescription
key={comment.permlink}
date={getTimeFromNow(comment.created)}
name={comment.author}
reputation={comment.author_reputation}
size={avatarSize || 40}
currentAccountUsername={currentAccountUsername}
isShowOwnerIndicator={mainAuthor === comment.author}
isHideImage={isHideImage}
inlineTime={true}
customStyle={{ alignItems: 'flex-start', paddingLeft: 12 }}
showDotMenuButton={true}
handleOnDotPress={handleOnLongPress}
secondaryContentComponent={_renderComment()}
/>
const customContainerStyle = commentNumber > 2 ? {marginLeft: 44}:null {commentNumber > 0 && _renderReplies()}
</View>
return ( </Fragment>
<Fragment> );
<View style={{...styles.commentContainer, ...customContainerStyle}}>
<PostHeaderDescription
key={comment.permlink}
date={getTimeFromNow(comment.created)}
name={comment.author}
reputation={comment.author_reputation}
size={avatarSize || 40}
currentAccountUsername={currentAccountUsername}
isShowOwnerIndicator={mainAuthor === comment.author}
isHideImage={isHideImage}
inlineTime={true}
customStyle={{alignItems:'flex-start', paddingLeft: 12}}
showDotMenuButton={true}
handleOnDotPress={handleOnLongPress}
secondaryContentComponent={_renderComment()}
/>
{_isShowSubComments && commentNumber > 0 && _renderReplies()}
</View>
</Fragment>
);
}; };
export default CommentView; export default CommentView;

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback } from 'react'; import React, { useState, useEffect } from 'react';
import { Platform } from 'react-native'; import { Platform } from 'react-native';
import { withNavigation } from '@react-navigation/compat'; import { withNavigation } from '@react-navigation/compat';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -19,7 +19,8 @@ import ROUTES from '../../../constants/routeNames';
// Component // Component
import CommentsView from '../view/commentsView'; import CommentsView from '../view/commentsView';
import { useAppSelector } from '../../../hooks'; import { useAppSelector } from '../../../hooks';
import { deleteCommentCacheEntry } from '../../../redux/actions/cacheActions'; import { updateCommentCache } from '../../../redux/actions/cacheActions';
import { CommentCacheStatus } from '../../../redux/reducers/cacheReducer';
const CommentsContainer = ({ const CommentsContainer = ({
author, author,
@ -66,7 +67,11 @@ const CommentsContainer = ({
}, [commentCount, selectedFilter]); }, [commentCount, selectedFilter]);
useEffect(() => { useEffect(() => {
setPropComments(comments); let _comments = comments;
if (_comments) {
_comments = _handleCachedComment(comments);
}
setPropComments(_comments);
}, [comments]); }, [comments]);
useEffect(() => { useEffect(() => {
@ -190,12 +195,15 @@ const CommentsContainer = ({
var ignoreCache = false; var ignoreCache = false;
var replaceAtIndex = -1; var replaceAtIndex = -1;
var removeAtIndex = -1;
_comments.forEach((comment, index) => { _comments.forEach((comment, index) => {
if (cachedComment.permlink === comment.permlink) { if (cachedComment.permlink === comment.permlink) {
if (cachedComment.updated < comment.updated) { if (cachedComment.updated < comment.updated) {
//comment is present with latest data //comment is present with latest data
ignoreCache = true; ignoreCache = true;
console.log('Ignore cache as comment is now present'); console.log('Ignore cache as comment is now present');
} else if (cachedComment.status === CommentCacheStatus.DELETED) {
removeAtIndex = index;
} else { } else {
//comment is present in list but data is old //comment is present in list but data is old
replaceAtIndex = index; replaceAtIndex = index;
@ -203,10 +211,18 @@ const CommentsContainer = ({
} }
}); });
//means deleted comment is not being retuend in fresh data, cache needs to be ignored
if (cachedComment.status === CommentCacheStatus.DELETED && removeAtIndex < 0) {
ignoreCache = true;
}
//manipulate comments with cached data //manipulate comments with cached data
if (!ignoreCache) { if (!ignoreCache) {
let newComments = []; let newComments = [];
if (replaceAtIndex >= 0) { if (removeAtIndex >= 0) {
newComments = _comments;
newComments.splice(removeAtIndex, 1);
} else if (replaceAtIndex >= 0) {
_comments[replaceAtIndex] = cachedComment; _comments[replaceAtIndex] = cachedComment;
newComments = [..._comments]; newComments = [..._comments];
} else { } else {
@ -266,10 +282,11 @@ const CommentsContainer = ({
let filteredComments; let filteredComments;
deleteComment(currentAccount, pinCode, _permlink).then(() => { deleteComment(currentAccount, pinCode, _permlink).then(() => {
let cachePath = null; let deletedItem = null;
const _applyFilter = (item) => { const _applyFilter = (item) => {
if (item.permlink === _permlink) { if (item.permlink === _permlink) {
cachePath = `${item.parent_author}/${item.parent_permlink}`; deletedItem = item;
return false; return false;
} }
return true; return true;
@ -284,7 +301,12 @@ const CommentsContainer = ({
} }
// remove cached entry based on parent // remove cached entry based on parent
dispatch(deleteCommentCacheEntry(cachePath)); if (deletedItem) {
const cachePath = `${deletedItem.parent_author}/${deletedItem.parent_permlink}`;
deletedItem.status = CommentCacheStatus.DELETED;
delete deletedItem.updated;
dispatch(updateCommentCache(cachePath, deletedItem, { isUpdate: true }));
}
}); });
}; };

View File

@ -18,4 +18,11 @@ export default EStyleSheet.create({
color: '$white', color: '$white',
fontSize: 10, fontSize: 10,
}, },
emptyText: {
color: '$primaryDarkGray',
fontSize: 16,
justifyContent: 'center',
marginTop: 5,
padding: 32,
},
}); });

View File

@ -1,5 +1,5 @@
import React, { useState, Fragment, useRef } from 'react'; import React, { useState, Fragment, useRef } from 'react';
import { FlatList } from 'react-native'; import { FlatList, Text } from 'react-native';
import get from 'lodash/get'; import get from 'lodash/get';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
@ -44,21 +44,21 @@ const CommentsView = ({
const _openCommentMenu = (item) => { const _openCommentMenu = (item) => {
if(commentMenu.current){ if (commentMenu.current) {
setSelectedComment(item); setSelectedComment(item);
commentMenu.current.show(); commentMenu.current.show();
} }
}; };
const _openReplyThread = (item) => { const _openReplyThread = (item) => {
if(item && openReplyThread){ if (item && openReplyThread) {
openReplyThread(item) openReplyThread(item)
} }
} }
const _readMoreComments = () => { const _readMoreComments = () => {
if(comments[0] && openReplyThread){ if (comments[0] && openReplyThread) {
openReplyThread(comments[0]) openReplyThread(comments[0])
} }
}; };
@ -111,7 +111,7 @@ const CommentsView = ({
key={get(item, 'permlink')} key={get(item, 'permlink')}
marginLeft={marginLeft} marginLeft={marginLeft}
handleOnLongPress={() => _openCommentMenu(item)} handleOnLongPress={() => _openCommentMenu(item)}
openReplyThread={()=> _openReplyThread(item)} openReplyThread={() => _openReplyThread(item)}
fetchedAt={fetchedAt} fetchedAt={fetchedAt}
incrementRepliesCount={incrementRepliesCount} incrementRepliesCount={incrementRepliesCount}
/> />
@ -120,19 +120,34 @@ const CommentsView = ({
const styleOerride = commentNumber > 1 ? { const styleOerride = commentNumber > 1 ? {
backgroundColor:EStyleSheet.value('$primaryLightBackground'), backgroundColor: EStyleSheet.value('$primaryLightBackground'),
marginTop:8, marginTop: 8,
}:null } : null
const _renderEmptyContent = () => {
if(commentNumber > 1){
return;
}
const _onPress = () => {
handleOnReplyPress()
}
return (
<Text onPress={_onPress} style={styles.emptyText}>
{intl.formatMessage({ id: "comments.no_comments" })}
</Text>
)
}
return ( return (
<Fragment> <Fragment>
<FlatList <FlatList
style={{...styles.list, ...styleOerride }} style={{ ...styles.list, ...styleOerride }}
contentContainerStyle={{padding:0}} contentContainerStyle={{ padding: 0 }}
data={comments} data={comments}
renderItem={_renderItem} renderItem={_renderItem}
keyExtractor={(item) => get(item, 'permlink')} keyExtractor={(item) => get(item, 'permlink')}
ListEmptyComponent={_renderEmptyContent()}
{...flatListProps} {...flatListProps}
/> />
<OptionsModal <OptionsModal

View File

@ -0,0 +1,27 @@
import EStyleSheet from 'react-native-extended-stylesheet';
export default EStyleSheet.create({
container: {
padding: 16,
height: 40,
flexDirection: 'row',
alignItems: 'center',
marginVertical: 16,
},
inputContainer: {
marginLeft: 12,
justifyContent: 'center',
height: 36,
borderRadius: 12,
flex: 1,
backgroundColor: '$primaryLightBackground',
borderWidth: EStyleSheet.hairlineWidth,
borderColor: '$primaryDarkGray',
},
inputPlaceholder: {
color: '$primaryDarkGray',
fontSize: 16,
marginTop: 5,
paddingHorizontal: 16,
},
});

View File

@ -1,3 +0,0 @@
import EStyleSheet from 'react-native-extended-stylesheet';
export default EStyleSheet.create({});

View File

@ -1,38 +1,52 @@
import React, { useState, Fragment } from 'react'; import React, { useState, Fragment, useImperativeHandle, forwardRef, useRef } from 'react';
import { View } from 'react-native'; import { View } from 'react-native';
import { injectIntl } from 'react-intl'; import { injectIntl, useIntl } from 'react-intl';
// Components // Components
import { FilterBar } from '../../filterBar'; import { FilterBar } from '../../filterBar';
import { Comments } from '../../comments'; import { Comments } from '../../comments';
import COMMENT_FILTER, { VALUE } from '../../../constants/options/comment'; import COMMENT_FILTER, { VALUE } from '../../../constants/options/comment';
import { WriteCommentButton } from './writeCommentButton';
// Styles const CommentsDisplayView = forwardRef(
import styles from './commentDisplayStyles'; (
{
author,
commentCount,
fetchPost,
permlink,
mainAuthor,
handleOnVotersPress,
handleOnReplyPress,
fetchedAt,
},
ref,
) => {
const intl = useIntl();
const CommentsDisplayView = ({ const writeCommentRef = useRef(null);
author,
commentCount,
fetchPost,
intl,
permlink,
mainAuthor,
handleOnVotersPress,
handleOnReplyPress,
fetchedAt,
}) => {
const [selectedFilter, setSelectedFilter] = useState('trending');
const [selectedOptionIndex, setSelectedOptionIndex] = useState(0);
const _handleOnDropdownSelect = (option, index) => { const [selectedFilter, setSelectedFilter] = useState('trending');
setSelectedFilter(option); const [selectedOptionIndex, setSelectedOptionIndex] = useState(0);
setSelectedOptionIndex(index);
};
return ( useImperativeHandle(ref, () => ({
<Fragment> bounceCommentButton: () => {
{commentCount > 0 && ( console.log('bouncing comment button');
if (writeCommentRef.current) {
writeCommentRef.current.bounce();
}
},
}));
const _handleOnDropdownSelect = (option, index) => {
setSelectedFilter(option);
setSelectedOptionIndex(index);
};
return (
<Fragment>
<Fragment> <Fragment>
<WriteCommentButton ref={writeCommentRef} onPress={handleOnReplyPress} />
<FilterBar <FilterBar
dropdownIconName="arrow-drop-down" dropdownIconName="arrow-drop-down"
options={VALUE.map((val) => intl.formatMessage({ id: `comment_filter.${val}` }))} options={VALUE.map((val) => intl.formatMessage({ id: `comment_filter.${val}` }))}
@ -56,9 +70,9 @@ const CommentsDisplayView = ({
/> />
</View> </View>
</Fragment> </Fragment>
)} </Fragment>
</Fragment> );
); },
}; );
export default injectIntl(CommentsDisplayView); export default CommentsDisplayView;

View File

@ -0,0 +1,56 @@
import { View, Text } from 'react-native'
import React, { forwardRef, useImperativeHandle, useRef } from 'react'
import UserAvatar from '../../userAvatar';
import { View as AnimatedView } from 'react-native-animatable';
import { TouchableOpacity } from 'react-native-gesture-handler';
import styles from './WriteCommentButtonStyles';
import { useAppSelector } from '../../../hooks';
import showLoginAlert from '../../../utils/showLoginAlert';
import { useIntl } from 'react-intl';
interface WriteCommentButton {
onPress: () => void;
}
export const WriteCommentButton = forwardRef(({ onPress }, ref) => {
const intl = useIntl();
const animatedContainer = useRef<AnimatedView>();
const isLoggedIn = useAppSelector(state => state.application.isLoggedIn);
useImperativeHandle(ref, () => ({
bounce: () => {
console.log("bouncing")
if (animatedContainer.current) {
animatedContainer.current.swing(1000);
}
},
}));
const _onPress = () => {
if (!isLoggedIn) {
showLoginAlert({ intl })
return;
}
if (onPress) {
onPress();
}
}
return (
<AnimatedView ref={animatedContainer}>
<TouchableOpacity onPress={_onPress}>
<View style={styles.container}>
<UserAvatar username="demo.com" />
<View style={styles.inputContainer}>
<Text style={styles.inputPlaceholder}>
{intl.formatMessage({id:'quick_reply.placeholder'})}
</Text>
</View>
</View>
</TouchableOpacity>
</AnimatedView>
)
})

View File

@ -1,6 +1,7 @@
import { get, isEmpty, some } from 'lodash'; import { get } from 'lodash';
import React, { useEffect, useRef, useState} from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { Animated, Text, TouchableOpacity, View } from 'react-native'; import { Text, TouchableOpacity, View } from 'react-native';
import { View as AnimatedView } from 'react-native-animatable';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { IconButton } from '..'; import { IconButton } from '..';
import { toastNotification } from '../../redux/actions/uiAction'; import { toastNotification } from '../../redux/actions/uiAction';
@ -13,148 +14,136 @@ import { navigate } from '../../navigation/service';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
interface RemoteMessage { interface RemoteMessage {
data:{ data: {
id:string; id: string;
source:string; source: string;
target:string; target: string;
permlink1:string; permlink1: string;
permlink2:string; permlink2: string;
permlink3:string; permlink3: string;
type:'mention'|'reply'; type: 'mention' | 'reply';
}; };
notification:{ notification: {
body:string; body: string;
title:string; title: string;
} }
} }
interface Props { interface Props {
remoteMessage:RemoteMessage remoteMessage: RemoteMessage
} }
const ForegroundNotification = ({remoteMessage}:Props) => { const ForegroundNotification = ({ remoteMessage }: Props) => {
let hideTimeout = null; const intl = useIntl();
const dispatch = useDispatch();
const intl = useIntl();
const [duration] = useState(5000); const hideTimeoutRef = useRef<any>(null);
const [activeId, setActiveId] = useState(''); const containerRef = useRef<AnimatedView>(null);
const [isVisible, setIsVisible] = useState(false);
const [username, setUsername] = useState(''); const [duration] = useState(5000);
const [title, setTitle] = useState(''); const [activeId, setActiveId] = useState('');
const [body, setBody] = useState(''); const [isVisible, setIsVisible] = useState(false);
const [username, setUsername] = useState('');
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
const animatedValue = useRef(new Animated.Value(-CONTAINER_HEIGHT)).current; useEffect(() => {
if (remoteMessage) {
const { source, target, type, id } = remoteMessage.data;
if (activeId !== id && (type === 'reply' || type === 'mention')) {
useEffect(() => { let titlePrefixId = '';
switch (type) {
if(remoteMessage){ case 'reply':
const {source, target, type, id} = remoteMessage.data; titlePrefixId = 'notification.reply_on'
if(activeId !== id && (type === 'reply' || type === 'mention')){ break;
case 'mention':
let titlePrefixId = ''; titlePrefixId = 'notification.mention_on'
switch(type){ break;
case 'reply':
titlePrefixId = 'notification.reply_on'
break;
case 'mention':
titlePrefixId = 'notification.mention_on'
break;
}
setActiveId(id);
setUsername(source);
setTitle(`${intl.formatMessage({id:titlePrefixId})} @${target}`)
setBody(intl.formatMessage({id:'notification.reply_body'}));
show();
} }
setActiveId(id);
setUsername(source);
setTitle(`${intl.formatMessage({ id: titlePrefixId })} @${target}`)
setBody(intl.formatMessage({ id: 'notification.reply_body' }));
show();
} }
}
return ()=>{ return () => {
if(hideTimeout){ if (hideTimeoutRef.current) {
clearTimeout(hideTimeout); clearTimeout(hideTimeoutRef.current);
}
} }
}, [remoteMessage]); }
}, [remoteMessage]);
const show = () => { const show = () => {
// Will change fadeAnim value to 1 in 5 seconds setIsVisible(true)
Animated.timing(animatedValue, { hideTimeoutRef.current = setTimeout(() => {
toValue: 0, hide();
duration: 350 }, duration)
}).start();
setIsVisible(true); };
hideTimeout = setTimeout(()=>{ const hide = async () => {
hide(); if (containerRef.current) {
}, duration) await containerRef.current.fadeOutUp(300);
}; setIsVisible(false);
if(hideTimeoutRef.current){
const hide = () => { clearTimeout(hideTimeoutRef.current);
if(hideTimeout || isVisible){
// Will change fadeAnim value to 0 in 3 seconds
Animated.timing(animatedValue, {
toValue: -CONTAINER_HEIGHT,
duration: 200
}).start(()=>{
dispatch(toastNotification(''))
});
setIsVisible(false);
clearTimeout(hideTimeout);
} }
};
const _onPress = () => {
const {data} = remoteMessage;
const fullPermlink =
get(data, 'permlink1', '') + get(data, 'permlink2', '') + get(data, 'permlink3', '');
let params = {
author: get(remoteMessage, 'source', ''),
permlink: fullPermlink,
};
let key = fullPermlink
let routeName = ROUTES.SCREENS.POST;
navigate({
routeName,
params,
key,
});
} }
};
const _onPress = () => {
const { data } = remoteMessage;
const fullPermlink =
get(data, 'permlink1', '') + get(data, 'permlink2', '') + get(data, 'permlink3', '');
let params = {
author: get(data, 'source', ''),
permlink: fullPermlink,
};
let key = fullPermlink
let routeName = ROUTES.SCREENS.POST;
navigate({
routeName,
params,
key,
});
hide();
}
return ( return (
<Animated.View isVisible &&
style={{ <AnimatedView
...styles.container, ref={containerRef}
transform: [{ translateY: animatedValue }], style={styles.container}
}} animation='slideInDown'
> duration={500}>
<View style={styles.contentContainer}> <View style={styles.contentContainer}>
<TouchableOpacity onPress={_onPress} style={{flexShrink:1}}> <TouchableOpacity onPress={_onPress} style={{ flexShrink: 1 }}>
<View style={{flexDirection:'row', alignItems:'center', marginRight:24}}> <View style={{ flexDirection: 'row', alignItems: 'center', marginRight: 24 }}>
<UserAvatar username={username}/> <UserAvatar username={username} />
<View style={{flexShrink:1}}> <View style={{ flexShrink: 1 }}>
<Text style={styles.text} numberOfLines={1}>{title}</Text> <Text style={styles.text} numberOfLines={1}>{title}</Text>
<Text style={styles.text} numberOfLines={1}>{body}</Text> <Text style={styles.text} numberOfLines={1}>{body}</Text>
</View> </View>
</View> </View>
</TouchableOpacity> </TouchableOpacity>
<IconButton <IconButton
name='close' name='close'
color="white" color="white"
@ -162,8 +151,7 @@ const ForegroundNotification = ({remoteMessage}:Props) => {
onPress={hide} onPress={hide}
/> />
</View> </View>
</AnimatedView>
</Animated.View>
) )
} }

View File

@ -16,7 +16,7 @@ export default EStyleSheet.create({
ios:getStatusBarHeight() + 12, ios:getStatusBarHeight() + 12,
android:8, android:8,
}), }),
backgroundColor: '$primaryDarkText', backgroundColor: '$darkGrayBackground',
shadowColor: '#5f5f5fbf', shadowColor: '#5f5f5fbf',
shadowOpacity: 0.3, shadowOpacity: 0.3,
shadowOffset: { shadowOffset: {

View File

@ -26,6 +26,8 @@ interface Props extends TextInputProps {
inputStyle:TextStyle; inputStyle:TextStyle;
isValid:boolean; isValid:boolean;
onChange?:(value:string)=>void; onChange?:(value:string)=>void;
onFocus?:()=>void;
onBlur?:()=>void;
} }
const FormInputView = ({ const FormInputView = ({
@ -44,6 +46,7 @@ const FormInputView = ({
isValid, isValid,
value, value,
onBlur, onBlur,
onFocus,
...props ...props
}:Props) => { }:Props) => {
const [_value, setValue] = useState(value || ''); const [_value, setValue] = useState(value || '');
@ -62,6 +65,9 @@ const FormInputView = ({
const _handleOnFocus = () => { const _handleOnFocus = () => {
setInputBorderColor('#357ce6'); setInputBorderColor('#357ce6');
if(onFocus){
onFocus();
}
}; };
const _handleOnBlur = () => { const _handleOnBlur = () => {

View File

@ -1,43 +1,67 @@
import React from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { View as AnimatedView } from 'react-native-animatable' import { View as AnimatedView } from 'react-native-animatable'
import { Portal } from 'react-native-portalize'; import { Portal } from 'react-native-portalize';
import styles from '../children/inputSupportModal.styles'; import styles from '../children/inputSupportModal.styles';
import { KeyboardAvoidingView, Platform, View } from 'react-native'; import { KeyboardAvoidingView, Platform, View } from 'react-native';
export interface InputSupportModalProps { export interface InputSupportModalProps {
visible:boolean; visible: boolean;
onClose:()=>void; onClose: () => void;
children?:any children?: any
} }
export const InputSupportModal = ({children, visible, onClose}: InputSupportModalProps, ref) => { export const InputSupportModal = ({ children, visible, onClose }: InputSupportModalProps, ref) => {
const container = useRef<AnimatedView>(null);
const innerContainer = useRef<AnimatedView>(null);
const [showModal, setShowModal] = useState(visible);
useEffect(() => {
if (visible) {
setShowModal(true);
}
else if (!visible && container.current && innerContainer.current) {
innerContainer.current.slideOutDown(1000)
setTimeout(async () => {
await container.current?.fadeOut(200)
setShowModal(false);
}, 300)
}
}, [visible])
return ( return showModal && (
<Portal> <Portal>
{
visible && (
<AnimatedView
style={styles.container}
duration={300}
animation='fadeInUp'>
<>
<View style={styles.container} onTouchEnd={onClose} />
{
Platform.select({
ios: (
<KeyboardAvoidingView behavior="padding" style={{backgroundColor: 'rgba(0, 0, 0, 0.2)'}}>
{children}
</KeyboardAvoidingView>
),
android: <View>{children}</View>,
})
}
</> <AnimatedView
</AnimatedView> ref={container}
) animation='fadeIn'
} duration={300}
style={styles.container} >
<AnimatedView
ref={innerContainer}
style={{ flex: 1 }}
animation='slideInUp'
duration={300}>
<View
style={{ flex: 1 }}
onTouchEnd={onClose} />
{
Platform.select({
ios: (
<KeyboardAvoidingView behavior="padding" style={{}}>
{children}
</KeyboardAvoidingView>
),
android: <View>{children}</View>,
})
}
</AnimatedView>
</AnimatedView>
</Portal> </Portal>
); );
}; };

View File

@ -1,4 +1,3 @@
import { Dimensions } from 'react-native';
import EStyleSheet from 'react-native-extended-stylesheet'; import EStyleSheet from 'react-native-extended-stylesheet';
import getWindowDimensions from '../../../utils/getWindowDimensions'; import getWindowDimensions from '../../../utils/getWindowDimensions';
@ -14,7 +13,8 @@ export default EStyleSheet.create({
backgroundColor: '$primaryBackgroundColor', backgroundColor: '$primaryBackgroundColor',
}, },
headerLine: { headerLine: {
bottom: 10, marginTop: -4,
marginBottom: 4,
}, },
title: { title: {
fontSize: 24, fontSize: 24,

View File

@ -1,10 +1,9 @@
import React, { useCallback, useEffect, useRef, useState, Fragment } from 'react'; import React, { useCallback, useEffect, useRef, useState, Fragment } from 'react';
import { View, Text, ScrollView, SafeAreaView, RefreshControl } from 'react-native'; import { View, Text, ScrollView, RefreshControl } from 'react-native';
import { injectIntl } from 'react-intl'; import { injectIntl } from 'react-intl';
import get from 'lodash/get'; import get from 'lodash/get';
// Providers // Providers
import { useSelector } from 'react-redux';
import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { userActivity } from '../../../providers/ecency/ePoint'; import { userActivity } from '../../../providers/ecency/ePoint';
@ -22,7 +21,6 @@ import { ParentPost } from '../../parentPost';
// Styles // Styles
import styles from './postDisplayStyles'; import styles from './postDisplayStyles';
import { OptionsModal } from '../../atoms'; import { OptionsModal } from '../../atoms';
import { QuickReplyModal } from '../..';
import getWindowDimensions from '../../../utils/getWindowDimensions'; import getWindowDimensions from '../../../utils/getWindowDimensions';
import { useAppDispatch } from '../../../hooks'; import { useAppDispatch } from '../../../hooks';
import { showReplyModal } from '../../../redux/actions/uiAction'; import { showReplyModal } from '../../../redux/actions/uiAction';
@ -37,7 +35,6 @@ const PostDisplayView = ({
isNewPost, isNewPost,
fetchPost, fetchPost,
handleOnEditPress, handleOnEditPress,
handleOnReplyPress,
handleOnVotersPress, handleOnVotersPress,
handleOnReblogsPress, handleOnReblogsPress,
post, post,
@ -53,6 +50,11 @@ const PostDisplayView = ({
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const commentsRef = useRef<CommentsDisplay>();
const scrollRef = useRef<ScrollView>();
const commentsReached = useRef<boolean>(false);
const [postHeight, setPostHeight] = useState(0); const [postHeight, setPostHeight] = useState(0);
const [scrollHeight, setScrollHeight] = useState(0); const [scrollHeight, setScrollHeight] = useState(0);
const [cacheVoteIcrement, setCacheVoteIcrement] = useState(0); const [cacheVoteIcrement, setCacheVoteIcrement] = useState(0);
@ -87,16 +89,30 @@ const PostDisplayView = ({
const _handleOnScroll = (event) => { const _handleOnScroll = (event) => {
const { y } = event.nativeEvent.contentOffset; const { y } = event.nativeEvent.contentOffset;
console.log("scroll height", y)
setScrollHeight(HEIGHT + y); setScrollHeight(HEIGHT + y);
const _commentButtonBounceOffset = y + (HEIGHT/1.7);
if(!commentsReached.current && commentsRef.current && _commentButtonBounceOffset > postHeight ){
commentsRef.current.bounceCommentButton();
commentsReached.current = true;
}
}; };
const _handleOnPostLayout = (event) => { const _handleOnPostLayout = (event) => {
const { height } = event.nativeEvent.layout; const { height } = event.nativeEvent.layout;
console.log('post height', height)
setPostHeight(height); setPostHeight(height);
}; };
const _scrollToComments = () => {
if(scrollRef.current){
const pos = postHeight;
scrollRef.current.scrollTo({y:pos})
}
}
const _handleOnReblogsPress = () => { const _handleOnReblogsPress = () => {
if (reblogs.length > 0 && handleOnReblogsPress) { if (reblogs.length > 0 && handleOnReblogsPress) {
handleOnReblogsPress(); handleOnReblogsPress();
@ -144,7 +160,7 @@ const PostDisplayView = ({
isClickable isClickable
text={get(post, 'children', 0)} text={get(post, 'children', 0)}
textMarginLeft={20} textMarginLeft={20}
onPress={() => _showQuickReplyModal(post)} onPress={() => _scrollToComments()}
// onPress={() => handleOnReplyPress && handleOnReplyPress()} // onPress={() => handleOnReplyPress && handleOnReplyPress()}
/> />
)} )}
@ -211,9 +227,9 @@ const PostDisplayView = ({
}; };
// show quick reply modal // show quick reply modal
const _showQuickReplyModal = (post) => { const _showQuickReplyModal = (_post = post) => {
if (isLoggedIn) { if (isLoggedIn) {
dispatch(showReplyModal(post)); dispatch(showReplyModal(_post));
} else { } else {
console.log('Not LoggedIn'); console.log('Not LoggedIn');
} }
@ -222,6 +238,7 @@ const PostDisplayView = ({
return ( return (
<View style={styles.container}> <View style={styles.container}>
<ScrollView <ScrollView
ref={scrollRef}
style={styles.scroll} style={styles.scroll}
contentContainerStyle={[styles.scrollContent]} contentContainerStyle={[styles.scrollContent]}
onScroll={(event) => _handleOnScroll(event)} onScroll={(event) => _handleOnScroll(event)}
@ -262,7 +279,9 @@ const PostDisplayView = ({
)} )}
</View> </View>
{post && !postBodyLoading && (isGetComment || isLoadedComments) && ( {post && !postBodyLoading && (isGetComment || isLoadedComments) && (
<CommentsDisplay
<CommentsDisplay
ref={commentsRef}
author={author || post.author} author={author || post.author}
mainAuthor={author || post.author} mainAuthor={author || post.author}
permlink={post.permlink} permlink={post.permlink}

View File

@ -724,7 +724,8 @@
"title": "Comments", "title": "Comments",
"reveal_comment": "Reveal comment", "reveal_comment": "Reveal comment",
"read_more": "Read more comments", "read_more": "Read more comments",
"more_replies": "replies" "more_replies": "replies",
"no_comments":"Be the first to respond..."
}, },
"search_result": { "search_result": {
"others": "Others", "others": "Others",
@ -817,7 +818,7 @@
"year":"years" "year":"years"
}, },
"quick_reply":{ "quick_reply":{
"placeholder":"Add a comment", "placeholder":"Add a comment...",
"comment": "Comment", "comment": "Comment",
"reply": "REPLY", "reply": "REPLY",
"close":"CLOSE" "close":"CLOSE"

View File

@ -252,7 +252,7 @@
"feedback_fail": "Ocurrió un error al intentar abrir el cliente del correo electrónico", "feedback_fail": "Ocurrió un error al intentar abrir el cliente del correo electrónico",
"server_fail": "Servidor no disponible", "server_fail": "Servidor no disponible",
"show_imgs": "Mostrar imágenes", "show_imgs": "Mostrar imágenes",
"delete_account": "Delete Account" "delete_account": "Eliminar cuenta"
}, },
"voters": { "voters": {
"voters_info": "Información de votantes", "voters_info": "Información de votantes",
@ -550,9 +550,9 @@
"confirm_report_body": "¿Estás seguro de que quieres reportar?" "confirm_report_body": "¿Estás seguro de que quieres reportar?"
}, },
"delete": { "delete": {
"confirm_delete_title": "Confirm Delete", "confirm_delete_title": "Confirmar eliminación",
"confirm_delete_body": "Are you sure you want to delete account? It will erase all of your data", "confirm_delete_body": "¿Estás seguro de que deseas eliminar la cuenta? Se borrarán todos tus datos",
"request_sent": "Your request for deletion is sent" "request_sent": "Su solicitud de eliminación está enviada"
}, },
"favorites": { "favorites": {
"title": "Favoritos", "title": "Favoritos",

View File

@ -252,7 +252,7 @@
"feedback_fail": "Sähköpostipalvelin alhaalla", "feedback_fail": "Sähköpostipalvelin alhaalla",
"server_fail": "Ei yhteyttä palvelimeen", "server_fail": "Ei yhteyttä palvelimeen",
"show_imgs": "Näytä kuvat", "show_imgs": "Näytä kuvat",
"delete_account": "Delete Account" "delete_account": "Poista tili"
}, },
"voters": { "voters": {
"voters_info": "Äänestystiedot", "voters_info": "Äänestystiedot",
@ -269,8 +269,8 @@
"login": "KIRJAUDU SISÄÄN", "login": "KIRJAUDU SISÄÄN",
"steemconnect_description": "Jos et halua säilyttää kryptattua salasanaa laitteessasi, voit käyttää Hivesigneriä.", "steemconnect_description": "Jos et halua säilyttää kryptattua salasanaa laitteessasi, voit käyttää Hivesigneriä.",
"steemconnect_fee_description": "tietoa", "steemconnect_fee_description": "tietoa",
"not_loggedin_alert": "Not LoggedIn", "not_loggedin_alert": "Ei Kirjautunut",
"not_loggedin_alert_desc": "Please login first" "not_loggedin_alert_desc": "Kirjaudu ensin sisään"
}, },
"register": { "register": {
"button": "Luo tili", "button": "Luo tili",
@ -550,9 +550,9 @@
"confirm_report_body": "Haluatko varmasti tehdä ilmiannon?" "confirm_report_body": "Haluatko varmasti tehdä ilmiannon?"
}, },
"delete": { "delete": {
"confirm_delete_title": "Confirm Delete", "confirm_delete_title": "Vahvista poistaminen",
"confirm_delete_body": "Are you sure you want to delete account? It will erase all of your data", "confirm_delete_body": "Oletko varma, että haluat poistaa tilin? Se poistaa kaikki tietosi",
"request_sent": "Your request for deletion is sent" "request_sent": "Pyyntösi poistamisesta on lähetetty"
}, },
"favorites": { "favorites": {
"title": "Suosikit", "title": "Suosikit",
@ -592,7 +592,7 @@
"pin-community": "Kiinnitä yhteisölle", "pin-community": "Kiinnitä yhteisölle",
"unpin-community": "Poista kiinnitys yhteisöstä", "unpin-community": "Poista kiinnitys yhteisöstä",
"edit-history": "Muokkaushistoria", "edit-history": "Muokkaushistoria",
"mute": "Mute / Block" "mute": "Mykistä / Estä"
}, },
"deep_link": { "deep_link": {
"no_existing_user": "Käyttäjää ei ole", "no_existing_user": "Käyttäjää ei ole",

View File

@ -10,9 +10,9 @@ import {
DELETE_DRAFT_CACHE_ENTRY, DELETE_DRAFT_CACHE_ENTRY,
UPDATE_SUBSCRIBED_COMMUNITY_CACHE, UPDATE_SUBSCRIBED_COMMUNITY_CACHE,
DELETE_SUBSCRIBED_COMMUNITY_CACHE, DELETE_SUBSCRIBED_COMMUNITY_CACHE,
CLEAR_SUBSCRIBED_COMMUNITIES_CACHE, CLEAR_SUBSCRIBED_COMMUNITIES_CACHE
} from '../constants/constants'; } from '../constants/constants';
import { Comment, Draft, SubscribedCommunity, Vote } from '../reducers/cacheReducer'; import { Comment, CommentCacheStatus, Draft, SubscribedCommunity, Vote } from '../reducers/cacheReducer';
@ -46,6 +46,8 @@ export const updateCommentCache = (commentPath: string, comment: Comment, option
throw new Error("either of json_metadata in comment data or parentTags in options must be provided"); throw new Error("either of json_metadata in comment data or parentTags in options must be provided");
} }
comment.created = comment.created || updatedStamp; //created will be set only once for new comment; comment.created = comment.created || updatedStamp; //created will be set only once for new comment;
comment.updated = comment.updated || updatedStamp; comment.updated = comment.updated || updatedStamp;
comment.expiresAt = comment.expiresAt || updated.getTime() + 6000000;//600000; comment.expiresAt = comment.expiresAt || updated.getTime() + 6000000;//600000;
@ -55,6 +57,7 @@ export const updateCommentCache = (commentPath: string, comment: Comment, option
comment.total_payout = comment.total_payout || 0; comment.total_payout = comment.total_payout || 0;
comment.json_metadata = comment.json_metadata || makeJsonMetadataReply(options.parentTags) comment.json_metadata = comment.json_metadata || makeJsonMetadataReply(options.parentTags)
comment.isDeletable = comment.isDeletable || true; comment.isDeletable = comment.isDeletable || true;
comment.status = comment.status || CommentCacheStatus.PENDING;
comment.body = renderPostBody({ comment.body = renderPostBody({
author: comment.author, author: comment.author,

View File

@ -1,4 +1,10 @@
import { PURGE_EXPIRED_CACHE, UPDATE_VOTE_CACHE, UPDATE_COMMENT_CACHE, DELETE_COMMENT_CACHE_ENTRY, DELETE_DRAFT_CACHE_ENTRY, UPDATE_DRAFT_CACHE, UPDATE_SUBSCRIBED_COMMUNITY_CACHE, DELETE_SUBSCRIBED_COMMUNITY_CACHE, CLEAR_SUBSCRIBED_COMMUNITIES_CACHE, } from "../constants/constants"; import { PURGE_EXPIRED_CACHE, UPDATE_VOTE_CACHE, UPDATE_COMMENT_CACHE, DELETE_COMMENT_CACHE_ENTRY, DELETE_DRAFT_CACHE_ENTRY, UPDATE_DRAFT_CACHE, UPDATE_SUBSCRIBED_COMMUNITY_CACHE, DELETE_SUBSCRIBED_COMMUNITY_CACHE, CLEAR_SUBSCRIBED_COMMUNITIES_CACHE, UPDATE_COMMENT_CACHE_ENTRY_STATUS, } from "../constants/constants";
export enum CommentCacheStatus {
PENDING = 'PENDING',
POSTPONED = 'PUBLISHED',
DELETED = 'DELETED',
}
export interface Vote { export interface Vote {
amount: number; amount: number;
@ -24,6 +30,7 @@ export interface Comment {
created?: string, //handle created and updated separatly created?: string, //handle created and updated separatly
updated?: string, updated?: string,
expiresAt?: number, expiresAt?: number,
status: CommentCacheStatus
} }
export interface Draft { export interface Draft {

View File

@ -18,7 +18,6 @@ import SplashScreen from 'react-native-splash-screen'
// Constants // Constants
import AUTH_TYPE from '../../../constants/authType'; import AUTH_TYPE from '../../../constants/authType';
import ROUTES from '../../../constants/routeNames'; import ROUTES from '../../../constants/routeNames';
import postUrlParser from '../../../utils/postUrlParser';
// Services // Services
import { import {
@ -34,7 +33,7 @@ import {
setLastUpdateCheck, setLastUpdateCheck,
getTheme, getTheme,
} from '../../../realm/realm'; } from '../../../realm/realm';
import { getUser, getPost, getDigitPinCode, getMutes } from '../../../providers/hive/dhive'; import { getUser, getDigitPinCode, getMutes } from '../../../providers/hive/dhive';
import { getPointsSummary } from '../../../providers/ecency/ePoint'; import { getPointsSummary } from '../../../providers/ecency/ePoint';
import { import {
migrateToMasterKeyWithAccessToken, migrateToMasterKeyWithAccessToken,
@ -62,7 +61,6 @@ import {
login, login,
logoutDone, logoutDone,
setConnectivityStatus, setConnectivityStatus,
setAnalyticsStatus,
setPinCode as savePinCode, setPinCode as savePinCode,
isRenderRequired, isRenderRequired,
logout, logout,
@ -85,21 +83,12 @@ import lightTheme from '../../../themes/lightTheme';
import persistAccountGenerator from '../../../utils/persistAccountGenerator'; import persistAccountGenerator from '../../../utils/persistAccountGenerator';
import parseVersionNumber from '../../../utils/parseVersionNumber'; import parseVersionNumber from '../../../utils/parseVersionNumber';
import { setMomentLocale } from '../../../utils/time'; import { setMomentLocale } from '../../../utils/time';
import parseAuthUrl from '../../../utils/parseAuthUrl';
import { purgeExpiredCache } from '../../../redux/actions/cacheActions'; import { purgeExpiredCache } from '../../../redux/actions/cacheActions';
import { fetchSubscribedCommunities } from '../../../redux/actions/communitiesAction'; import { fetchSubscribedCommunities } from '../../../redux/actions/communitiesAction';
import MigrationHelpers from '../../../utils/migrationHelpers'; import MigrationHelpers from '../../../utils/migrationHelpers';
import { deepLinkParser } from '../../../utils/deepLinkParser'; import { deepLinkParser } from '../../../utils/deepLinkParser';
import bugsnapInstance from '../../../config/bugsnag';
// Workaround
let previousAppState = 'background';
export const setPreviousAppState = () => {
previousAppState = AppState.currentState;
const appStateTimeout = setTimeout(() => {
previousAppState = AppState.currentState;
clearTimeout(appStateTimeout);
}, 500);
};
let firebaseOnNotificationOpenedAppListener = null; let firebaseOnNotificationOpenedAppListener = null;
let firebaseOnMessageListener = null; let firebaseOnMessageListener = null;
@ -131,7 +120,6 @@ class ApplicationContainer extends Component {
}); });
AppState.addEventListener('change', this._handleAppStateChange); AppState.addEventListener('change', this._handleAppStateChange);
setPreviousAppState();
this.removeAppearanceListener = Appearance.addChangeListener(this._appearanceChangeListener); this.removeAppearanceListener = Appearance.addChangeListener(this._appearanceChangeListener);
@ -338,7 +326,7 @@ class ApplicationContainer extends Component {
if (appState.match(/active|forground/) && nextAppState === 'inactive') { if (appState.match(/active|forground/) && nextAppState === 'inactive') {
this._startPinCodeTimer(); this._startPinCodeTimer();
} }
setPreviousAppState();
this.setState({ this.setState({
appState: nextAppState, appState: nextAppState,
}); });
@ -375,7 +363,7 @@ class ApplicationContainer extends Component {
let key = null; let key = null;
let routeName = null; let routeName = null;
if (previousAppState !== 'active' && !!notification) { if (!!notification) {
const push = get(notification, 'data'); const push = get(notification, 'data');
const type = get(push, 'type', ''); const type = get(push, 'type', '');
const fullPermlink = const fullPermlink =
@ -477,11 +465,11 @@ class ApplicationContainer extends Component {
firebaseOnMessageListener = messaging().onMessage((remoteMessage) => { firebaseOnMessageListener = messaging().onMessage((remoteMessage) => {
console.log('Notification Received: foreground', remoteMessage); console.log('Notification Received: foreground', remoteMessage);
// this._showNotificationToast(remoteMessage);
this.setState({ this.setState({
foregroundNotificationData: remoteMessage, foregroundNotificationData: remoteMessage,
}); });
this._pushNavigate(remoteMessage);
}); });
firebaseOnNotificationOpenedAppListener = messaging().onNotificationOpenedApp( firebaseOnNotificationOpenedAppListener = messaging().onNotificationOpenedApp(
@ -672,26 +660,40 @@ class ApplicationContainer extends Component {
//update notification settings and update push token for each signed accoutn useing access tokens //update notification settings and update push token for each signed accoutn useing access tokens
_registerDeviceForNotifications = (settings?:any) => { _registerDeviceForNotifications = (settings?: any) => {
const { otherAccounts, notificationDetails, isNotificationsEnabled } = this.props; const { currentAccount, otherAccounts, notificationDetails, isNotificationsEnabled } = this.props;
const isEnabled = settings ? !!settings.notification : isNotificationsEnabled; const isEnabled = settings ? !!settings.notification : isNotificationsEnabled;
settings = settings || notificationDetails; settings = settings || notificationDetails;
const _enabledNotificationForAccount = (account) => {
//updateing fcm token with settings;
otherAccounts.forEach((account) => {
//since there can be more than one accounts, process access tokens separate
const encAccessToken = account?.local?.accessToken; const encAccessToken = account?.local?.accessToken;
//decrypt access token //decrypt access token
let accessToken = null; let accessToken = null;
if (encAccessToken) { if (encAccessToken) {
//NOTE: default pin decryption works also for custom pin as other account //NOTE: default pin decryption works also for custom pin as other account
//keys are not yet being affected by changed pin, which I think we should dig more //keys are not yet being affected by changed pin, which I think we should dig more
accessToken = decryptKey(encAccessToken, Config.DEFAULT_PIN); accessToken = decryptKey(account.name, Config.DEFAULT_PIN);
} }
this._enableNotification(account.name, isEnabled, settings, accessToken); this._enableNotification(account.name, isEnabled, settings, accessToken);
}
//updateing fcm token with settings;
otherAccounts.forEach((account) => {
//since there can be more than one accounts, process access tokens separate
if (account?.local?.accessToken) {
_enabledNotificationForAccount(account)
} else {
console.warn("access token not present, reporting to bugsnag")
bugsnapInstance.notify(new Error(`Reporting missing access token in other accounts section: account:${account.name} with local data ${JSON.stringify(account?.local)}`))
//fallback to current account access token to register atleast logged in account
if (currentAccount.name === account.name) {
_enabledNotificationForAccount(currentAccount)
}
}
}); });
}; };

View File

@ -1,8 +1,16 @@
import React, { useState } from 'react'; import React, { useState, useEffect } from 'react';
import { View, StatusBar, Platform, Image, Text, SafeAreaView } from 'react-native'; import {
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; View,
StatusBar,
Platform,
Image,
Text,
SafeAreaView,
Keyboard,
KeyboardAvoidingView,
} from 'react-native';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import * as Animatable from 'react-native-animatable';
import RegisterContainer from './registerContainer'; import RegisterContainer from './registerContainer';
// Internal Components // Internal Components
@ -16,6 +24,7 @@ import styles from './registerStyles';
import ESTEEM_LOGO from '../../assets/like_new.png'; import ESTEEM_LOGO from '../../assets/like_new.png';
import ESTEEM_SMALL_LOGO from '../../assets/ecency_logo_transparent.png'; import ESTEEM_SMALL_LOGO from '../../assets/ecency_logo_transparent.png';
import getWindowDimensions from '../../utils/getWindowDimensions';
const RegisterScreen = ({ navigation, route }) => { const RegisterScreen = ({ navigation, route }) => {
const intl = useIntl(); const intl = useIntl();
@ -27,6 +36,19 @@ const RegisterScreen = ({ navigation, route }) => {
const [refUsername, setRefUsername] = useState(route.params?.referredUser ?? ''); const [refUsername, setRefUsername] = useState(route.params?.referredUser ?? '');
const [isRefUsernameValid, setIsRefUsernameValid] = useState(true); const [isRefUsernameValid, setIsRefUsernameValid] = useState(true);
useEffect(() => {
const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => {
setKeyboardIsOpen(true);
});
const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {
setKeyboardIsOpen(false);
});
return () => {
keyboardDidHideListener.remove();
keyboardDidShowListener.remove();
};
}, []);
const _handleEmailChange = (value) => { const _handleEmailChange = (value) => {
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
setIsEmailValid(re.test(value)); setIsEmailValid(re.test(value));
@ -74,7 +96,11 @@ const RegisterScreen = ({ navigation, route }) => {
/> />
</View> </View>
</View> </View>
{!keyboardIsOpen && ( <Animatable.View
animation={keyboardIsOpen ? hideAnimation : showAnimation}
delay={0}
duration={300}
>
<View style={styles.header}> <View style={styles.header}>
<View style={styles.titleText}> <View style={styles.titleText}>
<Text style={styles.title}>{intl.formatMessage({ id: 'register.title' })}</Text> <Text style={styles.title}>{intl.formatMessage({ id: 'register.title' })}</Text>
@ -84,15 +110,13 @@ const RegisterScreen = ({ navigation, route }) => {
</View> </View>
<Image style={styles.mascot} source={ESTEEM_LOGO} /> <Image style={styles.mascot} source={ESTEEM_LOGO} />
</View> </View>
)} </Animatable.View>
<View style={styles.body}> <KeyboardAvoidingView
<KeyboardAwareScrollView behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
onKeyboardWillShow={() => setKeyboardIsOpen(true)} style={styles.formWrapper}
onKeyboardWillHide={() => setKeyboardIsOpen(false)} keyboardShouldPersistTaps
enableAutoAutomaticScroll={Platform.OS === 'ios'} >
contentContainerStyle={styles.formWrapper} <View style={styles.body}>
enableOnAndroid={true}
>
<FormInput <FormInput
rightIconName="at" rightIconName="at"
leftIconName="close" leftIconName="close"
@ -107,6 +131,7 @@ const RegisterScreen = ({ navigation, route }) => {
isFirstImage isFirstImage
value={username} value={username}
inputStyle={styles.input} inputStyle={styles.input}
onFocus={() => setKeyboardIsOpen(true)}
/> />
<FormInput <FormInput
rightIconName="mail" rightIconName="mail"
@ -120,6 +145,7 @@ const RegisterScreen = ({ navigation, route }) => {
type="emailAddress" type="emailAddress"
value={email} value={email}
inputStyle={styles.input} inputStyle={styles.input}
onFocus={() => setKeyboardIsOpen(true)}
/> />
<FormInput <FormInput
rightIconName="person" rightIconName="person"
@ -134,14 +160,14 @@ const RegisterScreen = ({ navigation, route }) => {
isFirstImage isFirstImage
value={refUsername} value={refUsername}
inputStyle={styles.input} inputStyle={styles.input}
onFocus={() => setKeyboardIsOpen(true)}
/> />
<InformationArea <InformationArea
description={intl.formatMessage({ id: 'register.form_description' })} description={intl.formatMessage({ id: 'register.form_description' })}
iconName="ios-information-circle-outline" iconName="ios-information-circle-outline"
link="https://ecency.com/terms-of-service" link="https://ecency.com/terms-of-service"
/> />
</KeyboardAwareScrollView> </View>
<View style={styles.footerButtons}> <View style={styles.footerButtons}>
<TextButton <TextButton
style={styles.cancelButton} style={styles.cancelButton}
@ -166,11 +192,34 @@ const RegisterScreen = ({ navigation, route }) => {
style={styles.mainButton} style={styles.mainButton}
/> />
</View> </View>
</View> </KeyboardAvoidingView>
</SafeAreaView> </SafeAreaView>
)} )}
</RegisterContainer> </RegisterContainer>
); );
}; };
const { height } = getWindowDimensions();
const bodyHeight = height / 5;
const showAnimation = {
from: {
opacity: 0,
height: 0,
},
to: {
opacity: 1,
height: bodyHeight,
},
};
const hideAnimation = {
from: {
opacity: 1,
height: bodyHeight,
},
to: {
opacity: 0,
height: 0,
},
};
export default RegisterScreen; export default RegisterScreen;

View File

@ -1,5 +1,4 @@
import EStyleSheet from 'react-native-extended-stylesheet'; import EStyleSheet from 'react-native-extended-stylesheet';
import autoMergeLevel1 from 'redux-persist/es/stateReconciler/autoMergeLevel1';
export default EStyleSheet.create({ export default EStyleSheet.create({
container: { container: {
@ -12,12 +11,9 @@ export default EStyleSheet.create({
}, },
footerButtons: { footerButtons: {
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'center', justifyContent: 'flex-end',
alignItems: 'center', alignItems: 'center',
alignSelf: 'flex-end', height: 80,
marginRight: 10,
bottom: 24,
right: 24,
}, },
cancelButton: { cancelButton: {
marginRight: 10, marginRight: 10,
@ -25,6 +21,7 @@ export default EStyleSheet.create({
formWrapper: { formWrapper: {
marginHorizontal: 30, marginHorizontal: 30,
marginVertical: 10, marginVertical: 10,
flex: 1,
}, },
input: { input: {
color: '$primaryDarkText', color: '$primaryDarkText',

View File

@ -1,5 +1,9 @@
import { Platform } from "react-native" import { Platform } from "react-native"
export default () => { export default () => {
return Platform.OS === 'android' && Platform.Version === 26 return Platform.OS === 'android'
&& (
Platform.Version === 26
|| Platform.Version === 27
)
} }

View File

@ -1,7 +1,8 @@
import { Alert } from 'react-native'; import { Alert } from 'react-native';
import ROUTES from '../../src/constants/routeNames'; import ROUTES from '../../src/constants/routeNames';
import { navigate } from '../navigation/service';
const showLoginAlert = ({ navigation, intl }) => { const showLoginAlert = ({ intl }) => {
return Alert.alert( return Alert.alert(
intl.formatMessage({ id: 'login.not_loggedin_alert' }), intl.formatMessage({ id: 'login.not_loggedin_alert' }),
intl.formatMessage({ id: 'login.not_loggedin_alert_desc' }), intl.formatMessage({ id: 'login.not_loggedin_alert_desc' }),
@ -14,7 +15,7 @@ const showLoginAlert = ({ navigation, intl }) => {
{ {
text: intl.formatMessage({ id: 'login.login' }), text: intl.formatMessage({ id: 'login.login' }),
onPress: () => { onPress: () => {
navigation.navigate(ROUTES.SCREENS.LOGIN); navigate({routeName:ROUTES.SCREENS.LOGIN});
}, },
}, },
], ],