This commit is contained in:
Mustafa Buyukcelebi 2019-11-26 19:53:44 +03:00
parent 2451381917
commit 5257639629
7 changed files with 178 additions and 195 deletions

View File

@ -27,7 +27,7 @@ const SearchInputView = ({
<Icon style={styles.icon} iconType="FontAwesome" name="search" size={15} />
<TextInput
style={styles.input}
onChangeText={text => onChangeText(text)}
onChangeText={text => onChangeText && onChangeText(text)}
placeholder={placeholder}
placeholderTextColor="#c1c5c7"
autoCapitalize="none"

View File

@ -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 (
<SearchModalView
handleCloseButton={this._handleCloseButton}
handleOnChangeSearchInput={this._handleOnChangeSearchInput}
handleOnClose={handleOnClose}
handleOnPressListItem={this._handleOnPressListItem}
isOpen={isOpen}
placeholder={placeholder}
searchResults={searchResults}
/>
);
}
}
return (
<SearchModalView
handleCloseButton={_handleCloseButton}
handleOnChangeSearchInput={_handleOnChangeSearchInput}
handleOnClose={handleOnClose}
handleOnPressListItem={_handleOnPressListItem}
isOpen={isOpen}
placeholder={placeholder}
searchResults={searchResults}
/>
);
};
const mapStateToProps = state => ({
username: state.account.currentAccount.name,

View File

@ -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 (
<SearchResultScreen
currentAccount={currentAccount}
tag={tag}
navigationGoBack={this._navigationGoBack}
/>
);
}
}
const mapStateToProps = state => ({
currentAccount: state.account.currentAccount,
});
export default connect(mapStateToProps)(SearchResultContainer);

View File

@ -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;

View File

@ -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 (
<View style={styles.container}>
<SafeAreaView>
<SearchInput
onChangeText={() => {}}
handleOnModalClose={navigationGoBack}
placeholder={`#${tag}`}
editable={false}
const _navigationGoBack = () => {
navigation.goBack();
};
const _renderTabbar = () => (
<TabBar
style={styles.tabbar}
tabUnderlineDefaultWidth={80}
tabUnderlineScaleX={2}
tabBarPosition="overlayTop"
/>
);
const _getSelectedIndex = () => {
if (filter) {
const selectedIndex = POPULAR_FILTERS_VALUE.indexOf(filter);
if (selectedIndex > 0) {
return selectedIndex;
}
}
return 0;
};
return (
<View style={styles.container}>
<SafeAreaView>
<SearchInput
handleOnModalClose={_navigationGoBack}
placeholder={`#${tag}`}
editable={false}
/>
</SafeAreaView>
<ScrollableTabView style={globalStyles.tabView} renderTabBar={_renderTabbar}>
<View tabLabel={intl.formatMessage({ id: 'search.posts' })} style={styles.tabbarItem}>
<Posts
key={tag}
filterOptions={POPULAR_FILTERS}
filterOptionsValue={POPULAR_FILTERS_VALUE}
selectedOptionIndex={_getSelectedIndex()}
tag={tag}
/>
</SafeAreaView>
<ScrollableTabView
style={globalStyles.tabView}
renderTabBar={() => (
<TabBar
style={styles.tabbar}
tabUnderlineDefaultWidth={80}
tabUnderlineScaleX={2}
tabBarPosition="overlayTop"
/>
)}
>
<View
tabLabel={intl.formatMessage({
id: 'search.posts',
})}
style={styles.tabbarItem}
>
<Posts
key={tag}
filterOptions={POPULAR_FILTERS}
filterOptionsValue={POPULAR_FILTERS_VALUE}
tag={tag}
/>
</View>
</ScrollableTabView>
</View>
);
}
}
</View>
</ScrollableTabView>
</View>
);
};
export default injectIntl(SearchResultScreen);
export default SearchResultScreen;

View File

@ -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],