diff --git a/static/app-strings.json b/static/app-strings.json index 6eb8bbf74..385ff366a 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -991,4 +991,4 @@ "Email %help_link% or join our %chat_link% if you encounter any trouble verifying.": "Email %help_link% or join our %chat_link% if you encounter any trouble verifying.", "Show reposts": "Show reposts", "Show reposts from the creators you follow.": "Show reposts from the creators you follow." -} \ No newline at end of file +} diff --git a/ui/component/channelContent/view.jsx b/ui/component/channelContent/view.jsx index 2b6748966..f69fb4637 100644 --- a/ui/component/channelContent/view.jsx +++ b/ui/component/channelContent/view.jsx @@ -4,7 +4,7 @@ import HiddenNsfwClaims from 'component/hiddenNsfwClaims'; import { withRouter } from 'react-router-dom'; import Button from 'component/button'; import ClaimListDiscover from 'component/claimListDiscover'; -import { TYPE_NEW } from 'component/claimListDiscover/view'; +import * as CS from 'constants/claim_search'; type Props = { uri: string, @@ -51,7 +51,7 @@ function ChannelContent(props: Props) { {!channelIsMine && claimsInChannel > 0 && } {claim && claimsInChannel > 0 ? ( - + ) : (
This channel hasn't published anything yet
)} diff --git a/ui/component/claimListDiscover/view.jsx b/ui/component/claimListDiscover/view.jsx index 74b15274c..46bb33ce9 100644 --- a/ui/component/claimListDiscover/view.jsx +++ b/ui/component/claimListDiscover/view.jsx @@ -3,6 +3,7 @@ import type { Node } from 'react'; import classnames from 'classnames'; import React, { Fragment, useEffect, useState } from 'react'; import { withRouter } from 'react-router'; +import * as CS from 'constants/claim_search'; import { createNormalizedClaimSearchKey, MATURE_TAGS } from 'lbry-redux'; import { FormField } from 'component/common/form'; import Button from 'component/button'; @@ -11,26 +12,12 @@ import ClaimList from 'component/claimList'; import ClaimPreview from 'component/claimPreview'; import { toCapitalCase } from 'util/string'; import I18nMessage from 'component/i18nMessage'; - -const PAGE_SIZE = 20; -export const TIME_DAY = 'day'; -export const TIME_WEEK = 'week'; -export const TIME_MONTH = 'month'; -export const TIME_YEAR = 'year'; -export const TIME_ALL = 'all'; - -export const TYPE_TRENDING = 'trending'; -export const TYPE_TOP = 'top'; -export const TYPE_NEW = 'new'; - -const SEARCH_TYPES = [TYPE_TRENDING, TYPE_NEW, TYPE_TOP]; -const SEARCH_TIMES = [TIME_DAY, TIME_WEEK, TIME_MONTH, TIME_YEAR, TIME_ALL]; +import * as ICONS from 'constants/icons'; type Props = { uris: Array, subscribedChannels: Array, doClaimSearch: ({}) => void, - tags: Array, loading: boolean, personalView: boolean, doToggleTagFollow: string => void, @@ -45,17 +32,22 @@ type Props = { hiddenUris: Array, hiddenNsfwMessage?: Node, channelIds?: Array, - defaultTypeSort?: string, - defaultTimeSort?: string, - defaultOrderBy?: Array, + tags: Array, + orderBy?: Array, + defaultOrderBy?: string, + freshness?: string, + defaultFreshness?: string, header?: Node, headerLabel?: string | Node, name?: string, - pageSize?: number, - claimType?: Array, + hideBlock?: boolean, + claimType?: string | Array, + defaultClaimType?: string | Array, + streamType?: string | Array, + defaultStreamType?: string | Array, renderProperties?: Claim => Node, includeSupportAction?: boolean, - hideBlock: boolean, + noCustom?: boolean, }; function ClaimListDiscover(props: Props) { @@ -64,7 +56,6 @@ function ClaimListDiscover(props: Props) { claimSearchByQuery, tags, loading, - personalView, meta, channelIds, showNsfw, @@ -73,70 +64,93 @@ function ClaimListDiscover(props: Props) { location, hiddenUris, hiddenNsfwMessage, - defaultTypeSort, - defaultTimeSort, defaultOrderBy, + orderBy, headerLabel, header, name, claimType, pageSize, + hideBlock, + defaultClaimType, + streamType, + defaultStreamType, + freshness, + defaultFreshness, renderProperties, includeSupportAction, - hideBlock, + noCustom, } = props; const didNavigateForward = history.action === 'PUSH'; - const [page, setPage] = useState(1); const { search } = location; + + const [page, setPage] = useState(1); const [forceRefresh, setForceRefresh] = useState(); + const [expanded, setExpanded] = useState(false); + const urlParams = new URLSearchParams(search); - const typeSort = urlParams.get('type') || defaultTypeSort || TYPE_TRENDING; - const timeSort = urlParams.get('time') || defaultTimeSort || TIME_WEEK; - const tagsInUrl = urlParams.get('t') || ''; + const tagsParam = tags || urlParams.get(CS.TAGS_KEY) || null; + const orderParam = orderBy || urlParams.get(CS.ORDER_BY_KEY) || defaultOrderBy || CS.ORDER_BY_TRENDING; + const freshnessParam = freshness || urlParams.get(CS.FRESH_KEY) || defaultFreshness || CS.FRESH_WEEK; + const contentTypeParam = urlParams.get(CS.CONTENT_KEY); + const claimTypeParam = + claimType || (CS.CLAIM_TYPES.includes(contentTypeParam) && contentTypeParam) || defaultClaimType || null; + const streamTypeParam = + streamType || (CS.FILE_TYPES.includes(contentTypeParam) && contentTypeParam) || defaultStreamType || null; + const durationParam = urlParams.get(CS.DURATION_KEY) || null; + + const isFiltered = () => + Boolean(urlParams.get(CS.FRESH_KEY) || urlParams.get(CS.CONTENT_KEY) || urlParams.get(CS.DURATION_KEY)); + + useEffect(() => { + if (isFiltered()) setExpanded(true); + }, []); + const options: { page_size: number, page: number, no_totals: boolean, any_tags: Array, + not_tags: Array, channel_ids: Array, not_channel_ids: Array, - not_tags: Array, order_by: Array, release_time?: string, claim_type?: Array, name?: string, claim_type?: Array, + duration?: string, + claim_type?: string | Array, + stream_types?: any, } = { - page_size: pageSize || PAGE_SIZE, + page_size: pageSize || CS.PAGE_SIZE, page, name, claim_type: claimType || undefined, // no_totals makes it so the sdk doesn't have to calculate total number pages for pagination // it's faster, but we will need to remove it if we start using total_pages no_totals: true, - any_tags: tags || [], + any_tags: tagsParam || [], channel_ids: channelIds || [], not_channel_ids: // If channelIds were passed in, we don't need not_channel_ids !channelIds && hiddenUris && hiddenUris.length ? hiddenUris.map(hiddenUri => hiddenUri.split('#')[1]) : [], not_tags: !showNsfw ? MATURE_TAGS : [], order_by: - defaultOrderBy || - (typeSort === TYPE_TRENDING - ? ['trending_group', 'trending_mixed'] - : typeSort === TYPE_NEW - ? ['release_time'] - : ['effective_amount']), // Sort by top + orderParam === CS.ORDER_BY_TRENDING + ? CS.ORDER_BY_TRENDING_VALUE + : orderParam === CS.ORDER_BY_NEW + ? CS.ORDER_BY_NEW_VALUE + : CS.ORDER_BY_TOP_VALUE, // Sort by top }; - - if (typeSort === TYPE_TOP && timeSort !== TIME_ALL) { + if (orderParam === CS.ORDER_BY_TOP && freshnessParam !== CS.FRESH_ALL) { options.release_time = `>${Math.floor( moment() - .subtract(1, timeSort) + .subtract(1, freshnessParam) .startOf('hour') .unix() )}`; - } else if (typeSort === TYPE_NEW || typeSort === TYPE_TRENDING) { + } else if (orderParam === CS.ORDER_BY_NEW || orderParam === CS.ORDER_BY_TRENDING) { // Warning - hack below // If users are following more than 10 channels or tags, limit results to stuff less than a year old // For more than 20, drop it down to 6 months @@ -145,14 +159,14 @@ function ClaimListDiscover(props: Props) { if (options.channel_ids.length > 20 || options.any_tags.length > 20) { options.release_time = `>${Math.floor( moment() - .subtract(6, TIME_MONTH) + .subtract(3, CS.FRESH_MONTH) .startOf('week') .unix() )}`; } else if (options.channel_ids.length > 10 || options.any_tags.length > 10) { options.release_time = `>${Math.floor( moment() - .subtract(1, TIME_YEAR) + .subtract(1, CS.FRESH_YEAR) .startOf('week') .unix() )}`; @@ -166,6 +180,26 @@ function ClaimListDiscover(props: Props) { } } + if (durationParam) { + if (durationParam === CS.DURATION_SHORT) { + options.duration = '<=1800'; + } else if (durationParam === CS.DURATION_LONG) { + options.duration = '>=1800'; + } + } + + if (streamTypeParam) { + if (streamTypeParam !== CS.CONTENT_ALL) { + options.stream_types = [streamTypeParam]; + } + } + + if (claimTypeParam) { + if (claimTypeParam !== CS.CONTENT_ALL) { + options.claim_type = [claimTypeParam]; + } + } + if (!showReposts) { options.claim_type = options.claim_type === undefined @@ -179,7 +213,7 @@ function ClaimListDiscover(props: Props) { const shouldPerformSearch = uris.length === 0 || didNavigateForward || - (!loading && uris.length < PAGE_SIZE * page && uris.length % PAGE_SIZE === 0); + (!loading && uris.length < CS.PAGE_SIZE * page && uris.length % CS.PAGE_SIZE === 0); // Don't use the query from createNormalizedClaimSearchKey for the effect since that doesn't include page & release_time const optionsStringForEffect = JSON.stringify(options); @@ -191,13 +225,13 @@ function ClaimListDiscover(props: Props) { again: (