From ad34c47a3f68fcb7c6aa5f783ea77cde05fcc667 Mon Sep 17 00:00:00 2001 From: Mustafa Buyukcelebi Date: Wed, 30 Oct 2019 16:08:24 +0300 Subject: [PATCH 01/20] Fixed android animation splash design. Fixed android crash issue --- .../notification/view/notificationView.js | 48 +-- src/components/points/view/pointsView.js | 307 +++++++++--------- src/components/posts/view/postsView.js | 63 ++-- src/components/wallet/view/walletView.js | 116 +++---- src/screens/launch/screen/launchStyles.js | 1 + 5 files changed, 273 insertions(+), 262 deletions(-) diff --git a/src/components/notification/view/notificationView.js b/src/components/notification/view/notificationView.js index 178f49816..547d731bc 100644 --- a/src/components/notification/view/notificationView.js +++ b/src/components/notification/view/notificationView.js @@ -165,17 +165,17 @@ class NotificationView extends PureComponent { rightIconType="MaterialIcons" onRightIconPress={readAllNotification} /> - getActivities()} - keyExtractor={item => item.title} - onEndReached={() => getActivities(null, selectedFilter, true)} - ListFooterComponent={this._renderFooterLoading} - ListEmptyComponent={} - refreshControl={ - - {({ isDarkTheme }) => ( + + {({ isDarkTheme }) => ( + getActivities()} + keyExtractor={item => item.title} + onEndReached={() => getActivities(null, selectedFilter, true)} + ListFooterComponent={this._renderFooterLoading} + ListEmptyComponent={} + refreshControl={ + } + renderItem={({ item, index }) => ( + + + {this._renderList(item.notifications)} + )} - - } - renderItem={({ item, index }) => ( - - - {this._renderList(item.notifications)} - + /> )} - /> + ); } diff --git a/src/components/points/view/pointsView.js b/src/components/points/view/pointsView.js index 47e525494..6f95fb18f 100644 --- a/src/components/points/view/pointsView.js +++ b/src/components/points/view/pointsView.js @@ -40,22 +40,18 @@ class PointsView extends Component { // Component Functions - refreshControl = () => { + refreshControl = ({ isDarkTheme }) => { const { fetchUserActivity, refreshing } = this.props; return ( - - {isDarkTheme => ( - - )} - + ); }; @@ -100,147 +96,166 @@ class PointsView extends Component { return ( - - - - {get(userPoints, 'points')} - - - - {intl.formatMessage({ id: 'points.esteemPoints' })} - - - unclaimedPoints > 0 ? claimPoints() : navigation.navigate(ROUTES.SCREENS.BOOST) - } - > - - - {unclaimedPoints > 0 ? unclaimedPoints : intl.formatMessage({ id: 'boost.buy' })} - - - + + {isDarkTheme => ( + + + + {get(userPoints, 'points')} + + - - + + {intl.formatMessage({ id: 'points.esteemPoints' })} + - - get(item, 'type', Math.random()).toString()} - horizontal - renderItem={({ item }) => ( - - {({ - openPopover, - closePopover, - popoverVisible, - setPopoverAnchor, - popoverAnchorRect, - }) => ( - - - - - - - - {this._getTranslation(get(POINTS[get(item, 'type')], 'nameKey'))} - - closePopover()} - fromRect={popoverAnchorRect} - placement="top" - supportedOrientations={['portrait', 'landscape']} - > - - - {this._getTranslation(get(POINTS[get(item, 'type')], 'descriptionKey'))} + + unclaimedPoints > 0 ? claimPoints() : navigation.navigate(ROUTES.SCREENS.BOOST) + } + > + + + {unclaimedPoints > 0 + ? unclaimedPoints + : intl.formatMessage({ id: 'boost.buy' })} + + + + + + + + + get(item, 'type', Math.random()).toString()} + horizontal + renderItem={({ item }) => ( + + {({ + openPopover, + closePopover, + popoverVisible, + setPopoverAnchor, + popoverAnchorRect, + }) => ( + + + + + + + + {this._getTranslation(get(POINTS[get(item, 'type')], 'nameKey'))} + closePopover()} + fromRect={popoverAnchorRect} + placement="top" + supportedOrientations={['portrait', 'landscape']} + > + + + {this._getTranslation( + get(POINTS[get(item, 'type')], 'descriptionKey'), + )} + + + - - + )} + )} - - )} - /> - + /> + - - item.id.toString()} - ListEmptyComponent={this._renderLoading()} - renderItem={({ item, index }) => ( - - } - > - {(get(item, 'memo') || get(item, 'sender')) && ( - + item.id.toString()} + ListEmptyComponent={this._renderLoading()} + renderItem={({ item, index }) => ( + } - description={get(item, 'memo')} - /> + > + {(get(item, 'memo') || get(item, 'sender')) && ( + + )} + )} - - )} - /> - - + /> + + + )} + ); } diff --git a/src/components/posts/view/postsView.js b/src/components/posts/view/postsView.js index 28d7985fc..a3bd12a72 100644 --- a/src/components/posts/view/postsView.js +++ b/src/components/posts/view/postsView.js @@ -359,12 +359,7 @@ class PostsView extends Component { render() { const { refreshing, posts, isShowFilterBar } = this.state; - const { - filterOptions, - selectedOptionIndex, - isHideImage, - handleImagesHide, - } = this.props; + const { filterOptions, selectedOptionIndex, isHideImage, handleImagesHide } = this.props; return ( @@ -381,27 +376,27 @@ class PostsView extends Component { /> )} - - get(item, 'author', null) && ( - - ) - } - keyExtractor={(content, i) => `${get(content, 'permlink', '')}${i.toString()}`} - onEndReached={() => this._loadPosts()} - removeClippedSubviews - refreshing={refreshing} - onRefresh={() => this._handleOnRefreshPosts()} - onEndThreshold={0} - initialNumToRender={10} - ListFooterComponent={this._renderFooter} - onScrollEndDrag={this._handleOnScroll} - ListEmptyComponent={this._renderEmptyContent} - refreshControl={ - - {({ isDarkTheme }) => ( + + {({ isDarkTheme }) => ( + + get(item, 'author', null) && ( + + ) + } + keyExtractor={(content, i) => `${get(content, 'permlink', '')}${i.toString()}`} + onEndReached={() => this._loadPosts()} + removeClippedSubviews + refreshing={refreshing} + onRefresh={() => this._handleOnRefreshPosts()} + onEndThreshold={0} + initialNumToRender={10} + ListFooterComponent={this._renderFooter} + onScrollEndDrag={this._handleOnScroll} + ListEmptyComponent={this._renderEmptyContent} + refreshControl={ - )} - - } - ref={ref => { - this.flatList = ref; - }} - /> + } + ref={ref => { + this.flatList = ref; + }} + /> + )} + ); } diff --git a/src/components/wallet/view/walletView.js b/src/components/wallet/view/walletView.js index 5c9d64f22..f08c605a3 100644 --- a/src/components/wallet/view/walletView.js +++ b/src/components/wallet/view/walletView.js @@ -58,12 +58,12 @@ class WalletView extends PureComponent { } = this.props; return ( - - {isDarkTheme => ( + + {isDarkTheme => ( + - )} - - } - > - {!walletData ? ( - - - - ) : ( - - {walletData.hasUnclaimedRewards && ( - - {currentAccountUsername === selectedUsername ? ( - claimRewardBalance()} + } + > + {!walletData ? ( + + + + ) : ( + + {walletData.hasUnclaimedRewards && ( + - - {this._getUnclaimedText(walletData)} - - - - - - ) : ( - this._getUnclaimedText(walletData, true) + {currentAccountUsername === selectedUsername ? ( + claimRewardBalance()} + > + + {this._getUnclaimedText(walletData)} + + + + + + ) : ( + this._getUnclaimedText(walletData, true) + )} + )} - + + + + + )} - - - - - + )} - + ); } } diff --git a/src/screens/launch/screen/launchStyles.js b/src/screens/launch/screen/launchStyles.js index 474f80476..c98439d5b 100644 --- a/src/screens/launch/screen/launchStyles.js +++ b/src/screens/launch/screen/launchStyles.js @@ -5,5 +5,6 @@ export default EStyleSheet.create({ flex: 1, justifyContent: 'center', alignItems: 'center', + backgroundColor: '$pureWhite', }, }); From 2acf206205894bb038c5f0504ff4da598fb1f681 Mon Sep 17 00:00:00 2001 From: ue Date: Wed, 30 Oct 2019 23:47:47 +0300 Subject: [PATCH 02/20] created acccount container enhanced header container & view convert to hooks && merged trending and feed --- .../container/basicHeaderContainer.js | 6 +- .../bottomTabBar/view/bottomTabBarView.js | 2 +- .../formInput/view/formInputStyles.js | 2 +- .../header/container/headerContainer.js | 99 ++++----- src/components/header/view/headerStyles.js | 5 +- src/components/header/view/headerView.js | 204 ++++++++---------- .../posts/container/postsContainer.js | 123 +++++------ src/components/posts/view/postsView.js | 67 ++---- .../textInput/view/textInputStyles.js | 1 + src/constants/options/filters.js | 18 +- src/constants/routeNames.js | 4 +- src/containers/accountContainer.js | 33 +++ src/containers/index.js | 2 + src/navigation/baseNavigator.js | 6 +- src/navigation/routes.js | 2 +- src/providers/esteem/esteem.js | 8 +- src/screens/feed/index.js | 4 + src/screens/feed/screen/feedScreen.js | 36 ++++ .../screen/feedStyles.js} | 0 src/screens/home/container/homeContainer.js | 38 ---- src/screens/home/index.js | 5 - src/screens/home/screen/homeScreen.js | 73 ------- src/screens/index.js | 4 +- .../pinCode/container/pinCodeContainer.js | 14 +- 24 files changed, 313 insertions(+), 443 deletions(-) create mode 100644 src/containers/accountContainer.js create mode 100644 src/screens/feed/index.js create mode 100644 src/screens/feed/screen/feedScreen.js rename src/screens/{home/screen/homeStyles.js => feed/screen/feedStyles.js} (100%) delete mode 100644 src/screens/home/container/homeContainer.js delete mode 100644 src/screens/home/index.js delete mode 100644 src/screens/home/screen/homeScreen.js diff --git a/src/components/basicHeader/container/basicHeaderContainer.js b/src/components/basicHeader/container/basicHeaderContainer.js index 724474c49..3b3c581af 100644 --- a/src/components/basicHeader/container/basicHeaderContainer.js +++ b/src/components/basicHeader/container/basicHeaderContainer.js @@ -26,13 +26,15 @@ class BasicHeaderContainer extends Component { if (isNewPost) { navigation.navigate({ - routeName: ROUTES.SCREENS.HOME, + routeName: ROUTES.SCREENS.FEED, }); } else { navigation.goBack(); } - if (handleOnBackPress) handleOnBackPress(); + if (handleOnBackPress) { + handleOnBackPress(); + } }; render() { diff --git a/src/components/bottomTabBar/view/bottomTabBarView.js b/src/components/bottomTabBar/view/bottomTabBarView.js index 007e516cc..3399f7852 100644 --- a/src/components/bottomTabBar/view/bottomTabBarView.js +++ b/src/components/bottomTabBar/view/bottomTabBarView.js @@ -21,7 +21,7 @@ import styles from './bottomTabBarStyles'; const _jumpTo = (route, index, routes, jumpTo) => { const _routeName = routes[index].routeName; - if (!!get(route, 'params.scrollToTop') && _routeName === ROUTES.TABBAR.HOME) { + if (!!get(route, 'params.scrollToTop') && _routeName === ROUTES.TABBAR.FEED) { route.params.scrollToTop(); } diff --git a/src/components/formInput/view/formInputStyles.js b/src/components/formInput/view/formInputStyles.js index 3c46154da..a87f57620 100644 --- a/src/components/formInput/view/formInputStyles.js +++ b/src/components/formInput/view/formInputStyles.js @@ -6,9 +6,9 @@ export default EStyleSheet.create({ borderTopRightRadius: 8, marginTop: 16, flexDirection: 'row', - backgroundColor: '$primaryLightBackground', height: 60, borderBottomWidth: 2, + backgroundColor: '$primaryWhiteLightBackground', }, firstImage: { width: 24, diff --git a/src/components/header/container/headerContainer.js b/src/components/header/container/headerContainer.js index 6a8871cac..8b4a910d1 100644 --- a/src/components/header/container/headerContainer.js +++ b/src/components/header/container/headerContainer.js @@ -1,80 +1,53 @@ -import React, { PureComponent } from 'react'; +import React from 'react'; import { withNavigation } from 'react-navigation'; -import { connect } from 'react-redux'; -import { get, has } from 'lodash'; +import get from 'lodash/get'; +import has from 'lodash/has'; // Component import HeaderView from '../view/headerView'; -/* - * Props Name Description Value - *@props --> props name here description here Value Type Here - * - */ - -class HeaderContainer extends PureComponent { - constructor(props) { - super(props); - this.state = {}; - } - - // Component Life Cycle Functions - - // Component Functions - - _handleOpenDrawer = () => { - const { navigation } = this.props; +import { AccountContainer, ThemeContainer } from '../../../containers'; +const HeaderContainer = ({ selectedUser, isReverse, navigation, handleOnBackPress }) => { + const _handleOpenDrawer = () => { if (has(navigation, 'openDrawer') && typeof get(navigation, 'openDrawer') === 'function') { navigation.openDrawer(); } }; - _handleOnPressBackButton = () => { - const { navigation, handleOnBackPress } = this.props; - - if (handleOnBackPress) handleOnBackPress(); + const _handleOnPressBackButton = () => { + if (handleOnBackPress) { + handleOnBackPress(); + } navigation.goBack(); }; - render() { - const { - isLoggedIn, - currentAccount, - selectedUser, - isReverse, - isLoginDone, - isDarkTheme, - } = this.props; - const _user = isReverse && selectedUser ? selectedUser : currentAccount; + return ( + + {({ isDarkTheme }) => ( + + {({ currentAccount, isLoggedIn, isLoginDone }) => { + const _user = isReverse && selectedUser ? selectedUser : currentAccount; - const displayName = get(_user, 'display_name'); - const username = get(_user, 'name'); - const reputation = get(_user, 'reputation'); + return ( + + ); + }} + + )} + + ); +}; - return ( - - ); - } -} - -const mapStateToProps = state => ({ - isLoggedIn: state.application.isLoggedIn, - isLoginDone: state.application.isLoginDone, - isDarkTheme: state.application.isDarkTheme, - - currentAccount: state.account.currentAccount, -}); - -export default connect(mapStateToProps)(withNavigation(HeaderContainer)); +export default withNavigation(HeaderContainer); diff --git a/src/components/header/view/headerStyles.js b/src/components/header/view/headerStyles.js index 0910ee81a..bf4edf9e1 100644 --- a/src/components/header/view/headerStyles.js +++ b/src/components/header/view/headerStyles.js @@ -7,7 +7,7 @@ export default EStyleSheet.create({ width: '$deviceWidth', backgroundColor: '$primaryBackgroundColor', flex: 1, - maxHeight: Platform.OS === 'ios' ? 95 : 80, + maxHeight: Platform.OS === 'ios' ? 105 : 80, }, containerReverse: { justifyContent: 'space-between', @@ -33,8 +33,7 @@ export default EStyleSheet.create({ titleWrapper: { flexDirection: 'column', justifyContent: 'center', - marginLeft: 8, - marginRight: 8, + marginHorizontal: 8, }, title: { fontSize: 14, diff --git a/src/components/header/view/headerView.js b/src/components/header/view/headerView.js index a6b50aef4..d24df9997 100644 --- a/src/components/header/view/headerView.js +++ b/src/components/header/view/headerView.js @@ -1,131 +1,107 @@ -import React, { Component } from 'react'; +import React, { useState } from 'react'; import { View, Text, SafeAreaView, TouchableOpacity } from 'react-native'; import LinearGradient from 'react-native-linear-gradient'; -import { injectIntl } from 'react-intl'; +import { useIntl } from 'react-intl'; // Components import { SearchModal } from '../../searchModal'; import { IconButton } from '../../iconButton'; import { UserAvatar } from '../../userAvatar'; + // Styles import styles from './headerStyles'; -class HeaderView extends Component { - /* Props - * ------------------------------------------------ - * @prop { boolean } hideStatusBar - Can declare status bar is hide or not. - * - */ +const HeaderView = ({ + displayName, + handleOnPressBackButton, + handleOpenDrawer, + isDarkTheme, + isLoggedIn, + isLoginDone, + isReverse, + reputation, + username, +}) => { + const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); + const intl = useIntl(); + let gradientColor; - constructor(props) { - super(props); - this.state = { - isSearchModalOpen: false, - }; + if (isReverse) { + gradientColor = isDarkTheme ? ['#43638e', '#081c36'] : ['#357ce6', '#2d5aa0']; + } else { + gradientColor = isDarkTheme ? ['#081c36', '#43638e'] : ['#2d5aa0', '#357ce6']; } - // Component Life Cycles - - // Component Functions - - _handleOnCloseSearch = () => { - this.setState({ isSearchModalOpen: false }); - }; - - render() { - const { - displayName, - handleOnPressBackButton, - handleOpenDrawer, - intl, - isDarkTheme, - isLoggedIn, - isLoginDone, - isReverse, - reputation, - username, - } = this.props; - const { isSearchModalOpen } = this.state; - let gredientColor; - - if (isReverse) { - gredientColor = isDarkTheme ? ['#43638e', '#081c36'] : ['#357ce6', '#2d5aa0']; - } else { - gredientColor = isDarkTheme ? ['#081c36', '#43638e'] : ['#2d5aa0', '#357ce6']; - } - - return ( - - - handleOpenDrawer()} - disabled={isReverse} + return ( + + setIsSearchModalOpen(false)} + /> + + - - - - - {displayName || username ? ( - - {displayName && {displayName}} - - {`@${username}`} - {reputation && ` (${reputation})`} + + + + {displayName || username ? ( + + {displayName && {displayName}} + + {`@${username}`} + {reputation && ` (${reputation})`} + + + ) : ( + + {isLoginDone && !isLoggedIn && ( + + {intl.formatMessage({ + id: 'header.title', + })} - - ) : ( - - {isLoginDone && !isLoggedIn && ( - - {intl.formatMessage({ - id: 'header.title', - })} - - )} - - )} - {isReverse && ( - - handleOnPressBackButton()} - /> - - )} + )} + + )} - {!isReverse && ( - - this.setState({ isSearchModalOpen: true })} - /> - - )} - - ); - } -} + {isReverse ? ( + + handleOnPressBackButton()} + /> + + ) : ( + + setIsSearchModalOpen(true)} + /> + + )} + + ); +}; -export default injectIntl(HeaderView); +export default HeaderView; diff --git a/src/components/posts/container/postsContainer.js b/src/components/posts/container/postsContainer.js index 4e5e4d89a..64da5170b 100644 --- a/src/components/posts/container/postsContainer.js +++ b/src/components/posts/container/postsContainer.js @@ -1,94 +1,69 @@ -import React, { PureComponent } from 'react'; -import { connect } from 'react-redux'; -import get from 'lodash/get'; +import React from 'react'; +import { connect, useDispatch } from 'react-redux'; // Component import PostsView from '../view/postsView'; +// Container +import { AccountContainer } from '../../../containers'; + // Actions import { setFeedPosts } from '../../../redux/actions/postsAction'; import { hidePostsThumbnails } from '../../../redux/actions/uiAction'; -/* - * Props Name Description Value - *@props --> props name here description here Value Type Here - * - */ - -class PostsContainer extends PureComponent { - constructor(props) { - super(props); - this.state = { - promotedPosts: [], - }; - } - - // Component Life Cycle Functions - - // Component Functions - - _setFeedPosts = posts => { - const { dispatch } = this.props; +const PostsContainer = ({ + changeForceLoadPostState, + feedPosts, + filterOptions, + forceLoadPost, + getFor, + handleOnScroll, + isConnected, + isHideImages, + pageType, + selectedOptionIndex, + tag, + nsfw, +}) => { + const dispatch = useDispatch(); + const _setFeedPosts = posts => { dispatch(setFeedPosts(posts)); }; - _handleImagesHide = () => { - const { dispatch, isHideImages } = this.props; - + const _handleImagesHide = () => { dispatch(hidePostsThumbnails(!isHideImages)); }; - render() { - const { - changeForceLoadPostState, - currentAccount, - feedPosts, - filterOptions, - forceLoadPost, - getFor, - handleOnScroll, - isConnected, - isHideImages, - pageType, - selectedOptionIndex, - tag, - isLoginDone, - isLoggedIn, - nsfw, - } = this.props; - const { promotedPosts } = this.state; - - return ( - - ); - } -} + return ( + + {({ username, isLoggedIn, isLoginDone }) => ( + + )} + + ); +}; const mapStateToProps = state => ({ - currentAccount: state.account.currentAccount, - isLoggedIn: state.application.isLoggedIn, - isLoginDone: state.application.isLoginDone, nsfw: state.application.nsfw, feedPosts: state.posts.feedPosts, isConnected: state.application.isConnected, diff --git a/src/components/posts/view/postsView.js b/src/components/posts/view/postsView.js index 28d7985fc..80632a581 100644 --- a/src/components/posts/view/postsView.js +++ b/src/components/posts/view/postsView.js @@ -13,7 +13,6 @@ import { getPromotePosts } from '../../../providers/esteem/esteem'; import { PostCard } from '../../postCard'; import { FilterBar } from '../../filterBar'; import { PostCardPlaceHolder, NoPost } from '../../basicUIElements'; -import { POPULAR_FILTERS, PROFILE_FILTERS } from '../../../constants/options/filters'; import { ThemeContainer } from '../../../containers'; // Styles @@ -39,15 +38,6 @@ class PostsView extends Component { }; } - // Component Functions - componentWillMount() { - const { navigation } = this.props; - - navigation.setParams({ - scrollToTop: this._scrollToTop, - }); - } - async componentDidMount() { const { isConnected, pageType } = this.props; @@ -97,25 +87,24 @@ class PostsView extends Component { _getPromotePosts = async () => { const { currentAccountUsername } = this.props; - await getPromotePosts().then(async res => { - if (res && res.length) { - const promotedPosts = await Promise.all( - res.map(item => - getPost(get(item, 'author'), get(item, 'permlink'), currentAccountUsername, true).then( - post => post, + await getPromotePosts() + .then(async res => { + if (res && res.length) { + const promotedPosts = await Promise.all( + res.map(item => + getPost( + get(item, 'author'), + get(item, 'permlink'), + currentAccountUsername, + true, + ).then(post => post), ), - ), - ); + ); - this.setState({ promotedPosts }); - } - }); - }; - - _scrollToTop = () => { - if (this.flatList) { - this.flatList.scrollToOffset({ x: 0, y: 0, animated: true }); - } + this.setState({ promotedPosts }); + } + }) + .catch(() => {}); }; _loadPosts = async () => { @@ -123,10 +112,10 @@ class PostsView extends Component { getFor, tag, currentAccountUsername, - pageType, nsfw, setFeedPosts, isConnected, + filterOptions, } = this.props; const { posts, @@ -137,10 +126,7 @@ class PostsView extends Component { isLoading, promotedPosts, } = this.state; - const filter = - pageType === 'posts' - ? POPULAR_FILTERS[selectedFilterIndex].toLowerCase() - : PROFILE_FILTERS[selectedFilterIndex].toLowerCase(); + const filter = filterOptions[selectedFilterIndex].toLowerCase(); let options; const limit = 3; @@ -157,12 +143,7 @@ class PostsView extends Component { } this.setState({ isLoading: true }); - if (tag || filter === 'feed' || filter === 'blog' || getFor === 'blog') { - options = { - tag, - limit, - }; - } else if (filter === 'reblogs') { + if (filter === 'feed' || filter === 'blog' || getFor === 'blog' || filter === 'reblogs') { options = { tag, limit, @@ -359,12 +340,7 @@ class PostsView extends Component { render() { const { refreshing, posts, isShowFilterBar } = this.state; - const { - filterOptions, - selectedOptionIndex, - isHideImage, - handleImagesHide, - } = this.props; + const { filterOptions, selectedOptionIndex, isHideImage, handleImagesHide } = this.props; return ( @@ -413,9 +389,6 @@ class PostsView extends Component { )} } - ref={ref => { - this.flatList = ref; - }} /> ); diff --git a/src/components/textInput/view/textInputStyles.js b/src/components/textInput/view/textInputStyles.js index 2d00237e5..3bb825c83 100644 --- a/src/components/textInput/view/textInputStyles.js +++ b/src/components/textInput/view/textInputStyles.js @@ -15,5 +15,6 @@ export default EStyleSheet.create({ input: { flex: 1, minHeight: 50, + backgroundColor: '$primaryWhiteLightBackground', }, }); diff --git a/src/constants/options/filters.js b/src/constants/options/filters.js index 0baaad66d..875572f89 100644 --- a/src/constants/options/filters.js +++ b/src/constants/options/filters.js @@ -1,10 +1,10 @@ -export const POPULAR_FILTERS = [ - 'TRENDING', - 'HOT', - 'CREATED', - 'ACTIVE', - 'PROMOTED', - 'VOTES', - 'CHILDREN', -]; +export const POPULAR_FILTERS = ['TRENDING', 'HOT', 'NEW', 'PROMOTED']; export const PROFILE_FILTERS = ['BLOG', 'FEED']; + +// 'TRENDING', +// 'HOT', +// 'CREATED', +// 'ACTIVE', +// 'PROMOTED', +// 'VOTES', +// 'CHILDREN', diff --git a/src/constants/routeNames.js b/src/constants/routeNames.js index 11ec28eb7..714b1ac4c 100644 --- a/src/constants/routeNames.js +++ b/src/constants/routeNames.js @@ -11,7 +11,7 @@ export default { EDITOR: `Editor${SCREEN_SUFFIX}`, FOLLOWS: `Follows${SCREEN_SUFFIX}`, SPIN_GAME: `SpinGame${SCREEN_SUFFIX}`, - HOME: `Home${SCREEN_SUFFIX}`, + FEED: `Feed${SCREEN_SUFFIX}`, LOGIN: `Login${SCREEN_SUFFIX}`, PINCODE: `PinCode${SCREEN_SUFFIX}`, POST: `Post${SCREEN_SUFFIX}`, @@ -29,7 +29,7 @@ export default { MAIN: `Main${DRAWER_SUFFIX}`, }, TABBAR: { - HOME: `Home${TABBAR_SUFFIX}`, + FEED: `Feed${TABBAR_SUFFIX}`, NOTIFICATION: `Notification${TABBAR_SUFFIX}`, POINTS: `Points${TABBAR_SUFFIX}`, POST_BUTTON: `PostButton${TABBAR_SUFFIX}`, diff --git a/src/containers/accountContainer.js b/src/containers/accountContainer.js new file mode 100644 index 000000000..dc3d6711a --- /dev/null +++ b/src/containers/accountContainer.js @@ -0,0 +1,33 @@ +/* eslint-disable no-unused-vars */ +import React from 'react'; +import { connect } from 'react-redux'; + +const AccountContainer = ({ + accounts, + children, + currentAccount, + isLoggedIn, + isLoginDone, + username, +}) => { + return ( + children && + children({ + accounts, + currentAccount, + isLoggedIn, + isLoginDone, + username, + }) + ); +}; + +const mapStateToProps = state => ({ + accounts: state.account.otherAccounts, + currentAccount: state.account.currentAccount, + isLoggedIn: state.application.isLoggedIn, + isLoginDone: state.application.isLoginDone, + username: state.account.currentAccount.name, +}); + +export default connect(mapStateToProps)(AccountContainer); diff --git a/src/containers/index.js b/src/containers/index.js index 2b9d0390a..eda2d5363 100644 --- a/src/containers/index.js +++ b/src/containers/index.js @@ -1,3 +1,4 @@ +import AccountContainer from './accountContainer'; import InAppPurchaseContainer from './inAppPurchaseContainer'; import PointsContainer from './pointsContainer'; import ProfileContainer from './profileContainer'; @@ -8,6 +9,7 @@ import TransferContainer from './transferContainer'; import ThemeContainer from './themeContainer'; export { + AccountContainer, InAppPurchaseContainer, PointsContainer, ProfileContainer, diff --git a/src/navigation/baseNavigator.js b/src/navigation/baseNavigator.js index 6af0acd63..c86558efb 100644 --- a/src/navigation/baseNavigator.js +++ b/src/navigation/baseNavigator.js @@ -6,13 +6,13 @@ import ROUTES from '../constants/routeNames'; // Components import { Icon, IconContainer } from '../components/icon'; -import { Home, Notification, Profile, Points } from '../screens'; +import { Feed, Notification, Profile, Points } from '../screens'; import { PostButton, BottomTabBar } from '../components'; const BaseNavigator = createBottomTabNavigator( { - [ROUTES.TABBAR.HOME]: { - screen: Home, + [ROUTES.TABBAR.FEED]: { + screen: Feed, navigationOptions: () => ({ tabBarIcon: ({ tintColor }) => ( diff --git a/src/navigation/routes.js b/src/navigation/routes.js index 56d5dd2aa..40c83dd5e 100644 --- a/src/navigation/routes.js +++ b/src/navigation/routes.js @@ -31,7 +31,7 @@ import { SideMenu } from '../components'; const mainNavigation = createDrawerNavigator( { - [ROUTES.SCREENS.HOME]: { + [ROUTES.SCREENS.FEED]: { screen: BaseNavigator, }, }, diff --git a/src/providers/esteem/esteem.js b/src/providers/esteem/esteem.js index ca128b25e..aa8c0c52f 100644 --- a/src/providers/esteem/esteem.js +++ b/src/providers/esteem/esteem.js @@ -357,7 +357,13 @@ export const getSCAccessToken = code => api.post('/sc-token-refresh', { code }).then(resp => resolve(resp.data)); }); -export const getPromotePosts = () => api.get('/promoted-posts').then(resp => resp.data); +export const getPromotePosts = () => { + try { + return api.get('/promoted-posts').then(resp => resp.data); + } catch (error) { + return error; + } +}; export const purchaseOrder = data => api.post('/purchase-order', data).then(resp => resp.data); diff --git a/src/screens/feed/index.js b/src/screens/feed/index.js new file mode 100644 index 000000000..a3aa6e9ce --- /dev/null +++ b/src/screens/feed/index.js @@ -0,0 +1,4 @@ +import Feed from './screen/feedScreen'; + +export { Feed }; +export default Feed; diff --git a/src/screens/feed/screen/feedScreen.js b/src/screens/feed/screen/feedScreen.js new file mode 100644 index 000000000..a085fff2e --- /dev/null +++ b/src/screens/feed/screen/feedScreen.js @@ -0,0 +1,36 @@ +import React, { Fragment } from 'react'; +import { SafeAreaView } from 'react-native'; +import get from 'lodash/get'; + +// Components +import { Posts, Header } from '../../../components'; + +// Container +import { AccountContainer } from '../../../containers'; + +// Styles +import styles from './feedStyles'; + +import { POPULAR_FILTERS, PROFILE_FILTERS } from '../../../constants/options/filters'; + +const FeedScreen = () => { + return ( + + {({ currentAccount, isLoggedIn }) => ( + +
+ + + + + )} + + ); +}; + +export default FeedScreen; diff --git a/src/screens/home/screen/homeStyles.js b/src/screens/feed/screen/feedStyles.js similarity index 100% rename from src/screens/home/screen/homeStyles.js rename to src/screens/feed/screen/feedStyles.js diff --git a/src/screens/home/container/homeContainer.js b/src/screens/home/container/homeContainer.js deleted file mode 100644 index 670fd4f44..000000000 --- a/src/screens/home/container/homeContainer.js +++ /dev/null @@ -1,38 +0,0 @@ -import React, { PureComponent } from 'react'; -import { connect } from 'react-redux'; - -// Component -import HomeScreen from '../screen/homeScreen'; - -/* - * Props Name Description Value - *@props --> props name here description here Value Type Here - * - */ - -class HomeContainer extends PureComponent { - constructor(props) { - super(props); - this.state = {}; - } - - render() { - const { isLoggedIn, isLoginDone, currentAccount } = this.props; - - return ( - - ); - } -} - -const mapStateToProps = state => ({ - isLoggedIn: state.application.isLoggedIn, - isLoginDone: state.application.isLoginDone, - currentAccount: state.account.currentAccount, -}); - -export default connect(mapStateToProps)(HomeContainer); diff --git a/src/screens/home/index.js b/src/screens/home/index.js deleted file mode 100644 index b73835b3d..000000000 --- a/src/screens/home/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import HomeScreen from './screen/homeScreen'; -import Home from './container/homeContainer'; - -export { HomeScreen, Home }; -export default Home; diff --git a/src/screens/home/screen/homeScreen.js b/src/screens/home/screen/homeScreen.js deleted file mode 100644 index 8201afdf4..000000000 --- a/src/screens/home/screen/homeScreen.js +++ /dev/null @@ -1,73 +0,0 @@ -import React, { PureComponent, Fragment } from 'react'; -import { View, SafeAreaView } from 'react-native'; -import ScrollableTabView from 'react-native-scrollable-tab-view'; -import { injectIntl } from 'react-intl'; - -// Components -import { TabBar, Posts, Header } from '../../../components'; - -// Styles -import styles from './homeStyles'; -import globalStyles from '../../../globalStyles'; - -import { POPULAR_FILTERS, PROFILE_FILTERS } from '../../../constants/options/filters'; - -class HomeScreen extends PureComponent { - constructor(props) { - super(props); - this.state = {}; - } - - render() { - const { currentAccount, intl, isLoggedIn } = this.props; - - return ( - -
- - ( - - )} - > - - - - - - - - - - ); - } -} - -export default injectIntl(HomeScreen); diff --git a/src/screens/index.js b/src/screens/index.js index d717c6ad1..5de20e384 100755 --- a/src/screens/index.js +++ b/src/screens/index.js @@ -2,7 +2,7 @@ import { Bookmarks } from './bookmarks'; import { Drafts } from './drafts'; import { Editor } from './editor'; import { Follows } from './follows'; -import { Home } from './home'; +import { Feed } from './feed'; import { Launch } from './launch'; import { Login } from './login'; import { Notification } from './notification'; @@ -27,7 +27,7 @@ export { Drafts, Editor, Follows, - Home, + Feed, Launch, Login, Notification, diff --git a/src/screens/pinCode/container/pinCodeContainer.js b/src/screens/pinCode/container/pinCodeContainer.js index 4548cec71..9f99ddbfc 100644 --- a/src/screens/pinCode/container/pinCodeContainer.js +++ b/src/screens/pinCode/container/pinCodeContainer.js @@ -108,7 +108,9 @@ class PinCodeContainer extends Component { dispatch(updateCurrentAccount({ ..._currentAccount })); this._savePinCode(pin); - if (callback) callback(pin, oldPinCode); + if (callback) { + callback(pin, oldPinCode); + } dispatch(closePinCodeModal()); if (navigateTo) { const navigateAction = NavigationActions.navigate({ @@ -171,7 +173,9 @@ class PinCodeContainer extends Component { setExistUser(true).then(() => { this._savePinCode(pin); - if (callback) callback(pin, oldPinCode); + if (callback) { + callback(pin, oldPinCode); + } dispatch(closePinCodeModal()); if (navigateTo) { const navigateAction = NavigationActions.navigate({ @@ -197,7 +201,7 @@ class PinCodeContainer extends Component { } = this.props; const { oldPinCode } = this.state; - // If the user is exist, we are just checking to pin and navigating to home screen + // If the user is exist, we are just checking to pin and navigating to feed screen const pinData = { pinCode: pin, password: currentAccount ? currentAccount.password : '', @@ -213,7 +217,9 @@ class PinCodeContainer extends Component { [_currentAccount.local] = realmData; dispatch(updateCurrentAccount({ ..._currentAccount })); dispatch(closePinCodeModal()); - if (callback) callback(pin, oldPinCode); + if (callback) { + callback(pin, oldPinCode); + } if (navigateTo) { const navigateAction = NavigationActions.navigate({ routeName: navigateTo, From 88749046a82283d25bbc09229a2719a7062b2a51 Mon Sep 17 00:00:00 2001 From: ue Date: Thu, 31 Oct 2019 00:58:59 +0300 Subject: [PATCH 03/20] post view convert to the hook --- src/components/posts/view/postsView.js | 545 ++++++++++++------------- 1 file changed, 266 insertions(+), 279 deletions(-) diff --git a/src/components/posts/view/postsView.js b/src/components/posts/view/postsView.js index 80632a581..fa468de3b 100644 --- a/src/components/posts/view/postsView.js +++ b/src/components/posts/view/postsView.js @@ -1,7 +1,7 @@ /* eslint-disable react/jsx-wrap-multilines */ -import React, { Component, Fragment } from 'react'; +import React, { useState, Fragment, useEffect, useCallback } from 'react'; import { FlatList, View, ActivityIndicator, RefreshControl } from 'react-native'; -import { injectIntl } from 'react-intl'; +import { useIntl } from 'react-intl'; import { withNavigation } from 'react-navigation'; import { get, isEqual, unionWith } from 'lodash'; @@ -19,78 +19,104 @@ import { ThemeContainer } from '../../../containers'; import styles from './postsStyles'; import { default as ROUTES } from '../../../constants/routeNames'; -class PostsView extends Component { - constructor(props) { - super(props); - - this.state = { - posts: props.isConnected ? [] : props.feedPosts, - startAuthor: '', - startPermlink: '', - refreshing: false, - isLoading: false, - isShowFilterBar: true, - selectedFilterIndex: get(props, 'selectedOptionIndex', 0), - isNoPost: false, - promotedPosts: [], - scrollOffsetY: 0, - lockFilterBar: false, - }; - } - - async componentDidMount() { - const { isConnected, pageType } = this.props; +const PostsView = ({ + filterOptions, + selectedOptionIndex, + isHideImage, + handleImagesHide, + feedPosts, + isConnected, + currentAccountUsername, + getFor, + tag, + nsfw, + setFeedPosts, + pageType, + isLoginDone, + isLoggedIn, + handleOnScroll, + navigation, + changeForceLoadPostState, + forceLoadPost, +}) => { + const [posts, setPosts] = useState(isConnected ? [] : feedPosts); + const [startAuthor, setStartAuthor] = useState(''); + const [startPermlink, setStartPermlink] = useState(''); + const [refreshing, setRefreshing] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [isShowFilterBar, setIsShowFilterBar] = useState(true); + const [selectedFilterIndex, setSelectedFilterIndex] = useState(selectedOptionIndex || 0); + const [isNoPost, setIsNoPost] = useState(false); + const [promotedPosts, setPromotedPosts] = useState([]); + const [scrollOffsetY, setScrollOffsetY] = useState(0); + const intl = useIntl(); + useEffect(() => { if (isConnected) { - if (pageType !== 'profiles') { - await this._getPromotePosts(); + const fetchPromotePost = async () => { + if (pageType !== 'profiles') { + await _getPromotePosts(); + } + }; + fetchPromotePost(); + _loadPosts(); + setRefreshing(false); + setIsLoading(false); + } + }, [ + _getPromotePosts, + _loadPosts, + changeForceLoadPostState, + currentAccountUsername, + forceLoadPost, + isConnected, + pageType, + selectedOptionIndex, + ]); + + useEffect(() => { + if (forceLoadPost) { + setPosts([]); + setStartAuthor(''); + setStartPermlink(''); + setRefreshing(false); + setIsLoading(false); + setSelectedFilterIndex(selectedOptionIndex || 0); + setIsNoPost(false); + + _loadPosts(); + + if (changeForceLoadPostState) { + changeForceLoadPostState(false); } - this._loadPosts(); - } else { - this.setState({ - refreshing: false, - isLoading: false, - }); } - } + }, [ + _loadPosts, + changeForceLoadPostState, + currentAccountUsername, + forceLoadPost, + selectedOptionIndex, + ]); - UNSAFE_componentWillReceiveProps(nextProps) { - const { currentAccountUsername, changeForceLoadPostState } = this.props; - - if ( - (currentAccountUsername && - currentAccountUsername !== nextProps.currentAccountUsername && - nextProps.currentAccountUsername) || - nextProps.forceLoadPost - ) { - // Set all initial data (New user new rules) - this.setState( - { - posts: [], - startAuthor: '', - startPermlink: '', - refreshing: false, - isLoading: false, - selectedFilterIndex: get(nextProps, 'selectedOptionIndex', 0), - isNoPost: false, - }, - () => { - this._loadPosts(); - if (changeForceLoadPostState) { - changeForceLoadPostState(false); - } - }, - ); + useEffect(() => { + if (!startAuthor && !startPermlink) { + _loadPosts(filterOptions[selectedFilterIndex].toLowerCase()); } - } + }, [_loadPosts, filterOptions, selectedFilterIndex, startAuthor, startPermlink]); - _getPromotePosts = async () => { - const { currentAccountUsername } = this.props; + const _handleOnDropdownSelect = async index => { + setSelectedFilterIndex(index); + setPosts([]); + setStartPermlink(''); + setStartAuthor(''); + setIsNoPost(false); + }; + const _getPromotePosts = useCallback(async () => { await getPromotePosts() .then(async res => { if (res && res.length) { - const promotedPosts = await Promise.all( + const _promotedPosts = await Promise.all( res.map(item => getPost( get(item, 'author'), @@ -101,165 +127,146 @@ class PostsView extends Component { ), ); - this.setState({ promotedPosts }); + setPromotedPosts(_promotedPosts); } }) .catch(() => {}); - }; + }, [currentAccountUsername]); - _loadPosts = async () => { - const { - getFor, - tag, - currentAccountUsername, - nsfw, - setFeedPosts, - isConnected, - filterOptions, - } = this.props; - const { - posts, - startAuthor, - startPermlink, - refreshing, - selectedFilterIndex, - isLoading, - promotedPosts, - } = this.state; - const filter = filterOptions[selectedFilterIndex].toLowerCase(); - let options; - const limit = 3; + const _loadPosts = useCallback( + async type => { + const filter = + type || + (filterOptions && + filterOptions.length > 0 && + filterOptions[selectedFilterIndex].toLowerCase()); + let options; + const limit = 3; - if (!isConnected) { - this.setState({ - refreshing: false, - isLoading: false, - }); - return null; - } + if (!isConnected) { + setRefreshing(false); + setIsLoading(false); + return null; + } - if (isLoading) { - return null; - } + // if (isLoading) { + // return null; + // } - this.setState({ isLoading: true }); - if (filter === 'feed' || filter === 'blog' || getFor === 'blog' || filter === 'reblogs') { - options = { - tag, - limit, - }; - } else { - options = { - limit, - }; - } + setIsLoading(true); + if (filter === 'feed' || filter === 'blog' || getFor === 'blog' || filter === 'reblogs') { + options = { + tag, + limit, + }; + } else { + options = { + limit, + }; + } - if (startAuthor && startPermlink && !refreshing) { - options.start_author = startAuthor; - options.start_permlink = startPermlink; - } + if (startAuthor && startPermlink && !refreshing) { + options.start_author = startAuthor; + options.start_permlink = startPermlink; + } - getPostsSummary(filter, options, currentAccountUsername, nsfw) - .then(result => { - if (result.length > 0) { - let _posts = result; + getPostsSummary(filter, options, currentAccountUsername, nsfw) + .then(result => { + if (result.length > 0) { + let _posts = result; - if (filter === 'reblogs') { - for (let i = _posts.length - 1; i >= 0; i--) { - if (_posts[i].author === currentAccountUsername) { - _posts.splice(i, 1); + if (filter === 'reblogs') { + for (let i = _posts.length - 1; i >= 0; i--) { + if (_posts[i].author === currentAccountUsername) { + _posts.splice(i, 1); + } } } - } - if (_posts.length > 0) { - if (posts.length > 0) { - if (refreshing) { - _posts = unionWith(_posts, posts, isEqual); - } else { - _posts.shift(); - _posts = [...posts, ..._posts]; - } - } - - if (posts.length < 5) { - setFeedPosts(_posts); - } - - // Promoted post start - if (promotedPosts && promotedPosts.length > 0) { - const insert = (arr, index, newItem) => [ - ...arr.slice(0, index), - - newItem, - - ...arr.slice(index), - ]; - - if (refreshing) { - _posts = _posts.filter(item => !item.is_promoted); + if (_posts.length > 0) { + if (posts.length > 0) { + if (refreshing) { + _posts = unionWith(_posts, posts, isEqual); + } else { + _posts.shift(); + _posts = [...posts, ..._posts]; + } } - _posts.map((d, i) => { - if ([3, 6, 9].includes(i)) { - const ix = i / 3 - 1; - if (promotedPosts[ix] !== undefined) { - if (get(_posts, [i], {}).permlink !== promotedPosts[ix].permlink) { - _posts = insert(_posts, i, promotedPosts[ix]); + if (posts.length < 5) { + setFeedPosts(_posts); + } + + // Promoted post start + if (promotedPosts && promotedPosts.length > 0) { + const insert = (arr, index, newItem) => [ + ...arr.slice(0, index), + + newItem, + + ...arr.slice(index), + ]; + + if (refreshing) { + _posts = _posts.filter(item => !item.is_promoted); + } + + _posts.map((d, i) => { + if ([3, 6, 9].includes(i)) { + const ix = i / 3 - 1; + if (promotedPosts[ix] !== undefined) { + if (get(_posts, [i], {}).permlink !== promotedPosts[ix].permlink) { + _posts = insert(_posts, i, promotedPosts[ix]); + } } } - } - }); - } - // Promoted post end + }); + } + // Promoted post end - if (refreshing) { - this.setState({ - posts: _posts, - }); - } else if (!refreshing) { - this.setState({ - posts: _posts, - startAuthor: result[result.length - 1] && result[result.length - 1].author, - startPermlink: result[result.length - 1] && result[result.length - 1].permlink, - }); + if (refreshing) { + } else if (!refreshing) { + setStartAuthor(result[result.length - 1] && result[result.length - 1].author); + setStartPermlink(result[result.length - 1] && result[result.length - 1].permlink); + } + setPosts(_posts); + setRefreshing(false); + setIsLoading(false); } - - this.setState({ - refreshing: false, - isLoading: false, - }); + } else if (result.length === 0) { + setIsNoPost(true); } - } else if (result.length === 0) { - this.setState({ isNoPost: true }); - } - }) - .catch(() => { - this.setState({ - refreshing: false, + }) + .catch(() => { + setRefreshing(false); }); - }); + }, + [ + currentAccountUsername, + filterOptions, + getFor, + isConnected, + nsfw, + posts, + promotedPosts, + refreshing, + selectedFilterIndex, + setFeedPosts, + startAuthor, + startPermlink, + tag, + ], + ); + + const _handleOnRefreshPosts = async () => { + setRefreshing(true); + if (pageType !== 'profiles') { + await _getPromotePosts(); + } + + _loadPosts(); }; - _handleOnRefreshPosts = () => { - const { pageType } = this.props; - - this.setState( - { - refreshing: true, - }, - async () => { - if (pageType !== 'profiles') { - await this._getPromotePosts(); - } - - this._loadPosts(); - }, - ); - }; - - _renderFooter = () => { - const { isLoading } = this.state; - + const _renderFooter = () => { if (isLoading) { return ( @@ -267,29 +274,15 @@ class PostsView extends Component { ); } + return null; }; - _handleOnDropdownSelect = async index => { - await this.setState({ - selectedFilterIndex: index, - posts: [], - startAuthor: '', - startPermlink: '', - isNoPost: false, - }); - this._loadPosts(); - }; - - _handleOnPressLogin = () => { - const { navigation } = this.props; + const _handleOnPressLogin = () => { navigation.navigate(ROUTES.SCREENS.LOGIN); }; - _renderEmptyContent = () => { - const { intl, getFor, isLoginDone, isLoggedIn, tag } = this.props; - const { isNoPost } = this.state; - + const _renderEmptyContent = () => { if (getFor === 'feed' && isLoginDone && !isLoggedIn) { return ( ); } @@ -326,73 +319,67 @@ class PostsView extends Component { ); }; - _handleOnScroll = event => { - const { scrollOffsetY } = this.state; - const { handleOnScroll } = this.props; + const _handleOnScroll = event => { const currentOffset = event.nativeEvent.contentOffset.y; if (handleOnScroll) { handleOnScroll(); } - this.setState({ scrollOffsetY: currentOffset }); - this.setState({ isShowFilterBar: scrollOffsetY > currentOffset || scrollOffsetY <= 0 }); + + setScrollOffsetY(currentOffset); + setIsShowFilterBar(scrollOffsetY > currentOffset || scrollOffsetY <= 0); }; - render() { - const { refreshing, posts, isShowFilterBar } = this.state; - const { filterOptions, selectedOptionIndex, isHideImage, handleImagesHide } = this.props; - - return ( - - {filterOptions && isShowFilterBar && ( - - )} - - - get(item, 'author', null) && ( - - ) - } - keyExtractor={(content, i) => `${get(content, 'permlink', '')}${i.toString()}`} - onEndReached={() => this._loadPosts()} - removeClippedSubviews - refreshing={refreshing} - onRefresh={() => this._handleOnRefreshPosts()} - onEndThreshold={0} - initialNumToRender={10} - ListFooterComponent={this._renderFooter} - onScrollEndDrag={this._handleOnScroll} - ListEmptyComponent={this._renderEmptyContent} - refreshControl={ - - {({ isDarkTheme }) => ( - - )} - - } + return ( + + {filterOptions && isShowFilterBar && ( + - - ); - } -} + )} -export default withNavigation(injectIntl(PostsView)); + + get(item, 'author', null) && ( + + ) + } + keyExtractor={(content, i) => `${get(content, 'permlink', '')}${i.toString()}`} + onEndReached={() => _loadPosts()} + removeClippedSubviews + refreshing={refreshing} + onRefresh={_handleOnRefreshPosts} + onEndThreshold={0} + initialNumToRender={10} + ListFooterComponent={_renderFooter} + onScrollEndDrag={_handleOnScroll} + ListEmptyComponent={_renderEmptyContent} + refreshControl={ + + {({ isDarkTheme }) => ( + + )} + + } + /> + + ); +}; + +export default withNavigation(PostsView); From 45e54ec67ddf02e5a9c62e4aecda3929370bb75c Mon Sep 17 00:00:00 2001 From: Mustafa Buyukcelebi Date: Thu, 7 Nov 2019 21:04:34 +0300 Subject: [PATCH 04/20] Removed realm library --- ios/Podfile.lock | 4 +- ios/eSteem.xcodeproj/project.pbxproj | 32 -- .../UserInterfaceState.xcuserstate | Bin 98726 -> 97873 bytes package.json | 1 - src/realm/realm.js | 160 +------- yarn.lock | 379 +----------------- 6 files changed, 15 insertions(+), 561 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index d99a26faf..890ea09e7 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -360,7 +360,7 @@ DEPENDENCIES: - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: - trunk: + https://github.com/cocoapods/specs.git: - AppCenter - AppCenterReactNativeShared - boost-for-react-native @@ -523,4 +523,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 4faf3202c73803d0ba69b4aaf79ce8642ecf11b2 -COCOAPODS: 1.8.3 +COCOAPODS: 1.7.5 diff --git a/ios/eSteem.xcodeproj/project.pbxproj b/ios/eSteem.xcodeproj/project.pbxproj index 630d4c96c..46a708343 100644 --- a/ios/eSteem.xcodeproj/project.pbxproj +++ b/ios/eSteem.xcodeproj/project.pbxproj @@ -24,7 +24,6 @@ 4D1363A2D0804E3EA7132027 /* Feather.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 420ABF9795564845A0963C27 /* Feather.ttf */; }; 54D038BB7E4B4CA0805EF769 /* Entypo.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 93B182C6FFA44610AB188D7C /* Entypo.ttf */; }; 58190B3C23294814000EA0E1 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 58190B3B23294814000EA0E1 /* StoreKit.framework */; }; - 58190B582329808D000EA0E1 /* libRealmReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58190B572329807B000EA0E1 /* libRealmReact.a */; }; 588019272355C26C008397D1 /* AppCenter-Config.plist in Resources */ = {isa = PBXBuildFile; fileRef = 588019232355C26B008397D1 /* AppCenter-Config.plist */; }; 588A5055232A3A4C00FC1361 /* Sansation_Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 588A504E232A3A4B00FC1361 /* Sansation_Bold.ttf */; }; 588A5056232A3A4C00FC1361 /* RobotoMono-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 588A5050232A3A4B00FC1361 /* RobotoMono-Regular.ttf */; }; @@ -32,7 +31,6 @@ 588A5058232A3A4C00FC1361 /* Sansation_Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 588A5052232A3A4C00FC1361 /* Sansation_Regular.ttf */; }; 588A5059232A3A4C00FC1361 /* Roboto.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 588A5053232A3A4C00FC1361 /* Roboto.ttf */; }; 588A505A232A3A4C00FC1361 /* Roboto-medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 588A5054232A3A4C00FC1361 /* Roboto-medium.ttf */; }; - 58F630102350580B0017C953 /* libRealmJS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58F6300F2350580B0017C953 /* libRealmJS.a */; }; 60B4658C6F794BF28A644ADC /* FontAwesome5_Solid.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4EB466C53BAE4EDC904357B3 /* FontAwesome5_Solid.ttf */; }; 834D70F2C64AF4A71AFB8536 /* libPods-eSteemTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FEBCC53EBF278472CC890AA8 /* libPods-eSteemTests.a */; }; 8739625C16E2FD1D46235BB0 /* libPods-eSteem-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 926635867AC7C716988E74B7 /* libPods-eSteem-tvOS.a */; }; @@ -65,13 +63,6 @@ remoteGlobalIDString = 2D02E47A1E0B4A5D006451C7; remoteInfo = "eSteem-tvOS"; }; - 58190B562329807B000EA0E1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 58190B512329807B000EA0E1 /* RealmReact.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = F60690131CA2766F0003FB26; - remoteInfo = RealmReact; - }; 588A5069232A497100FC1361 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 588A5064232A497100FC1361 /* ReactNativeConfig.xcodeproj */; @@ -117,7 +108,6 @@ 58190B3B23294814000EA0E1 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; 58190B3D23294823000EA0E1 /* eSteem.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = eSteem.entitlements; path = eSteem/eSteem.entitlements; sourceTree = ""; }; 58190B4723294D1D000EA0E1 /* libreact-native-config.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libreact-native-config.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 58190B512329807B000EA0E1 /* RealmReact.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RealmReact.xcodeproj; path = "../node_modules/realm/react-native/ios/RealmReact.xcodeproj"; sourceTree = ""; }; 588019232355C26B008397D1 /* AppCenter-Config.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "AppCenter-Config.plist"; sourceTree = ""; }; 588A504E232A3A4B00FC1361 /* Sansation_Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = Sansation_Bold.ttf; path = ../src/assets/Fonts/Sansation_Bold.ttf; sourceTree = ""; }; 588A5050232A3A4B00FC1361 /* RobotoMono-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "RobotoMono-Regular.ttf"; path = "../src/assets/Fonts/RobotoMono-Regular.ttf"; sourceTree = ""; }; @@ -164,8 +154,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 58F630102350580B0017C953 /* libRealmJS.a in Frameworks */, - 58190B582329808D000EA0E1 /* libRealmReact.a in Frameworks */, 58190B3C23294814000EA0E1 /* StoreKit.framework in Frameworks */, 350AB4A00BAFD4D99C09E484 /* libPods-eSteem.a in Frameworks */, ); @@ -269,14 +257,6 @@ name = Resources; sourceTree = ""; }; - 58190B522329807B000EA0E1 /* Products */ = { - isa = PBXGroup; - children = ( - 58190B572329807B000EA0E1 /* libRealmReact.a */, - ); - name = Products; - sourceTree = ""; - }; 588A5065232A497100FC1361 /* Products */ = { isa = PBXGroup; children = ( @@ -298,7 +278,6 @@ isa = PBXGroup; children = ( 588A5064232A497100FC1361 /* ReactNativeConfig.xcodeproj */, - 58190B512329807B000EA0E1 /* RealmReact.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -483,10 +462,6 @@ ProductGroup = 588A5065232A497100FC1361 /* Products */; ProjectRef = 588A5064232A497100FC1361 /* ReactNativeConfig.xcodeproj */; }, - { - ProductGroup = 58190B522329807B000EA0E1 /* Products */; - ProjectRef = 58190B512329807B000EA0E1 /* RealmReact.xcodeproj */; - }, ); projectRoot = ""; targets = ( @@ -499,13 +474,6 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ - 58190B572329807B000EA0E1 /* libRealmReact.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRealmReact.a; - remoteRef = 58190B562329807B000EA0E1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 588A506A232A497100FC1361 /* libReactNativeConfig.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; diff --git a/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate b/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate index c0cb6ac833db55e02698569fe1c2e9884736a07e..9f7267666441dee623c18fc7f3f47def6092bc45 100644 GIT binary patch literal 97873 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 lSdWGO>c#+ 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 literal 98726 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 diff --git a/package.json b/package.json index b22b96466..0519de56f 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,6 @@ "react-navigation-stack": "^1.9.3", "react-navigation-tabs": "^2.5.5", "react-redux": "^7.1.1", - "realm": "^3.2.0", "redux": "^4.0.4", "redux-persist": "^6.0.0", "redux-promise": "^0.6.0", diff --git a/src/realm/realm.js b/src/realm/realm.js index 275f644d5..2d8e499bc 100644 --- a/src/realm/realm.js +++ b/src/realm/realm.js @@ -1,4 +1,3 @@ -import Realm from 'realm'; import sha256 from 'crypto-js/sha256'; import { AsyncStorage } from 'react-native'; @@ -10,117 +9,6 @@ const DRAFT_SCHEMA = 'draft'; const SETTINGS_SCHEMA = 'settings'; const APPLICATION_SCHEMA = 'application'; -const userSchema = { - name: USER_SCHEMA, - properties: { - username: { type: 'string' }, - avatar: { type: 'string' }, - authType: { type: 'string' }, - postingKey: { type: 'string' }, - activeKey: { type: 'string' }, - memoKey: { type: 'string' }, - masterKey: { type: 'string' }, - accessToken: { type: 'string' }, - }, -}; - -const scAccounts = { - name: SC_ACCOUNTS, - properties: { - username: { type: 'string', default: null }, - refreshToken: { type: 'string', default: null }, - expireDate: { type: 'string', default: null }, - }, -}; - -const draftSchema = { - name: DRAFT_SCHEMA, - properties: { - title: { type: 'string' }, - tags: { type: 'string' }, - body: { type: 'string' }, - username: { type: 'string' }, - }, -}; - -const settingsSchema = { - name: SETTINGS_SCHEMA, - properties: { - currency: { type: 'string', default: null }, - isDarkTheme: { type: 'bool', default: false }, - isPinCodeOpen: { type: 'bool', default: true }, - isDefaultFooter: { type: 'bool', default: true }, - language: { type: 'string', default: null }, - notification: { type: 'bool', default: true }, - nsfw: { type: 'string', default: null }, - server: { type: 'string', default: null }, - upvotePercent: { type: 'string', default: null }, - followNotification: { type: 'bool', default: true }, - voteNotification: { type: 'bool', default: true }, - commentNotification: { type: 'bool', default: true }, - mentionNotification: { type: 'bool', default: true }, - reblogNotification: { type: 'bool', default: true }, - transfersNotification: { type: 'bool', default: true }, - }, -}; - -const applicationSchema = { - name: APPLICATION_SCHEMA, - properties: { - isPushTokenSaved: { type: 'bool', default: false }, - isExistUser: { type: 'bool', default: false }, - }, -}; - -const authSchema = { - name: AUTH_SCHEMA, - properties: { - isLoggedIn: { type: 'bool', default: false }, - pinCode: { type: 'string' }, - currentUsername: { type: 'string' }, - }, -}; - -const realm = new Realm({ - path: 'esteem.realm', - schema: [userSchema, authSchema, draftSchema, settingsSchema, applicationSchema, scAccounts], - schemaVersion: 3, - migration: (oldRealm, newRealm) => { - if (oldRealm.schemaVersion < 3 && newRealm.schemaVersion > 2) { - const newObjects = newRealm.objects(SETTINGS_SCHEMA); - newObjects[0].isPinCodeOpen = true; - } - }, -}); - -const settings = realm.objects(SETTINGS_SCHEMA); - -if (Array.from(settings).length <= 0) { - realm.write(() => { - realm.create(SETTINGS_SCHEMA, { - language: '', - isDarkTheme: false, - currency: '', - notification: true, - server: '', - upvotePercent: '1', - nsfw: '0', - followNotification: true, - voteNotification: true, - commentNotification: true, - mentionNotification: true, - reblogNotification: true, - transfersNotification: true, - }); - }); -} - -export const convertToArray = realmObjectsArray => { - const copyOfJsonArray = Array.from(realmObjectsArray); - const jsonArray = JSON.parse(JSON.stringify(copyOfJsonArray)); - return jsonArray; -}; - export const getItemFromStorage = async key => { const data = await AsyncStorage.getItem(key); if (data) { @@ -138,52 +26,6 @@ export const setItemToStorage = async (key, data) => { return false; }; -export const getAllData = async () => { - try { - const keys = await AsyncStorage.getAllKeys(); - - const isMigrated = [ - USER_SCHEMA, - SC_ACCOUNTS, - AUTH_SCHEMA, - DRAFT_SCHEMA, - SETTINGS_SCHEMA, - APPLICATION_SCHEMA, - ].some(el => keys.includes(el)); - if (!isMigrated) { - const users = convertToArray(realm.objects(USER_SCHEMA)); - const scAccount = convertToArray(realm.objects(SC_ACCOUNTS)); - const draft = convertToArray(realm.objects(DRAFT_SCHEMA)); - const auth = - convertToArray(realm.objects(AUTH_SCHEMA)).length === 1 - ? convertToArray(realm.objects(AUTH_SCHEMA))[0] - : convertToArray(realm.objects(AUTH_SCHEMA)); - const setting = - convertToArray(realm.objects(SETTINGS_SCHEMA)).length === 1 - ? convertToArray(realm.objects(SETTINGS_SCHEMA))[0] - : convertToArray(realm.objects(SETTINGS_SCHEMA)); - const application = - convertToArray(realm.objects(APPLICATION_SCHEMA)).length === 1 - ? convertToArray(realm.objects(APPLICATION_SCHEMA))[0] - : convertToArray(realm.objects(APPLICATION_SCHEMA)); - - const data = [ - [USER_SCHEMA, JSON.stringify(users)], - [SC_ACCOUNTS, JSON.stringify(scAccount)], - [AUTH_SCHEMA, JSON.stringify(auth)], - [DRAFT_SCHEMA, JSON.stringify(draft)], - [SETTINGS_SCHEMA, JSON.stringify(setting)], - [APPLICATION_SCHEMA, JSON.stringify(application)], - ]; - AsyncStorage.multiSet(data); - } - } catch (error) { - return error; - } -}; - -getAllData(); - // TODO: This is getting ALL user data, we should change this method with getUserDataWithUsername export const getUserData = async () => { try { @@ -710,7 +552,7 @@ export const getSCAccount = async username => { try { const scAccountStr = await getItemFromStorage(SC_ACCOUNTS); const scAccount = scAccountStr.filter(u => u.username === username); - if (convertToArray(scAccount).length > 0) { + if (scAccount.length > 0) { return scAccount[0]; } return false; diff --git a/yarn.lock b/yarn.lock index c87d1c779..d3fdc471e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1890,20 +1890,6 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-back@^1.0.3, array-back@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" - integrity sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs= - dependencies: - typical "^2.6.0" - -array-back@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" - integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== - dependencies: - typical "^2.6.1" - array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" @@ -2273,14 +2259,6 @@ bip66@^1.1.5: dependencies: safe-buffer "^5.0.1" -bl@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - bn.js@^4.11.8, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -2367,29 +2345,11 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - buffer-crc32@^0.2.13, buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= - buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -2511,11 +2471,6 @@ capture-exit@^2.0.0: dependencies: rsvp "^4.8.4" -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - integrity sha1-cVuW6phBWTzDMGeSP17GDr2k99c= - caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -2707,15 +2662,6 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -command-line-args@^4.0.6: - version "4.0.7" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" - integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== - dependencies: - array-back "^2.0.0" - find-replace "^1.0.3" - typical "^2.6.1" - commander@2.20.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" @@ -2736,13 +2682,6 @@ commander@~2.13.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA== -commander@~2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= - dependencies: - graceful-readlink ">= 1.0.0" - common-tags@^1.4.0: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" @@ -2783,7 +2722,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.4.6, concat-stream@^1.4.7, concat-stream@^1.6.0: +concat-stream@^1.4.7, concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -3053,59 +2992,6 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= -decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== - dependencies: - file-type "^5.2.0" - is-stream "^1.1.0" - tar-stream "^1.5.2" - -decompress-tarbz2@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== - dependencies: - decompress-tar "^4.1.0" - file-type "^6.1.0" - is-stream "^1.1.0" - seek-bzip "^1.0.5" - unbzip2-stream "^1.0.9" - -decompress-targz@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== - dependencies: - decompress-tar "^4.1.1" - file-type "^5.2.0" - is-stream "^1.1.0" - -decompress-unzip@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= - dependencies: - file-type "^3.8.0" - get-stream "^2.2.0" - pify "^2.3.0" - yauzl "^2.4.2" - -decompress@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" - integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= - dependencies: - decompress-tar "^4.0.0" - decompress-tarbz2 "^4.0.0" - decompress-targz "^4.0.0" - decompress-unzip "^4.0.1" - graceful-fs "^4.1.10" - make-dir "^1.0.0" - pify "^2.3.0" - strip-dirs "^2.0.0" - dedent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.6.0.tgz#0e6da8f0ce52838ef5cec5c8f9396b0c1b64a3cb" @@ -3131,11 +3017,6 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -deepmerge@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.1.0.tgz#511a54fff405fc346f0240bb270a3e9533a31102" - integrity sha512-Q89Z26KAfA3lpPGhbF6XMfYAm3jIV3avViy6KOJ2JLzFbeWHOvPQUu5aSJIWXap3gDZC2y1eF5HXEPI2wGqgvw== - deepmerge@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.3.0.tgz#d3c47fd6f3a93d517b14426b0628a17b0125f5f7" @@ -3402,7 +3283,7 @@ encoding@^0.1.11: dependencies: iconv-lite "~0.4.13" -end-of-stream@^1.0.0, end-of-stream@^1.1.0: +end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -4132,13 +4013,6 @@ fbjs@^0.8.4, fbjs@^0.8.9: setimmediate "^1.0.5" ua-parser-js "^0.7.18" -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= - dependencies: - pend "~1.2.0" - figures@^1.3.5, figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -4169,21 +4043,6 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -file-type@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= - -file-type@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - integrity sha1-LdvqfHP/42No365J3DOMBYwritY= - -file-type@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== - file-uri-to-path@1, file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -4226,14 +4085,6 @@ find-parent-dir@^0.3.0: resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" integrity sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ= -find-replace@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" - integrity sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A= - dependencies: - array-back "^1.0.4" - test-value "^2.1.0" - find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -4331,11 +4182,6 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - fs-extra@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" @@ -4345,15 +4191,6 @@ fs-extra@^1.0.0: jsonfile "^2.1.0" klaw "^1.0.0" -fs-extra@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" @@ -4435,14 +4272,6 @@ get-stdin@^6.0.0: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== -get-stream@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -4514,16 +4343,11 @@ globals@^11.0.1, globals@^11.1.0, globals@^11.7.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.2.2" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= - growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -4703,15 +4527,6 @@ htmlparser2@^3.10.0, htmlparser2@^3.10.1: inherits "^2.0.1" readable-stream "^3.1.1" -http-basic@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-2.5.1.tgz#8ce447bdb5b6c577f8a63e3fa78056ec4bb4dbfb" - integrity sha1-jORHvbW2xXf4pj4/p4BW7Eu02/s= - dependencies: - caseless "~0.11.0" - concat-stream "^1.4.6" - http-response-object "^1.0.0" - http-errors@1.7.3, http-errors@~1.7.2: version "1.7.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" @@ -4731,11 +4546,6 @@ http-proxy-agent@^2.1.0: agent-base "4" debug "3.1.0" -http-response-object@^1.0.0, http-response-object@^1.0.1, http-response-object@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-1.1.0.tgz#a7c4e75aae82f3bb4904e4f43f615673b4d518c3" - integrity sha1-p8TnWq6C87tJBOT0P2FWc7TVGMM= - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -4844,7 +4654,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: +ini@^1.3.4, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== @@ -5082,11 +4892,6 @@ is-glob@^4.0.0, is-glob@^4.0.1: dependencies: is-extglob "^2.1.1" -is-natural-number@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= - is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -6154,13 +5959,6 @@ lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.5: pseudomap "^1.0.2" yallist "^2.1.2" -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== - dependencies: - pify "^3.0.0" - make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -6700,7 +6498,7 @@ node-fetch@2.6.0, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.5.0: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== -node-fetch@^1.0.1, node-fetch@^1.7.3: +node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== @@ -6713,11 +6511,6 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= -node-machine-id@^1.1.10: - version "1.1.12" - resolved "https://registry.yarnpkg.com/node-machine-id/-/node-machine-id-1.1.12.tgz#37904eee1e59b320bb9c5d6c0a59f3b469cb6267" - integrity sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ== - node-modules-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" @@ -6750,22 +6543,6 @@ node-pre-gyp@^0.12.0: semver "^5.3.0" tar "^4" -node-pre-gyp@^0.13.0: - version "0.13.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz#df9ab7b68dd6498137717838e4f92a33fc9daa42" - integrity sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - nopt@^4.0.1, nopt@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -7288,17 +7065,12 @@ pegjs@^0.10.0: resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -pify@^2.0.0, pify@^2.3.0: +pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= @@ -7480,7 +7252,7 @@ process@^0.11.1: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -progress@^2.0.0, progress@^2.0.3: +progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -7579,7 +7351,7 @@ q@^1.4.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qs@^6.1.0, qs@^6.5.1: +qs@^6.5.1: version "6.9.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.0.tgz#d1297e2a049c53119cb49cca366adbbacc80b409" integrity sha512-27RP4UotQORTpmNQDX8BHPukOnBP3p1uUJY5UnDhaJB+rMt9iMsok724XL+UHU23bEFOHRMQ2ZhI99qOWUMGFA== @@ -7603,11 +7375,6 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= -querystringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" - integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== - range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -8079,7 +7846,7 @@ readable-stream@3, readable-stream@^3.1.1: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@~2.3.6: +readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.5, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -8092,28 +7859,6 @@ readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.2.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -realm@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/realm/-/realm-3.2.0.tgz#32aa87c98d9db5f0c289f4d235bd35813620a903" - integrity sha512-bAS16v0jVmmH2/o4kEdBETf+ywhIy9Bq4rXKBpGZ9egSBdlYBIOfO/dhDqeMaR+toEGrfMgvobDSiQYUgGiBBw== - dependencies: - command-line-args "^4.0.6" - decompress "^4.2.0" - deepmerge "2.1.0" - fs-extra "^4.0.3" - https-proxy-agent "^2.2.1" - ini "^1.3.5" - nan "^2.12.1" - node-fetch "^1.7.3" - node-machine-id "^1.1.10" - node-pre-gyp "^0.13.0" - progress "^2.0.3" - prop-types "^15.6.2" - request "^2.88.0" - stream-counter "^1.0.0" - sync-request "^3.0.1" - url-parse "^1.4.4" - realpath-native@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" @@ -8281,7 +8026,7 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.87.0, request@^2.88.0: +request@^2.87.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -8335,11 +8080,6 @@ require-uncached@^1.0.3: caller-path "^0.1.0" resolve-from "^1.0.0" -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -8562,13 +8302,6 @@ secp256k1@^3.5.2: nan "^2.14.0" safe-buffer "^5.1.2" -seek-bzip@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= - dependencies: - commander "~2.8.1" - semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -8995,11 +8728,6 @@ stream-buffers@~2.2.0: resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4" integrity sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ= -stream-counter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-counter/-/stream-counter-1.0.0.tgz#91cf2569ce4dc5061febcd7acb26394a5a114751" - integrity sha1-kc8lac5NxQYf6816yyY5SloRR1E= - strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" @@ -9114,13 +8842,6 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= -strip-dirs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== - dependencies: - is-natural-number "^4.0.1" - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -9194,15 +8915,6 @@ symbol-tree@^3.2.2: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -sync-request@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-3.0.1.tgz#caa1235aaf889ba501076a1834c436830a82fb73" - integrity sha1-yqEjWq+Im6UBB2oYNMQ2gwqC+3M= - dependencies: - concat-stream "^1.4.7" - http-response-object "^1.0.1" - then-request "^2.0.1" - table@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" @@ -9225,19 +8937,6 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" -tar-stream@^1.5.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== - dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - tar@^4: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" @@ -9269,31 +8968,11 @@ test-exclude@^5.2.3: read-pkg-up "^4.0.0" require-main-filename "^2.0.0" -test-value@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" - integrity sha1-Edpv9nDzRxpztiXKTz/c97t0gpE= - dependencies: - array-back "^1.0.3" - typical "^2.6.0" - text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -then-request@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/then-request/-/then-request-2.2.0.tgz#6678b32fa0ca218fe569981bbd8871b594060d81" - integrity sha1-ZnizL6DKIY/laZgbvYhxtZQGDYE= - dependencies: - caseless "~0.11.0" - concat-stream "^1.4.7" - http-basic "^2.5.1" - http-response-object "^1.1.0" - promise "^7.1.1" - qs "^6.1.0" - throat@^4.0.0, throat@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" @@ -9307,7 +8986,7 @@ through2@^2.0.0, through2@^2.0.1: readable-stream "~2.3.6" xtend "~4.0.1" -through@^2.3.6, through@^2.3.8: +through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -9341,11 +9020,6 @@ tmpl@1.0.x: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -9468,11 +9142,6 @@ typescript@^2.5.1: resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w== -typical@^2.6.0, typical@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" - integrity sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0= - ua-parser-js@^0.7.18: version "0.7.20" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098" @@ -9504,14 +9173,6 @@ ultron@~1.1.0: resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== -unbzip2-stream@^1.0.9: - version "1.3.3" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" - integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg== - dependencies: - buffer "^5.2.1" - through "^2.3.8" - underscore.string@^3.3.5: version "3.3.5" resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.5.tgz#fc2ad255b8bd309e239cbc5816fd23a9b7ea4023" @@ -9583,14 +9244,6 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= -url-parse@^1.4.4: - version "1.4.7" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" - integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" @@ -9920,7 +9573,7 @@ xregexp@2.0.0: resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: +xtend@^4.0.1, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== @@ -10021,14 +9674,6 @@ yargs@^9.0.0: y18n "^3.2.1" yargs-parser "^7.0.0" -yauzl@^2.4.2: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - yazl@^2.4.1: version "2.5.1" resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" From 6118934b398e52554133f157e33955efd69507b8 Mon Sep 17 00:00:00 2001 From: ue Date: Thu, 7 Nov 2019 22:25:49 +0300 Subject: [PATCH 05/20] created custom filter enhanced posts --- .../filterBar/view/filterBarStyles.js | 6 ++++ .../filterBar/view/filterBarView.js | 23 ++++++++------ .../posts/container/postsContainer.js | 4 +++ src/components/posts/view/postsView.js | 31 +++++++++++++------ src/components/profile/profileView.js | 15 ++++++--- src/constants/options/filters.js | 3 ++ src/screens/feed/screen/feedScreen.js | 9 +++++- 7 files changed, 67 insertions(+), 24 deletions(-) diff --git a/src/components/filterBar/view/filterBarStyles.js b/src/components/filterBar/view/filterBarStyles.js index 8b5210bfa..c1d3e0145 100644 --- a/src/components/filterBar/view/filterBarStyles.js +++ b/src/components/filterBar/view/filterBarStyles.js @@ -12,8 +12,14 @@ export default EStyleSheet.create({ }, zIndex: 99, }, + dropdownWrapper: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + }, filterBarWrapper: { flexDirection: 'row', + alignItems: 'center', justifyContent: 'space-between', }, rightIconWrapper: { diff --git a/src/components/filterBar/view/filterBarView.js b/src/components/filterBar/view/filterBarView.js index 1b1c7ddd9..bd0d9dfcd 100644 --- a/src/components/filterBar/view/filterBarView.js +++ b/src/components/filterBar/view/filterBarView.js @@ -1,12 +1,12 @@ import React from 'react'; -import { View, TouchableOpacity } from 'react-native'; +import { View, Text, TouchableOpacity } from 'react-native'; import { Icon } from '../../icon'; // External Components import { DropdownButton } from '../../dropdownButton'; // Components -import { LineBreak } from '../../basicUIElements'; +import { LineBreak, Tag } from '../../basicUIElements'; // Styles import styles from './filterBarStyles'; @@ -27,18 +27,23 @@ const FilterBarView = ({ rightIconName, rightIconType, selectedOptionIndex, + customOption, }) => ( {!isHide && ( - + + + {customOption && onDropdownSelect(3)} />} + + {rightIconName && ( onRightIconPress && onRightIconPress()} diff --git a/src/components/posts/container/postsContainer.js b/src/components/posts/container/postsContainer.js index 64da5170b..b646855b9 100644 --- a/src/components/posts/container/postsContainer.js +++ b/src/components/posts/container/postsContainer.js @@ -24,6 +24,8 @@ const PostsContainer = ({ selectedOptionIndex, tag, nsfw, + filterOptionsValue, + customOption, }) => { const dispatch = useDispatch(); @@ -57,6 +59,8 @@ const PostsContainer = ({ selectedOptionIndex={selectedOptionIndex} setFeedPosts={_setFeedPosts} tag={tag} + filterOptionsValue={filterOptionsValue} + customOption={customOption} /> )} diff --git a/src/components/posts/view/postsView.js b/src/components/posts/view/postsView.js index fa468de3b..f7412b1b8 100644 --- a/src/components/posts/view/postsView.js +++ b/src/components/posts/view/postsView.js @@ -38,6 +38,8 @@ const PostsView = ({ navigation, changeForceLoadPostState, forceLoadPost, + filterOptionsValue, + customOption, }) => { const [posts, setPosts] = useState(isConnected ? [] : feedPosts); const [startAuthor, setStartAuthor] = useState(''); @@ -100,9 +102,16 @@ const PostsView = ({ useEffect(() => { if (!startAuthor && !startPermlink) { - _loadPosts(filterOptions[selectedFilterIndex].toLowerCase()); + _loadPosts(filterOptionsValue[selectedFilterIndex]); } - }, [_loadPosts, filterOptions, selectedFilterIndex, startAuthor, startPermlink]); + }, [ + _loadPosts, + filterOptions, + filterOptionsValue, + selectedFilterIndex, + startAuthor, + startPermlink, + ]); const _handleOnDropdownSelect = async index => { setSelectedFilterIndex(index); @@ -135,11 +144,15 @@ const PostsView = ({ const _loadPosts = useCallback( async type => { + if (isLoading) { + return; + } else { + setIsLoading(true); + } + const filter = type || - (filterOptions && - filterOptions.length > 0 && - filterOptions[selectedFilterIndex].toLowerCase()); + (filterOptions && filterOptions.length > 0 && filterOptionsValue[selectedFilterIndex]); let options; const limit = 3; @@ -149,11 +162,6 @@ const PostsView = ({ return null; } - // if (isLoading) { - // return null; - // } - - setIsLoading(true); if (filter === 'feed' || filter === 'blog' || getFor === 'blog' || filter === 'reblogs') { options = { tag, @@ -243,8 +251,10 @@ const PostsView = ({ [ currentAccountUsername, filterOptions, + filterOptionsValue, getFor, isConnected, + isLoading, nsfw, posts, promotedPosts, @@ -342,6 +352,7 @@ const PostsView = ({ rightIconType="MaterialIcons" onDropdownSelect={_handleOnDropdownSelect} onRightIconPress={handleImagesHide} + customOption={customOption} /> )} diff --git a/src/components/profile/profileView.js b/src/components/profile/profileView.js index 03f86c0c5..82a1fb5f8 100644 --- a/src/components/profile/profileView.js +++ b/src/components/profile/profileView.js @@ -15,7 +15,7 @@ import { TabBar } from '../tabBar'; import { Wallet } from '../wallet'; // Constants -import { PROFILE_FILTERS } from '../../constants/options/filters'; +import { PROFILE_FILTERS, PROFILE_FILTERS_VALUE } from '../../constants/options/filters'; // Utils import { getFormatedCreatedDate } from '../../utils/time'; @@ -38,13 +38,17 @@ class ProfileView extends PureComponent { _handleOnScroll = () => { const { isSummaryOpen } = this.state; - if (isSummaryOpen) this.setState({ isSummaryOpen: false }); + if (isSummaryOpen) { + this.setState({ isSummaryOpen: false }); + } }; _handleOnSummaryExpanded = () => { const { isSummaryOpen } = this.state; - if (!isSummaryOpen) this.setState({ isSummaryOpen: true }); + if (!isSummaryOpen) { + this.setState({ isSummaryOpen: true }); + } }; _handleUIChange = height => { @@ -156,7 +160,9 @@ class ProfileView extends PureComponent { estimatedWalletValue: 0, oldEstimatedWalletValue: estimatedWalletValue, }); - } else this.setState({ estimatedWalletValue: oldEstimatedWalletValue }); + } else { + this.setState({ estimatedWalletValue: oldEstimatedWalletValue }); + } }} > { return ( @@ -22,9 +27,11 @@ const FeedScreen = () => { From dcafd4854ec4bac744c9d234631b0534ccee576a Mon Sep 17 00:00:00 2001 From: Mustafa Buyukcelebi Date: Fri, 8 Nov 2019 10:35:16 +0300 Subject: [PATCH 06/20] Fixed login and logout issues --- src/containers/transferContainer.js | 4 +-- src/providers/steem/auth.js | 14 ++++---- .../container/applicationContainer.js | 2 +- .../pinCode/container/pinCodeContainer.js | 33 ++++++++++--------- 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/containers/transferContainer.js b/src/containers/transferContainer.js index e4562c6b0..149f3fc54 100644 --- a/src/containers/transferContainer.js +++ b/src/containers/transferContainer.js @@ -107,7 +107,7 @@ class TransferContainer extends Component { return validUsers; }; - _transferToAccount = (from, destination, amount, memo) => { + _transferToAccount = async (from, destination, amount, memo) => { const { pinCode, navigation, dispatch, intl } = this.props; let { currentAccount } = this.props; const { selectedAccount } = this.state; @@ -160,7 +160,7 @@ class TransferContainer extends Component { break; } if (!currentAccount.local) { - const realmData = getUserDataWithUsername(currentAccount.name); + const realmData = await getUserDataWithUsername(currentAccount.name); currentAccount.local = realmData[0]; } diff --git a/src/providers/steem/auth.js b/src/providers/steem/auth.js index 4b2c5676e..f9b794a58 100644 --- a/src/providers/steem/auth.js +++ b/src/providers/steem/auth.js @@ -32,7 +32,7 @@ export const login = async (username, password, isPinCodeOpen) => { if (!account) { return Promise.reject(new Error('auth.invalid_username')); } - if (isLoggedInUser(username)) { + if (await isLoggedInUser(username)) { return Promise.reject(new Error('auth.already_logged')); } // Public keys of user @@ -144,7 +144,7 @@ export const loginWithSC2 = async (code, isPinCodeOpen) => { account.local.avatar = avatar; } - if (isLoggedInUser(account.name)) { + if (await isLoggedInUser(account.name)) { reject(new Error('auth.already_logged')); } @@ -167,7 +167,7 @@ export const loginWithSC2 = async (code, isPinCodeOpen) => { export const setUserDataWithPinCode = async data => { try { - const result = getUserDataWithUsername(data.username); + const result = await getUserDataWithUsername(data.username); const userData = result[0]; if (!data.password) { @@ -234,7 +234,7 @@ export const updatePinCode = data => export const verifyPinCode = async data => { const pinHash = await getPinCode(); - const result = getUserDataWithUsername(data.username); + const result = await getUserDataWithUsername(data.username); const userData = result[0]; // This is migration for new pin structure, it will remove v2.2 @@ -279,8 +279,10 @@ export const switchAccount = username => new Promise((resolve, reject) => { getUser(username) .then(account => { + console.log('account 2 :', account); updateCurrentUsername(username) .then(() => { + console.log('updateCurrentUsername :', username); resolve(account); }) .catch(() => { @@ -338,8 +340,8 @@ export const getUpdatedUserData = (userData, data) => { }; }; -const isLoggedInUser = username => { - const result = getUserDataWithUsername(username); +const isLoggedInUser = async username => { + const result = await getUserDataWithUsername(username); if (result.length > 0) { return true; } diff --git a/src/screens/application/container/applicationContainer.js b/src/screens/application/container/applicationContainer.js index 4e3acb206..fe0c534d7 100644 --- a/src/screens/application/container/applicationContainer.js +++ b/src/screens/application/container/applicationContainer.js @@ -638,7 +638,7 @@ class ApplicationContainer extends Component { const accountData = await switchAccount(targetAccountUsername); - const realmData = getUserDataWithUsername(targetAccountUsername); + const realmData = await getUserDataWithUsername(targetAccountUsername); const _currentAccount = accountData; _currentAccount.username = accountData.name; [_currentAccount.local] = realmData; diff --git a/src/screens/pinCode/container/pinCodeContainer.js b/src/screens/pinCode/container/pinCodeContainer.js index 4548cec71..689c733e5 100644 --- a/src/screens/pinCode/container/pinCodeContainer.js +++ b/src/screens/pinCode/container/pinCodeContainer.js @@ -207,21 +207,22 @@ class PinCodeContainer extends Component { verifyPinCode(pinData) .then(() => { this._savePinCode(pin); - const realmData = getUserDataWithUsername(currentAccount.name); - const _currentAccount = currentAccount; - _currentAccount.username = _currentAccount.name; - [_currentAccount.local] = realmData; - dispatch(updateCurrentAccount({ ..._currentAccount })); - dispatch(closePinCodeModal()); - if (callback) callback(pin, oldPinCode); - if (navigateTo) { - const navigateAction = NavigationActions.navigate({ - routeName: navigateTo, - params: navigateParams, - action: NavigationActions.navigate({ routeName: navigateTo }), - }); - dispatch(navigateAction); - } + getUserDataWithUsername(currentAccount.name).then(realmData => { + const _currentAccount = currentAccount; + _currentAccount.username = _currentAccount.name; + [_currentAccount.local] = realmData; + dispatch(updateCurrentAccount({ ..._currentAccount })); + dispatch(closePinCodeModal()); + if (callback) callback(pin, oldPinCode); + if (navigateTo) { + const navigateAction = NavigationActions.navigate({ + routeName: navigateTo, + params: navigateParams, + action: NavigationActions.navigate({ routeName: navigateTo }), + }); + dispatch(navigateAction); + } + }); }) .catch(err => { Alert.alert( @@ -246,7 +247,7 @@ class PinCodeContainer extends Component { const { intl, currentAccount, applicationPinCode } = this.props; const { isExistUser, pinCode } = this.state; - const realmData = getUserDataWithUsername(currentAccount.name); + const realmData = await getUserDataWithUsername(currentAccount.name); const userData = realmData[0]; // For exist users From 86d415756eb0dcd66a6af5c01c96848d5863f8fc Mon Sep 17 00:00:00 2001 From: Mustafa Buyukcelebi Date: Fri, 8 Nov 2019 11:33:43 +0300 Subject: [PATCH 07/20] Update src/providers/steem/auth.js --- src/providers/steem/auth.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/providers/steem/auth.js b/src/providers/steem/auth.js index f9b794a58..3076b0e1e 100644 --- a/src/providers/steem/auth.js +++ b/src/providers/steem/auth.js @@ -279,7 +279,6 @@ export const switchAccount = username => new Promise((resolve, reject) => { getUser(username) .then(account => { - console.log('account 2 :', account); updateCurrentUsername(username) .then(() => { console.log('updateCurrentUsername :', username); From 92d452dba9df92d2c7f96718640bf2b66c471b2c Mon Sep 17 00:00:00 2001 From: Mustafa Buyukcelebi Date: Fri, 8 Nov 2019 11:33:51 +0300 Subject: [PATCH 08/20] Update src/providers/steem/auth.js --- src/providers/steem/auth.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/providers/steem/auth.js b/src/providers/steem/auth.js index 3076b0e1e..594ac64c6 100644 --- a/src/providers/steem/auth.js +++ b/src/providers/steem/auth.js @@ -281,7 +281,6 @@ export const switchAccount = username => .then(account => { updateCurrentUsername(username) .then(() => { - console.log('updateCurrentUsername :', username); resolve(account); }) .catch(() => { From 16ba0364dddc90b5bd875a292ffdc7a2e864873c Mon Sep 17 00:00:00 2001 From: ue Date: Sun, 10 Nov 2019 00:09:12 +0300 Subject: [PATCH 09/20] removed hot filter --- src/components/points/view/pointsStyles.js | 1 + src/constants/options/filters.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/points/view/pointsStyles.js b/src/components/points/view/pointsStyles.js index bb0d07464..79df62eb6 100644 --- a/src/components/points/view/pointsStyles.js +++ b/src/components/points/view/pointsStyles.js @@ -120,6 +120,7 @@ export default EStyleSheet.create({ scrollContainer: { flex: 1, backgroundColor: '$primaryBackgroundColor', + marginBottom: 60, }, popoverDetails: { flexDirection: 'row', diff --git a/src/constants/options/filters.js b/src/constants/options/filters.js index 0fe3803b8..189812cfe 100644 --- a/src/constants/options/filters.js +++ b/src/constants/options/filters.js @@ -1,5 +1,5 @@ -export const POPULAR_FILTERS = ['TRENDING', 'HOT', 'NEW', 'PROMOTED']; -export const POPULAR_FILTERS_VALUE = ['trending', 'hot', 'created', 'promoted']; +export const POPULAR_FILTERS = ['TRENDING', 'NEW', 'PROMOTED']; +export const POPULAR_FILTERS_VALUE = ['trending', 'created', 'promoted']; export const PROFILE_FILTERS = ['BLOG', 'FEED']; export const PROFILE_FILTERS_VALUE = ['blog', 'feed']; From 0100ac046071f594dc5839653f7c6d478839eb47 Mon Sep 17 00:00:00 2001 From: ue Date: Sun, 10 Nov 2019 00:13:14 +0300 Subject: [PATCH 10/20] fixed spacing issue for custom option --- src/components/filterBar/view/filterBarStyles.js | 4 ++++ src/components/filterBar/view/filterBarView.js | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/filterBar/view/filterBarStyles.js b/src/components/filterBar/view/filterBarStyles.js index c1d3e0145..76cc94521 100644 --- a/src/components/filterBar/view/filterBarStyles.js +++ b/src/components/filterBar/view/filterBarStyles.js @@ -30,4 +30,8 @@ export default EStyleSheet.create({ color: '$darkIconColor', textAlign: 'center', }, + customOptionWrapper: { + left: 120, + position: 'absolute', + }, }); diff --git a/src/components/filterBar/view/filterBarView.js b/src/components/filterBar/view/filterBarView.js index bd0d9dfcd..59743f0c6 100644 --- a/src/components/filterBar/view/filterBarView.js +++ b/src/components/filterBar/view/filterBarView.js @@ -41,7 +41,11 @@ const FilterBarView = ({ onSelect={onDropdownSelect} selectedOptionIndex={selectedOptionIndex} /> - {customOption && onDropdownSelect(3)} />} + + {customOption && ( + onDropdownSelect(3)} /> + )} + {rightIconName && ( From ccab073a563abf0bb0376b171712c069101a7755 Mon Sep 17 00:00:00 2001 From: ue Date: Sun, 10 Nov 2019 00:24:29 +0300 Subject: [PATCH 11/20] fixed search result issues --- src/components/posts/view/postsView.js | 4 +++- .../searchResult/screen/searchResultScreen.js | 14 +++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/components/posts/view/postsView.js b/src/components/posts/view/postsView.js index f7412b1b8..10a002c6b 100644 --- a/src/components/posts/view/postsView.js +++ b/src/components/posts/view/postsView.js @@ -102,7 +102,9 @@ const PostsView = ({ useEffect(() => { if (!startAuthor && !startPermlink) { - _loadPosts(filterOptionsValue[selectedFilterIndex]); + _loadPosts( + filterOptions && filterOptions.length > 0 && filterOptionsValue[selectedFilterIndex], + ); } }, [ _loadPosts, diff --git a/src/screens/searchResult/screen/searchResultScreen.js b/src/screens/searchResult/screen/searchResultScreen.js index c7dee45b2..063ec0c7f 100644 --- a/src/screens/searchResult/screen/searchResultScreen.js +++ b/src/screens/searchResult/screen/searchResultScreen.js @@ -10,6 +10,13 @@ import { SearchInput, Posts, TabBar } from '../../../components'; import styles from './searchResultStyles'; import globalStyles from '../../../globalStyles'; +import { + POPULAR_FILTERS, + PROFILE_FILTERS, + PROFILE_FILTERS_VALUE, + POPULAR_FILTERS_VALUE, +} from '../../../constants/options/filters'; + class SearchResultScreen extends PureComponent { constructor(props) { super(props); @@ -46,7 +53,12 @@ class SearchResultScreen extends PureComponent { })} style={styles.tabbarItem} > - + From f9a82e6d6fa5ce6fc8e729c95086985f6da00728 Mon Sep 17 00:00:00 2001 From: ue Date: Sun, 10 Nov 2019 00:30:04 +0300 Subject: [PATCH 12/20] fixed dark mode splash screen --- src/screens/launch/screen/launchScreen.js | 4 ++-- src/screens/launch/screen/launchStyles.js | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/screens/launch/screen/launchScreen.js b/src/screens/launch/screen/launchScreen.js index c428b038f..7de46acf1 100644 --- a/src/screens/launch/screen/launchScreen.js +++ b/src/screens/launch/screen/launchScreen.js @@ -1,11 +1,11 @@ import React from 'react'; import { View } from 'react-native'; import LottieView from 'lottie-react-native'; - +import { initialMode as nativeThemeInitialMode } from 'react-native-dark-mode'; import styles from './launchStyles'; const LaunchScreen = () => ( - + ); diff --git a/src/screens/launch/screen/launchStyles.js b/src/screens/launch/screen/launchStyles.js index 474f80476..86fe06aa2 100644 --- a/src/screens/launch/screen/launchStyles.js +++ b/src/screens/launch/screen/launchStyles.js @@ -6,4 +6,10 @@ export default EStyleSheet.create({ justifyContent: 'center', alignItems: 'center', }, + darkContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#1e2835', + }, }); From f5bd46f605fdb430c9c466f623903de7ec61d87e Mon Sep 17 00:00:00 2001 From: Mustafa Buyukcelebi Date: Sun, 10 Nov 2019 23:18:00 +0300 Subject: [PATCH 13/20] Fixed realm to asyncstorage issues --- src/components/sideMenu/view/sideMenuView.js | 11 +++++- src/containers/transferContainer.js | 4 +- src/providers/steem/auth.js | 12 +++--- src/realm/realm.js | 38 +++++++++++++------ src/redux/store/store.js | 1 + .../container/applicationContainer.js | 2 +- .../pinCode/container/pinCodeContainer.js | 33 ++++++++-------- 7 files changed, 62 insertions(+), 39 deletions(-) diff --git a/src/components/sideMenu/view/sideMenuView.js b/src/components/sideMenu/view/sideMenuView.js index c5a89a31e..9f315ae9f 100644 --- a/src/components/sideMenu/view/sideMenuView.js +++ b/src/components/sideMenu/view/sideMenuView.js @@ -4,6 +4,7 @@ import { injectIntl } from 'react-intl'; import LinearGradient from 'react-native-linear-gradient'; import ActionSheet from 'react-native-actionsheet'; import VersionNumber from 'react-native-version-number'; +import { getStorageType } from '../../../realm/realm'; // Components import { IconButton } from '../../buttons'; @@ -31,10 +32,16 @@ class SideMenuView extends Component { this.state = { menuItems: props.isLoggedIn ? MENU.AUTH_MENU_ITEMS : MENU.NO_AUTH_MENU_ITEMS, isAddAccountIconActive: false, + storageT: 'R', }; } // Component Life Cycles + componentDidMount() { + getStorageType().then(item => { + this.setState({ storageT: item }); + }); + } componentWillReceiveProps(nextProps) { const { isLoggedIn, accounts } = this.props; @@ -87,7 +94,7 @@ class SideMenuView extends Component { render() { const { currentAccount, isLoggedIn, intl, handleLogout } = this.props; - const { menuItems, isAddAccountIconActive } = this.state; + const { menuItems, isAddAccountIconActive, storageT } = this.state; const { version } = PackageJson; const { buildVersion } = VersionNumber; @@ -169,7 +176,7 @@ class SideMenuView extends Component { )} /> - {`v${version}, ${buildVersion}`} + {`v${version}, ${buildVersion}${storageT}`} (this.ActionSheet = o)} options={[ diff --git a/src/containers/transferContainer.js b/src/containers/transferContainer.js index e4562c6b0..149f3fc54 100644 --- a/src/containers/transferContainer.js +++ b/src/containers/transferContainer.js @@ -107,7 +107,7 @@ class TransferContainer extends Component { return validUsers; }; - _transferToAccount = (from, destination, amount, memo) => { + _transferToAccount = async (from, destination, amount, memo) => { const { pinCode, navigation, dispatch, intl } = this.props; let { currentAccount } = this.props; const { selectedAccount } = this.state; @@ -160,7 +160,7 @@ class TransferContainer extends Component { break; } if (!currentAccount.local) { - const realmData = getUserDataWithUsername(currentAccount.name); + const realmData = await getUserDataWithUsername(currentAccount.name); currentAccount.local = realmData[0]; } diff --git a/src/providers/steem/auth.js b/src/providers/steem/auth.js index 4b2c5676e..594ac64c6 100644 --- a/src/providers/steem/auth.js +++ b/src/providers/steem/auth.js @@ -32,7 +32,7 @@ export const login = async (username, password, isPinCodeOpen) => { if (!account) { return Promise.reject(new Error('auth.invalid_username')); } - if (isLoggedInUser(username)) { + if (await isLoggedInUser(username)) { return Promise.reject(new Error('auth.already_logged')); } // Public keys of user @@ -144,7 +144,7 @@ export const loginWithSC2 = async (code, isPinCodeOpen) => { account.local.avatar = avatar; } - if (isLoggedInUser(account.name)) { + if (await isLoggedInUser(account.name)) { reject(new Error('auth.already_logged')); } @@ -167,7 +167,7 @@ export const loginWithSC2 = async (code, isPinCodeOpen) => { export const setUserDataWithPinCode = async data => { try { - const result = getUserDataWithUsername(data.username); + const result = await getUserDataWithUsername(data.username); const userData = result[0]; if (!data.password) { @@ -234,7 +234,7 @@ export const updatePinCode = data => export const verifyPinCode = async data => { const pinHash = await getPinCode(); - const result = getUserDataWithUsername(data.username); + const result = await getUserDataWithUsername(data.username); const userData = result[0]; // This is migration for new pin structure, it will remove v2.2 @@ -338,8 +338,8 @@ export const getUpdatedUserData = (userData, data) => { }; }; -const isLoggedInUser = username => { - const result = getUserDataWithUsername(username); +const isLoggedInUser = async username => { + const result = await getUserDataWithUsername(username); if (result.length > 0) { return true; } diff --git a/src/realm/realm.js b/src/realm/realm.js index 275f644d5..f797b8594 100644 --- a/src/realm/realm.js +++ b/src/realm/realm.js @@ -9,6 +9,7 @@ const AUTH_SCHEMA = 'auth'; const DRAFT_SCHEMA = 'draft'; const SETTINGS_SCHEMA = 'settings'; const APPLICATION_SCHEMA = 'application'; +const STORAGE_SCHEMA = 'storage'; const userSchema = { name: USER_SCHEMA, @@ -174,6 +175,7 @@ export const getAllData = async () => { [DRAFT_SCHEMA, JSON.stringify(draft)], [SETTINGS_SCHEMA, JSON.stringify(setting)], [APPLICATION_SCHEMA, JSON.stringify(application)], + [STORAGE_SCHEMA, 'A'], ]; AsyncStorage.multiSet(data); } @@ -388,8 +390,8 @@ export const getPinCode = async () => { export const getPinCodeOpen = async () => { try { const setting = await getItemFromStorage(SETTINGS_SCHEMA); - if (setting[0]) { - return setting[0].isPinCodeOpen; + if (setting) { + return setting.isPinCodeOpen; } return false; } catch (error) { @@ -426,8 +428,8 @@ export const setTheme = async isDarkTheme => { export const getTheme = async () => { try { const setting = await getItemFromStorage(SETTINGS_SCHEMA); - if (setting[0]) { - return setting[0].isDarkTheme; + if (setting) { + return setting.isDarkTheme; } return false; } catch (error) { @@ -464,8 +466,8 @@ export const setUpvotePercent = async percent => { export const getUpvotePercent = async () => { try { const setting = await getItemFromStorage(SETTINGS_SCHEMA); - if (setting[0]) { - return setting[0].upvotePercent; + if (setting) { + return setting.upvotePercent; } return false; } catch (error) { @@ -476,8 +478,8 @@ export const getUpvotePercent = async () => { export const getNsfw = async () => { try { const setting = await getItemFromStorage(SETTINGS_SCHEMA); - if (setting[0]) { - return setting[0].nsfw; + if (setting) { + return setting.nsfw; } return false; } catch (error) { @@ -577,8 +579,8 @@ export const setCurrency = async currencyProps => { export const getLanguage = async () => { try { const setting = await getItemFromStorage(SETTINGS_SCHEMA); - if (setting[0]) { - return setting[0].language; + if (setting) { + return setting.language; } return false; } catch (error) { @@ -589,8 +591,8 @@ export const getLanguage = async () => { export const getServer = async () => { try { const setting = await getItemFromStorage(SETTINGS_SCHEMA); - if (setting[0]) { - return setting[0].server; + if (setting) { + return setting.server; } return false; } catch (error) { @@ -735,3 +737,15 @@ export const removeSCAccount = async username => { return error; } }; + +export const getStorageType = async () => { + try { + const storageType = await AsyncStorage.getItem(STORAGE_SCHEMA); + if (storageType !== null) { + return storageType; + } + return 'R'; + } catch (error) { + return error; + } +}; diff --git a/src/redux/store/store.js b/src/redux/store/store.js index ad38eefa4..b15047a7f 100644 --- a/src/redux/store/store.js +++ b/src/redux/store/store.js @@ -14,6 +14,7 @@ const persistConfig = { storage: AsyncStorage, // Blacklist (Don't Save Specific Reducers) blacklist: ['nav', 'application'], + timeout: 0, }; // Middleware: Redux Persist Persisted Reducer diff --git a/src/screens/application/container/applicationContainer.js b/src/screens/application/container/applicationContainer.js index 4e3acb206..fe0c534d7 100644 --- a/src/screens/application/container/applicationContainer.js +++ b/src/screens/application/container/applicationContainer.js @@ -638,7 +638,7 @@ class ApplicationContainer extends Component { const accountData = await switchAccount(targetAccountUsername); - const realmData = getUserDataWithUsername(targetAccountUsername); + const realmData = await getUserDataWithUsername(targetAccountUsername); const _currentAccount = accountData; _currentAccount.username = accountData.name; [_currentAccount.local] = realmData; diff --git a/src/screens/pinCode/container/pinCodeContainer.js b/src/screens/pinCode/container/pinCodeContainer.js index 4548cec71..689c733e5 100644 --- a/src/screens/pinCode/container/pinCodeContainer.js +++ b/src/screens/pinCode/container/pinCodeContainer.js @@ -207,21 +207,22 @@ class PinCodeContainer extends Component { verifyPinCode(pinData) .then(() => { this._savePinCode(pin); - const realmData = getUserDataWithUsername(currentAccount.name); - const _currentAccount = currentAccount; - _currentAccount.username = _currentAccount.name; - [_currentAccount.local] = realmData; - dispatch(updateCurrentAccount({ ..._currentAccount })); - dispatch(closePinCodeModal()); - if (callback) callback(pin, oldPinCode); - if (navigateTo) { - const navigateAction = NavigationActions.navigate({ - routeName: navigateTo, - params: navigateParams, - action: NavigationActions.navigate({ routeName: navigateTo }), - }); - dispatch(navigateAction); - } + getUserDataWithUsername(currentAccount.name).then(realmData => { + const _currentAccount = currentAccount; + _currentAccount.username = _currentAccount.name; + [_currentAccount.local] = realmData; + dispatch(updateCurrentAccount({ ..._currentAccount })); + dispatch(closePinCodeModal()); + if (callback) callback(pin, oldPinCode); + if (navigateTo) { + const navigateAction = NavigationActions.navigate({ + routeName: navigateTo, + params: navigateParams, + action: NavigationActions.navigate({ routeName: navigateTo }), + }); + dispatch(navigateAction); + } + }); }) .catch(err => { Alert.alert( @@ -246,7 +247,7 @@ class PinCodeContainer extends Component { const { intl, currentAccount, applicationPinCode } = this.props; const { isExistUser, pinCode } = this.state; - const realmData = getUserDataWithUsername(currentAccount.name); + const realmData = await getUserDataWithUsername(currentAccount.name); const userData = realmData[0]; // For exist users From a772c8f17add8950434a10a0fca8c1a3f4a9fdcc Mon Sep 17 00:00:00 2001 From: Mustafa Buyukcelebi Date: Mon, 11 Nov 2019 01:22:17 +0300 Subject: [PATCH 14/20] Fixed clean start issues --- src/realm/realm.js | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/realm/realm.js b/src/realm/realm.js index f797b8594..32ce136b9 100644 --- a/src/realm/realm.js +++ b/src/realm/realm.js @@ -199,8 +199,11 @@ export const getUserData = async () => { export const getUserDataWithUsername = async username => { try { const user = await getItemFromStorage(USER_SCHEMA); - const userObj = user.filter(u => u.username === username); - return userObj; + if (user) { + const userObj = user.filter(u => u.username === username); + return userObj; + } + return []; } catch (error) { return error; } @@ -209,7 +212,7 @@ export const getUserDataWithUsername = async username => { export const setUserData = async userData => { try { const account = await getUserDataWithUsername(userData.username); - const user = await getItemFromStorage(USER_SCHEMA); + const user = (await getItemFromStorage(USER_SCHEMA)) || []; if (account.length === 0) { user.push(userData); @@ -607,7 +610,23 @@ export const getSettings = async () => { if (setting) { return setting; } - return false; + const settingData = { + language: '', + isDarkTheme: false, + currency: '', + notification: true, + server: '', + upvotePercent: '1', + nsfw: '0', + followNotification: true, + voteNotification: true, + commentNotification: true, + mentionNotification: true, + reblogNotification: true, + transfersNotification: true, + }; + await setItemToStorage(SETTINGS_SCHEMA, settingData); + return settingData; } catch (error) { return error; } From 93478f36456b8145aff21e70c304cdd4c63b6446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?u=C4=9Fur=20erdal?= Date: Mon, 11 Nov 2019 21:58:55 +0300 Subject: [PATCH 15/20] Update src/components/header/view/headerView.js Co-Authored-By: Mustafa Buyukcelebi --- src/components/header/view/headerView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/header/view/headerView.js b/src/components/header/view/headerView.js index d24df9997..8f9bf0aa3 100644 --- a/src/components/header/view/headerView.js +++ b/src/components/header/view/headerView.js @@ -88,7 +88,7 @@ const HeaderView = ({ style={styles.backButton} iconStyle={styles.backIcon} name="md-arrow-back" - onPress={() => handleOnPressBackButton()} + onPress={handleOnPressBackButton} /> ) : ( From 358f37bc708f01649488ef8b5aad6898da079d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?u=C4=9Fur=20erdal?= Date: Mon, 11 Nov 2019 21:59:41 +0300 Subject: [PATCH 16/20] Update src/components/posts/view/postsView.js Co-Authored-By: Mustafa Buyukcelebi --- src/components/posts/view/postsView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/posts/view/postsView.js b/src/components/posts/view/postsView.js index 10a002c6b..f49ea6507 100644 --- a/src/components/posts/view/postsView.js +++ b/src/components/posts/view/postsView.js @@ -367,7 +367,7 @@ const PostsView = ({ ) } keyExtractor={(content, i) => `${get(content, 'permlink', '')}${i.toString()}`} - onEndReached={() => _loadPosts()} + onEndReached={_loadPosts} removeClippedSubviews refreshing={refreshing} onRefresh={_handleOnRefreshPosts} From db3e5447d98cb09f1a98d579a441a07a2e555c7e Mon Sep 17 00:00:00 2001 From: ue Date: Mon, 11 Nov 2019 22:12:27 +0300 Subject: [PATCH 17/20] fixed review comments --- src/components/posts/view/postsView.js | 80 +++++++++++++------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/components/posts/view/postsView.js b/src/components/posts/view/postsView.js index f49ea6507..3f45974fd 100644 --- a/src/components/posts/view/postsView.js +++ b/src/components/posts/view/postsView.js @@ -343,42 +343,42 @@ const PostsView = ({ }; return ( - - {filterOptions && isShowFilterBar && ( - - )} + + {({ isDarkTheme }) => ( + + {filterOptions && isShowFilterBar && ( + + )} - - get(item, 'author', null) && ( - - ) - } - keyExtractor={(content, i) => `${get(content, 'permlink', '')}${i.toString()}`} - onEndReached={_loadPosts} - removeClippedSubviews - refreshing={refreshing} - onRefresh={_handleOnRefreshPosts} - onEndThreshold={0} - initialNumToRender={10} - ListFooterComponent={_renderFooter} - onScrollEndDrag={_handleOnScroll} - ListEmptyComponent={_renderEmptyContent} - refreshControl={ - - {({ isDarkTheme }) => ( + + get(item, 'author', null) && ( + + ) + } + keyExtractor={(content, i) => `${get(content, 'permlink', '')}${i.toString()}`} + onEndReached={_loadPosts} + removeClippedSubviews + refreshing={refreshing} + onRefresh={_handleOnRefreshPosts} + onEndThreshold={0} + initialNumToRender={10} + ListFooterComponent={_renderFooter} + onScrollEndDrag={_handleOnScroll} + ListEmptyComponent={_renderEmptyContent} + refreshControl={ - )} - - } - /> - + } + /> + + )} + ); }; From 149ae7498ac49113a1a4e5cb6db5d8317bdf860e Mon Sep 17 00:00:00 2001 From: ue Date: Mon, 11 Nov 2019 23:22:14 +0300 Subject: [PATCH 18/20] updated auth js a bit --- src/providers/steem/auth.js | 97 ++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 40 deletions(-) diff --git a/src/providers/steem/auth.js b/src/providers/steem/auth.js index 594ac64c6..a815d88b2 100644 --- a/src/providers/steem/auth.js +++ b/src/providers/steem/auth.js @@ -29,18 +29,22 @@ export const login = async (username, password, isPinCodeOpen) => { let authType = ''; // Get user account data from STEEM Blockchain const account = await getUser(username); + const isUserLoggedIn = await isLoggedInUser(username); + if (!account) { return Promise.reject(new Error('auth.invalid_username')); } - if (await isLoggedInUser(username)) { + + if (isUserLoggedIn) { return Promise.reject(new Error('auth.already_logged')); } + // Public keys of user const publicKeys = { - activeKey: account.active.key_auths.map(x => x[0])[0], - memoKey: account.memo_key, - ownerKey: account.owner.key_auths.map(x => x[0])[0], - postingKey: account.posting.key_auths.map(x => x[0])[0], + activeKey: get(account, 'active.key_auths', []).map(x => x[0])[0], + memoKey: get(account, 'memo_key', ''), + ownerKey: get(account, 'owner.key_auths', []).map(x => x[0])[0], + postingKey: get(account, 'posting.key_auths').map(x => x[0])[0], }; // // Set private keys of user @@ -50,8 +54,11 @@ export const login = async (username, password, isPinCodeOpen) => { Object.keys(publicKeys).map(pubKey => { if (publicKeys[pubKey] === privateKeys[pubKey].createPublic().toString()) { loginFlag = true; - if (privateKeys.isMasterKey) authType = AUTH_TYPE.MASTER_KEY; - else authType = pubKey; + if (privateKeys.isMasterKey) { + authType = AUTH_TYPE.MASTER_KEY; + } else { + authType = pubKey; + } } }); @@ -105,7 +112,7 @@ export const login = async (username, password, isPinCodeOpen) => { export const loginWithSC2 = async (code, isPinCodeOpen) => { const scTokens = await getSCAccessToken(code); - await steemConnect.setAccessToken(scTokens.access_token); + await steemConnect.setAccessToken(get(scTokens, 'access_token', '')); const scAccount = await steemConnect.me(); const account = await getUser(scAccount.account.name); let avatar = ''; @@ -130,13 +137,14 @@ export const loginWithSC2 = async (code, isPinCodeOpen) => { memoKey: '', accessToken: '', }; + const isUserLoggedIn = await isLoggedInUser(account.name); if (isPinCodeOpen) { account.local = userData; } else { const resData = { pinCode: Config.DEFAULT_PIN, - accessToken: scTokens.access_token, + accessToken: get(scTokens, 'access_token', ''), }; const updatedUserData = await getUpdatedUserData(userData, resData); @@ -144,7 +152,7 @@ export const loginWithSC2 = async (code, isPinCodeOpen) => { account.local.avatar = avatar; } - if (await isLoggedInUser(account.name)) { + if (isUserLoggedIn) { reject(new Error('auth.already_logged')); } @@ -157,7 +165,7 @@ export const loginWithSC2 = async (code, isPinCodeOpen) => { }; await setAuthStatus(authData); await setSCAccount(scTokens); - resolve({ ...account, accessToken: scTokens.access_token }); + resolve({ ...account, accessToken: get(scTokens, 'access_token', '') }); }) .catch(() => { reject(new Error('auth.unknow_error')); @@ -178,13 +186,13 @@ export const setUserDataWithPinCode = async data => { get(userData, 'postingKey'); if (publicKey) { - data.password = decryptKey(publicKey, data.pinCode); + data.password = decryptKey(publicKey, get(data, 'pinCode')); } } const updatedUserData = getUpdatedUserData(userData, data); - await setPinCode(data.pinCode); + await setPinCode(get(data, 'pinCode')); await updateUserData(updatedUserData); return updatedUserData; @@ -197,15 +205,15 @@ export const updatePinCode = data => new Promise((resolve, reject) => { let currentUser = null; try { - setPinCode(data.pinCode); + setPinCode(get(data, 'pinCode')); getUserData().then(async users => { if (users && users.length > 0) { await users.forEach(userData => { if ( - userData.authType === AUTH_TYPE.MASTER_KEY || - userData.authType === AUTH_TYPE.ACTIVE_KEY || - userData.authType === AUTH_TYPE.MEMO_KEY || - userData.authType === AUTH_TYPE.POSTING_KEY + get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY || + get(userData, 'authType', '') === AUTH_TYPE.ACTIVE_KEY || + get(userData, 'authType', '') === AUTH_TYPE.MEMO_KEY || + get(userData, 'authType', '') === AUTH_TYPE.POSTING_KEY ) { const publicKey = get(userData, 'masterKey') || @@ -213,9 +221,12 @@ export const updatePinCode = data => get(userData, 'memoKey') || get(userData, 'postingKey'); - data.password = decryptKey(publicKey, data.oldPinCode); - } else if (userData.authType === AUTH_TYPE.STEEM_CONNECT) { - data.accessToken = decryptKey(userData.accessToken, data.oldPinCode); + data.password = decryptKey(publicKey, get(data, 'oldPinCode', '')); + } else if (get(userData, 'authType', '') === AUTH_TYPE.STEEM_CONNECT) { + data.accessToken = decryptKey( + get(userData, 'accessToken'), + get(data, 'oldPinCode', ''), + ); } const updatedUserData = getUpdatedUserData(userData, data); updateUserData(updatedUserData); @@ -240,24 +251,24 @@ export const verifyPinCode = async data => { // This is migration for new pin structure, it will remove v2.2 if (!pinHash) { try { - if (userData.authType === AUTH_TYPE.STEEM_CONNECT) { - decryptKey(userData.accessToken, data.pinCode); + if (get(userData, 'authType', '') === AUTH_TYPE.STEEM_CONNECT) { + decryptKey(get(userData, 'accessToken'), get(data, 'pinCode')); } else { - decryptKey(userData.masterKey, data.pinCode); + decryptKey(userData.masterKey, get(data, 'pinCode')); } - await setPinCode(data.pinCode); + await setPinCode(get(data, 'pinCode')); } catch (error) { return Promise.reject(new Error('Invalid pin code, please check and try again')); } } - if (sha256(data.pinCode).toString() !== pinHash) { + if (sha256(get(data, 'pinCode')).toString() !== pinHash) { return Promise.reject(new Error('auth.invalid_pin')); } if (result.length > 0) { - if (userData.authType === AUTH_TYPE.STEEM_CONNECT) { - await refreshSCToken(userData, data.pinCode); + if (get(userData, 'authType', '') === AUTH_TYPE.STEEM_CONNECT) { + await refreshSCToken(userData, get(data, 'pinCode')); } } return true; @@ -313,27 +324,33 @@ const getPrivateKeys = (username, password) => { }; export const getUpdatedUserData = (userData, data) => { - const privateKeys = getPrivateKeys(userData.username, data.password); + const privateKeys = getPrivateKeys(get(userData, 'username', ''), get(data, 'password')); + return { - username: userData.username, - authType: userData.authType, + username: get(userData, 'username', ''), + authType: get(userData, 'authType', ''), accessToken: - userData.authType === AUTH_TYPE.STEEM_CONNECT - ? encryptKey(data.accessToken, data.pinCode) + get(userData, 'authType', '') === AUTH_TYPE.STEEM_CONNECT + ? encryptKey(data.accessToken, get(data, 'pinCod')) : '', masterKey: - userData.authType === AUTH_TYPE.MASTER_KEY ? encryptKey(data.password, data.pinCode) : '', + get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY + ? encryptKey(data.password, get(data, 'pinCod')) + : '', postingKey: - userData.authType === AUTH_TYPE.MASTER_KEY || userData.authType === AUTH_TYPE.POSTING_KEY - ? encryptKey(privateKeys.postingKey.toString(), data.pinCode) + get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY || + get(userData, 'authType', '') === AUTH_TYPE.POSTING_KEY + ? encryptKey(get(privateKeys, 'postingKey', '').toString(), get(data, 'pinCod')) : '', activeKey: - userData.authType === AUTH_TYPE.MASTER_KEY || userData.authType === AUTH_TYPE.ACTIVE_KEY - ? encryptKey(privateKeys.activeKey.toString(), data.pinCode) + get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY || + get(userData, 'authType', '') === AUTH_TYPE.ACTIVE_KEY + ? encryptKey(get(privateKeys, 'activeKey', '').toString(), get(data, 'pinCod')) : '', memoKey: - userData.authType === AUTH_TYPE.MASTER_KEY || userData.authType === AUTH_TYPE.MEMO_KEY - ? encryptKey(privateKeys.memoKey.toString(), data.pinCode) + get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY || + get(userData, 'authType', '') === AUTH_TYPE.MEMO_KEY + ? encryptKey(get(privateKeys, 'memoKey', '').toString(), get(data, 'pinCod')) : '', }; }; From a1dc0459a50f58677d191549d2242b5aefefa9c2 Mon Sep 17 00:00:00 2001 From: ue Date: Mon, 11 Nov 2019 23:30:41 +0300 Subject: [PATCH 19/20] fixed pincod to pincode --- src/providers/steem/auth.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/providers/steem/auth.js b/src/providers/steem/auth.js index a815d88b2..d586648f2 100644 --- a/src/providers/steem/auth.js +++ b/src/providers/steem/auth.js @@ -331,26 +331,26 @@ export const getUpdatedUserData = (userData, data) => { authType: get(userData, 'authType', ''), accessToken: get(userData, 'authType', '') === AUTH_TYPE.STEEM_CONNECT - ? encryptKey(data.accessToken, get(data, 'pinCod')) + ? encryptKey(data.accessToken, get(data, 'pinCode')) : '', masterKey: get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY - ? encryptKey(data.password, get(data, 'pinCod')) + ? encryptKey(data.password, get(data, 'pinCode')) : '', postingKey: get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY || get(userData, 'authType', '') === AUTH_TYPE.POSTING_KEY - ? encryptKey(get(privateKeys, 'postingKey', '').toString(), get(data, 'pinCod')) + ? encryptKey(get(privateKeys, 'postingKey', '').toString(), get(data, 'pinCode')) : '', activeKey: get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY || get(userData, 'authType', '') === AUTH_TYPE.ACTIVE_KEY - ? encryptKey(get(privateKeys, 'activeKey', '').toString(), get(data, 'pinCod')) + ? encryptKey(get(privateKeys, 'activeKey', '').toString(), get(data, 'pinCode')) : '', memoKey: get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY || get(userData, 'authType', '') === AUTH_TYPE.MEMO_KEY - ? encryptKey(get(privateKeys, 'memoKey', '').toString(), get(data, 'pinCod')) + ? encryptKey(get(privateKeys, 'memoKey', '').toString(), get(data, 'pinCode')) : '', }; }; From 916aea3965a57c9638d60effa4a930964a40068a Mon Sep 17 00:00:00 2001 From: ue Date: Mon, 11 Nov 2019 23:33:41 +0300 Subject: [PATCH 20/20] fixed default value for publicKEys --- src/providers/steem/auth.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/steem/auth.js b/src/providers/steem/auth.js index d586648f2..fb71de6bf 100644 --- a/src/providers/steem/auth.js +++ b/src/providers/steem/auth.js @@ -44,7 +44,7 @@ export const login = async (username, password, isPinCodeOpen) => { activeKey: get(account, 'active.key_auths', []).map(x => x[0])[0], memoKey: get(account, 'memo_key', ''), ownerKey: get(account, 'owner.key_auths', []).map(x => x[0])[0], - postingKey: get(account, 'posting.key_auths').map(x => x[0])[0], + postingKey: get(account, 'posting.key_auths', []).map(x => x[0])[0], }; // // Set private keys of user