diff --git a/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate b/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate index 7b5d228fb..457547ef2 100644 Binary files a/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate and b/ios/eSteem.xcworkspace/xcuserdata/mistik.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/src/components/searchInput/view/searchInputView.js b/src/components/searchInput/view/searchInputView.js index 5d7467933..4dd8db6dc 100644 --- a/src/components/searchInput/view/searchInputView.js +++ b/src/components/searchInput/view/searchInputView.js @@ -27,7 +27,7 @@ const SearchInputView = ({ onChangeText(text)} + onChangeText={text => onChangeText && onChangeText(text)} placeholder={placeholder} placeholderTextColor="#c1c5c7" autoCapitalize="none" diff --git a/src/components/searchModal/container/searchModalContainer.js b/src/components/searchModal/container/searchModalContainer.js index 31975211f..d0b50b22a 100644 --- a/src/components/searchModal/container/searchModalContainer.js +++ b/src/components/searchModal/container/searchModalContainer.js @@ -1,4 +1,4 @@ -import React, { PureComponent } from 'react'; +import React, { useState } from 'react'; import { withNavigation } from 'react-navigation'; import { connect } from 'react-redux'; import get from 'lodash/get'; @@ -23,31 +23,27 @@ import SearchModalView from '../view/searchModalView'; * */ -class SearchModalContainer extends PureComponent { - constructor(props) { - super(props); - this.state = { - searchResults: {}, - }; - } - - // Component Life Cycle Functions - - // Component Functions - _handleCloseButton = () => { - const { navigation } = this.props; +const SearchModalContainer = ({ + navigation, + isConnected, + handleOnClose, + username, + isOpen, + placeholder, +}) => { + const [searchResults, setSearchResults] = useState({}); + const _handleCloseButton = () => { navigation.goBack(); }; - _handleOnChangeSearchInput = text => { - const { isConnected } = this.props; - - if (text && text.length < 2) return; - if (this.timer) { - clearTimeout(this.timer); + const _handleOnChangeSearchInput = text => { + if (text && text.length < 2) { + return; + } + if (!isConnected) { + return; } - if (!isConnected) return; if (text && text !== '@' && text !== '#') { if (text[0] === '@') { lookupAccounts(text.substr(1)).then(res => { @@ -56,7 +52,7 @@ class SearchModalContainer extends PureComponent { text: item, ...item, })); - this.setState({ searchResults: { type: 'user', data: users } }); + setSearchResults({ type: 'user', data: users }); }); } else if (text[0] === '#') { getTrendingTags(text.substr(1)).then(res => { @@ -65,13 +61,13 @@ class SearchModalContainer extends PureComponent { ...item, })); - this.setState({ searchResults: { type: 'tag', data: tags } }); + setSearchResults({ type: 'tag', data: tags }); }); - } else if (text.includes('https')) { + } else if (text.includes('https://') || text.includes('esteem://')) { const postUrl = postUrlParser(text.replace(/\s/g, '')); if (postUrl) { - const { author, permlink } = postUrl; + const { author, permlink, feedType, tag } = postUrl; if (author) { if (permlink) { @@ -87,9 +83,9 @@ class SearchModalContainer extends PureComponent { result.author = author; result.text = post.title; result.permlink = permlink; - this.setState({ searchResults: { type: 'content', data: [result] } }); + setSearchResults({ type: 'content', data: [result] }); } else { - this.setState({ searchResults: { type: 'content', data: [] } }); + setSearchResults({ type: 'content', data: [] }); } }); } else { @@ -99,7 +95,26 @@ class SearchModalContainer extends PureComponent { text: item, ...item, })); - this.setState({ searchResults: { type: 'user', data: users } }); + setSearchResults({ type: 'user', data: users }); + }); + } + } else if (feedType) { + handleOnClose(); + setSearchResults({}); + if (tag) { + navigation.navigate({ + routeName: ROUTES.SCREENS.SEARCH_RESULT, + params: { + tag: tag, + filter: feedType, + }, + }); + } else { + navigation.navigate({ + routeName: ROUTES.SCREENS.SEARCH_RESULT, + params: { + filter: feedType, + }, }); } } @@ -112,21 +127,20 @@ class SearchModalContainer extends PureComponent { text: item.title, ...item, })); - this.setState({ searchResults: { type: 'content', data: get(res, 'results', []) } }); + setSearchResults({ type: 'content', data: get(res, 'results', []) }); }); } } } }; - _handleOnPressListItem = (type, item) => { - const { navigation, handleOnClose, username } = this.props; + const _handleOnPressListItem = (type, item) => { let routeName = null; let params = null; let key = null; handleOnClose(); - this.setState({ searchResults: {} }); + setSearchResults({}); switch (type) { case 'user': @@ -164,23 +178,18 @@ class SearchModalContainer extends PureComponent { } }; - render() { - const { searchResults } = this.state; - const { handleOnClose, isOpen, placeholder } = this.props; - - return ( - - ); - } -} + return ( + + ); +}; const mapStateToProps = state => ({ username: state.account.currentAccount.name, diff --git a/src/screens/searchResult/container/searchResultContainer.js b/src/screens/searchResult/container/searchResultContainer.js deleted file mode 100644 index 3abcdfb7a..000000000 --- a/src/screens/searchResult/container/searchResultContainer.js +++ /dev/null @@ -1,44 +0,0 @@ -import React, { PureComponent } from 'react'; -import { connect } from 'react-redux'; - -// Component -import SearchResultScreen from '../screen/searchResultScreen'; - -/* - * Props Name Description Value - *@props --> props name here description here Value Type Here - * - */ - -class SearchResultContainer extends PureComponent { - constructor(props) { - super(props); - this.state = {}; - } - - _navigationGoBack = () => { - const { navigation } = this.props; - - navigation.goBack(); - }; - - render() { - const { currentAccount, navigation } = this.props; - - const tag = navigation.getParam('tag', 'esteem'); - - return ( - - ); - } -} - -const mapStateToProps = state => ({ - currentAccount: state.account.currentAccount, -}); - -export default connect(mapStateToProps)(SearchResultContainer); diff --git a/src/screens/searchResult/index.js b/src/screens/searchResult/index.js index 595b2f8e6..fabbaba9e 100644 --- a/src/screens/searchResult/index.js +++ b/src/screens/searchResult/index.js @@ -1,5 +1,4 @@ -import SearchResultScreen from './screen/searchResultScreen'; -import SearchResult from './container/searchResultContainer'; +import SearchResult from './screen/searchResultScreen'; -export { SearchResultScreen, SearchResult }; +export { SearchResult }; export default SearchResult; diff --git a/src/screens/searchResult/screen/searchResultScreen.js b/src/screens/searchResult/screen/searchResultScreen.js index 063ec0c7f..04d0682b2 100644 --- a/src/screens/searchResult/screen/searchResultScreen.js +++ b/src/screens/searchResult/screen/searchResultScreen.js @@ -1,7 +1,7 @@ -import React, { PureComponent } from 'react'; +import React from 'react'; import { View, SafeAreaView } from 'react-native'; import ScrollableTabView from 'react-native-scrollable-tab-view'; -import { injectIntl } from 'react-intl'; +import { useIntl } from 'react-intl'; // Components import { SearchInput, Posts, TabBar } from '../../../components'; @@ -10,60 +10,59 @@ 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'; +import { POPULAR_FILTERS, POPULAR_FILTERS_VALUE } from '../../../constants/options/filters'; -class SearchResultScreen extends PureComponent { - constructor(props) { - super(props); - this.state = {}; - } +const SearchResultScreen = ({ navigation }) => { + const tag = navigation.getParam('tag', ''); + const filter = navigation.getParam('filter', ''); - render() { - const { intl, tag, navigationGoBack } = this.props; + const intl = useIntl(); - return ( - - - {}} - handleOnModalClose={navigationGoBack} - placeholder={`#${tag}`} - editable={false} + const _navigationGoBack = () => { + navigation.goBack(); + }; + + const _renderTabbar = () => ( + + ); + + const _getSelectedIndex = () => { + if (filter) { + const selectedIndex = POPULAR_FILTERS_VALUE.indexOf(filter); + if (selectedIndex > 0) { + return selectedIndex; + } + } + return 0; + }; + + return ( + + + + + + + - - ( - - )} - > - - - - - - ); - } -} + + + + ); +}; -export default injectIntl(SearchResultScreen); +export default SearchResultScreen; diff --git a/src/utils/postUrlParser.js b/src/utils/postUrlParser.js index 56d99ec02..efaa1c0fc 100644 --- a/src/utils/postUrlParser.js +++ b/src/utils/postUrlParser.js @@ -1,52 +1,72 @@ +const parseCatAuthorPermlink = u => { + const postRegex = /^https?:\/\/(.*)\/(.*)\/(@[\w.\d-]+)\/(.*)/i; + const postMatch = u.match(postRegex); + + if (postMatch && postMatch.length === 5) { + return { + author: postMatch[3].replace('@', ''), + permlink: postMatch[4], + }; + } + const authorRegex = /^https?:\/\/(.*)\/(.*)\/(@[\w.\d-]+)/i; + const authorMatch = u.match(authorRegex); + if (authorMatch && authorMatch.length === 4) { + return { + author: authorMatch[3].replace('@', ''), + permlink: null, + }; + } + return null; +}; + +const parseAuthorPermlink = u => { + const r = /^https?:\/\/(.*)\/(@[\w.\d-]+)\/(.*)/i; + const match = u.match(r); + + if (match && match.length === 4) { + return { + author: match[2].replace('@', ''), + permlink: match[3], + }; + } + const authorRegex = /^https?:\/\/(.*)\/(@[\w.\d-]+)/i; + const authorMatch = u.match(authorRegex); + if (authorMatch && authorMatch.length === 3) { + return { + author: authorMatch[2].replace('@', ''), + permlink: null, + }; + } + + return null; +}; + export default url => { - const parseCatAuthorPermlink = u => { - const postRegex = /^https?:\/\/(.*)\/(.*)\/(@[\w.\d-]+)\/(.*)/i; - const postMatch = u.match(postRegex); - if (postMatch && postMatch.length === 5) { - return { - author: postMatch[3].replace('@', ''), - permlink: postMatch[4], - }; - } - const authorRegex = /^https?:\/\/(.*)\/(.*)\/(@[\w.\d-]+)/i; - const authorMatch = u.match(authorRegex); - if (authorMatch && authorMatch.length === 4) { - return { - author: authorMatch[3].replace('@', ''), - permlink: null, - }; - } - return null; - }; - - const parseAuthorPermlink = u => { - const r = /^https?:\/\/(.*)\/(@[\w.\d-]+)\/(.*)/i; - const match = u.match(r); - if (match && match.length === 4) { - return { - author: match[2].replace('@', ''), - permlink: match[3], - }; - } - const authorRegex = /^https?:\/\/(.*)\/(@[\w.\d-]+)/i; - const authorMatch = u.match(authorRegex); - if (authorMatch && authorMatch.length === 3) { - return { - author: authorMatch[2].replace('@', ''), - permlink: null, - }; - } - - return null; - }; if (url.startsWith('esteem://')) { url = url.replace('esteem://', 'https://esteem.app/'); } + const feedMatch = url.match(/^https:\/\/([\w-\.]*)\/([\w-]*)\/?([\w-]*)\/?$/); + + if (feedMatch) { + if (feedMatch[3]) { + return { + feedType: feedMatch[2], + tag: feedMatch[3], + }; + } + return { + feedType: feedMatch[2], + }; + } + if ( - ['https://esteem.app', 'https://steemit.com', 'https://steempeak.com'].some(x => - url.startsWith(x), - ) + [ + 'https://estm.to', + 'https://esteem.app', + 'https://steemit.com', + 'https://steempeak.com', + ].some(x => url.startsWith(x)) ) { return parseCatAuthorPermlink(url); } @@ -65,7 +85,7 @@ export default url => { } // For non urls with category like esteem/@good-karma/esteem-london-presentation-e3105ba6637ed - match = url.match(/^[/]?([\w.\d-]+)\/(@[\w.\d-]+)\/(.*)/); + match = url.match(/([\w.\d-]+)\/(@[\w.\d-]+)\/(.*)/); if (match && match.length === 4) { return { category: match[1],