move channel search into ChannelContent component

This commit is contained in:
Sean Yesmunt 2020-06-18 11:10:46 -04:00
parent a479c70021
commit fa246a7f1f
5 changed files with 78 additions and 95 deletions

View file

@ -1,3 +1,4 @@
import * as SETTINGS from 'constants/settings';
import { connect } from 'react-redux';
import { PAGE_SIZE } from 'constants/claim';
import {
@ -10,6 +11,8 @@ import {
} from 'lbry-redux';
import { withRouter } from 'react-router';
import { selectUserVerifiedEmail } from 'redux/selectors/user';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import ChannelPage from './view';
const select = (state, props) => {
@ -24,6 +27,7 @@ const select = (state, props) => {
channelIsBlocked: selectChannelIsBlocked(props.uri)(state),
claim: props.uri && makeSelectClaimForUri(props.uri)(state),
isAuthenticated: selectUserVerifiedEmail(state),
showMature: makeSelectClientSetting(SETTINGS.SHOW_MATURE)(state),
};
};

View file

@ -1,11 +1,17 @@
// @flow
import * as CS from 'constants/claim_search';
import * as ICONS from 'constants/icons';
import React, { Fragment } from 'react';
import HiddenNsfwClaims from 'component/hiddenNsfwClaims';
import { withRouter } from 'react-router-dom';
import { useHistory } from 'react-router-dom';
import Button from 'component/button';
import ClaimListDiscover from 'component/claimListDiscover';
import * as CS from 'constants/claim_search';
import Ads from 'web/component/ads';
import Icon from 'component/common/icon';
import { Form, FormField } from 'component/common/form';
import { DEBOUNCE_WAIT_DURATION_MS } from 'constants/search';
const LIGHTHOUSE_URL = 'https://lighthouse.lbry.com/search';
type Props = {
uri: string,
@ -21,6 +27,7 @@ type Props = {
defaultInfiniteScroll?: Boolean,
claim: ?Claim,
isAuthenticated: boolean,
showMature: boolean,
};
function ChannelContent(props: Props) {
@ -34,8 +41,56 @@ function ChannelContent(props: Props) {
isAuthenticated,
defaultPageSize = CS.PAGE_SIZE,
defaultInfiniteScroll = true,
showMature,
} = props;
const claimsInChannel = (claim && claim.meta.claims_in_channel) || 0;
const [searchQuery, setSearchQuery] = React.useState('');
const [searchResults, setSearchResults] = React.useState(undefined);
const {
location: { pathname, search },
} = useHistory();
const url = `${pathname}${search}`;
const claimId = claim && claim.claim_id;
function handleInputChange(e) {
const { value } = e.target;
setSearchQuery(value);
}
function getResults(fetchUrl) {
fetch(fetchUrl)
.then(res => res.json())
.then(results => {
const urls = results.map(({ name, claimId }) => {
return `lbry://${name}#${claimId}`;
});
setSearchResults(urls);
})
.catch(() => {
setSearchResults(null);
});
}
React.useEffect(() => {
const timer = setTimeout(() => {
if (searchQuery === '' || !claimId) {
// In order to display original search results, search results must be set to null. A query of '' should display original results.
return setSearchResults(null);
} else {
getResults(
`${LIGHTHOUSE_URL}?s=${encodeURIComponent(searchQuery)}&channel_id=${encodeURIComponent(claimId)}${
!showMature ? '&nsfw=false' : ''
}`
);
}
}, DEBOUNCE_WAIT_DURATION_MS);
return () => clearTimeout(timer);
}, [claimId, searchQuery, showMature]);
React.useEffect(() => {
setSearchQuery('');
setSearchResults(null);
}, [url]);
return (
<Fragment>
@ -66,11 +121,24 @@ function ChannelContent(props: Props) {
{claim && claimsInChannel > 0 ? (
<ClaimListDiscover
uris={searchResults}
channelIds={[claim.claim_id]}
defaultOrderBy={CS.ORDER_BY_NEW}
pageSize={defaultPageSize}
infiniteScroll={defaultInfiniteScroll}
injectedItem={!isAuthenticated && IS_WEB && <Ads type="video" />}
meta={
<Form onSubmit={() => {}} className="wunderbar--inline">
<Icon icon={ICONS.SEARCH} />
<FormField
className="wunderbar__input"
value={searchQuery}
onChange={handleInputChange}
type="text"
placeholder={__('Search')}
/>
</Form>
}
/>
) : (
<section className="main--empty">{__("This channel hasn't published anything yet")}</section>
@ -79,4 +147,4 @@ function ChannelContent(props: Props) {
);
}
export default withRouter(ChannelContent);
export default ChannelContent;

View file

@ -95,6 +95,7 @@ function ClaimListDiscover(props: Props) {
followedTags,
injectedItem,
feeAmount,
uris,
} = props;
const didNavigateForward = history.action === 'PUSH';
const { search } = location;
@ -694,7 +695,7 @@ function ClaimListDiscover(props: Props) {
isCardBody
id={claimSearchCacheQuery}
loading={loading}
uris={claimSearchResult}
uris={uris || claimSearchResult}
onScrollBottom={handleScrollBottom}
page={page}
pageSize={CS.PAGE_SIZE}

View file

@ -1,5 +1,4 @@
import { connect } from 'react-redux';
import * as settings from 'constants/settings';
import {
makeSelectClaimIsMine,
makeSelectTitleForUri,
@ -11,7 +10,6 @@ import {
} from 'lbry-redux';
import { selectBlackListedOutpoints, doFetchSubCount, makeSelectSubCountForUri } from 'lbryinc';
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import ChannelPage from './view';
const select = (state, props) => ({
@ -24,7 +22,6 @@ const select = (state, props) => ({
isSubscribed: makeSelectIsSubscribed(props.uri, true)(state),
channelIsBlocked: selectChannelIsBlocked(props.uri)(state),
blackListedOutpoints: selectBlackListedOutpoints(state),
showMature: makeSelectClientSetting(settings.SHOW_MATURE)(state),
subCount: makeSelectSubCountForUri(props.uri)(state),
});

View file

@ -18,20 +18,14 @@ import ChannelThumbnail from 'component/channelThumbnail';
import ChannelEdit from 'component/channelEdit';
import ClaimUri from 'component/claimUri';
import classnames from 'classnames';
import { Form, FormField } from 'component/common/form';
import Icon from 'component/common/icon';
import HelpLink from 'component/common/help-link';
import { DEBOUNCE_WAIT_DURATION_MS } from 'constants/search';
import ClaimList from 'component/claimList';
import DateTime from 'component/dateTime';
import ClaimSupportButton from 'component/claimSupportButton';
const PAGE_VIEW_QUERY = `view`;
const ABOUT_PAGE = `about`;
const DISCUSSION_PAGE = `discussion`;
const LIGHTHOUSE_URL = 'https://lighthouse.lbry.com/search';
const ARROW_LEFT_KEYCODE = 37;
const ARROW_RIGHT_KEYCODE = 39;
type Props = {
uri: string,
@ -52,7 +46,6 @@ type Props = {
}>,
fetchSubCount: string => void,
subCount: number,
showMature: boolean,
};
function ChannelPage(props: Props) {
@ -69,7 +62,6 @@ function ChannelPage(props: Props) {
isSubscribed,
channelIsBlocked,
blackListedOutpoints,
showMature,
fetchSubCount,
subCount,
} = props;
@ -83,8 +75,6 @@ function ChannelPage(props: Props) {
const [editing, setEditing] = useState(false);
const [thumbPreview, setThumbPreview] = useState(thumbnail);
const [coverPreview, setCoverPreview] = useState(cover);
const [searchQuery, setSearchQuery] = useState('');
const [searchResults, setSearchResults] = useState(undefined);
const [lastYtSyncDate, setLastYtSyncDate] = useState();
const claimId = claim.claim_id;
const formattedSubCount = Number(subCount).toLocaleString();
@ -99,7 +89,6 @@ function ChannelPage(props: Props) {
let search = '?';
if (newTabIndex === 0) {
setSearchResults(null);
search += `page=${page}`;
} else if (newTabIndex === 1) {
search += `${PAGE_VIEW_QUERY}=${ABOUT_PAGE}`;
@ -109,36 +98,6 @@ function ChannelPage(props: Props) {
history.push(`${url}${search}`);
}
function getResults(fetchUrl) {
fetch(fetchUrl)
.then(res => res.json())
.then(results => {
const urls = results.map(({ name, claimId }) => {
return `lbry://${name}#${claimId}`;
});
setSearchResults(urls);
})
.catch(() => {
setSearchResults(null);
});
}
useEffect(() => {
const timer = setTimeout(() => {
if (searchQuery === '') {
// In order to display original search results, search results must be set to null. A query of '' should display original results.
return setSearchResults(null);
} else {
getResults(
`${LIGHTHOUSE_URL}?s=${encodeURIComponent(searchQuery)}&channel_id=${encodeURIComponent(claimId)}${
!showMature ? '&nsfw=false' : ''
}`
);
}
}, DEBOUNCE_WAIT_DURATION_MS);
return () => clearTimeout(timer);
}, [claimId, searchQuery]);
useEffect(() => {
Lbryio.call('yt', 'get_youtuber', { channel_claim_id: claimId }).then(response => {
if (response.is_verified_youtuber) {
@ -147,22 +106,6 @@ function ChannelPage(props: Props) {
});
}, [claimId]);
function handleInputChange(e) {
const { value } = e.target;
setSearchQuery(value);
}
/*
Since the search is inside of TabList, the left and right arrow keys change the tabIndex.
This results in the user not being able to navigate the search string by using arrow keys.
This function allows the event to change cursor position and then stops propagation to prevent tab changing.
*/
function handleSearchArrowKeys(e) {
if (e.keyCode === ARROW_LEFT_KEYCODE || e.keyCode === ARROW_RIGHT_KEYCODE) {
e.stopPropagation();
}
}
let channelIsBlackListed = false;
if (claim && blackListedOutpoints) {
@ -172,9 +115,6 @@ function ChannelPage(props: Props) {
}
React.useEffect(() => {
setSearchResults(null);
setSearchQuery('');
fetchSubCount(claimId);
}, [uri, fetchSubCount, claimId]);
@ -252,38 +192,11 @@ function ChannelPage(props: Props) {
<Tab disabled={editing}>{__('Content')}</Tab>
<Tab>{editing ? __('Editing Your Channel') : __('About')}</Tab>
<Tab disabled={editing}>{__('Comments')}</Tab>
{/* only render searchbar on content page (tab index 0 === content page) */}
{tabIndex === 0 ? (
<Form onSubmit={() => {}} className="wunderbar--inline">
<Icon icon={ICONS.SEARCH} />
<FormField
className="wunderbar__input"
value={searchQuery}
onChange={handleInputChange}
onKeyDown={handleSearchArrowKeys}
type="text"
placeholder={__('Search')}
/>
</Form>
) : (
<div />
)}
</TabList>
<TabPanels>
<TabPanel>
{searchResults ? (
<ClaimList
header={false}
headerAltControls={null}
id={`search-results-for-${claimId}`}
loading={false}
showHiddenByUser={false}
uris={searchResults}
/>
) : (
<ChannelContent uri={uri} channelIsBlackListed={channelIsBlackListed} />
)}
<ChannelContent uri={uri} channelIsBlackListed={channelIsBlackListed} />
</TabPanel>
<TabPanel>
{editing ? (