Add "Hide Repost" button in channel page (#1796)
* Re-organized per 'state->var->func->effect->return' structure. * Add "Hide Repost" button in channel page Ticket: 1762 ## Change For the placement of the button, putting it inside the expanded settings group feels the most natural, plus we then don't need to check whether the channel has reposts or not before displaying it (the expanded area is for stuff like this). ## Notes The tricky part was making the code maintainable w.r.t to the global "Hide Repost" setting. Changed `forceShowReposts` to `hideRepostsOverride`, hopefully makes things more obvious. - undefined = fallback to global setting - true/false = use override
This commit is contained in:
parent
5638f64831
commit
b0e88ff5d1
4 changed files with 111 additions and 67 deletions
|
@ -13,9 +13,11 @@ import Icon from 'component/common/icon';
|
|||
import LivestreamLink from 'component/livestreamLink';
|
||||
import { Form, FormField } from 'component/common/form';
|
||||
import ScheduledStreams from 'component/scheduledStreams';
|
||||
import { ClaimSearchFilterContext } from 'contexts/claimSearchFilterContext';
|
||||
import { SearchResults } from './internal/searchResults';
|
||||
import useFetchLiveStatus from 'effects/use-fetch-live';
|
||||
import { useIsLargeScreen } from 'effects/use-screensize';
|
||||
import usePersistedState from 'effects/use-persisted-state';
|
||||
|
||||
const TYPES_TO_ALLOW_FILTER = ['stream', 'repost'];
|
||||
|
||||
|
@ -74,6 +76,15 @@ function ChannelContent(props: Props) {
|
|||
const {
|
||||
location: { pathname, search },
|
||||
} = useHistory();
|
||||
|
||||
// In Channel Page, ignore SETTINGS.HIDE_REPOSTS and show reposts by default:
|
||||
const [hideReposts, setHideReposts] = usePersistedState('hideRepostsChannelPage');
|
||||
|
||||
const claimSearchFilterCtx = {
|
||||
contentTypes: CS.CONTENT_TYPES,
|
||||
repost: { hideReposts, setHideReposts },
|
||||
};
|
||||
|
||||
const url = `${pathname}${search}`;
|
||||
const claimId = claim && claim.claim_id;
|
||||
const isChannelEmpty = !claim || !claim.meta;
|
||||
|
@ -85,6 +96,10 @@ function ChannelContent(props: Props) {
|
|||
const isLargeScreen = useIsLargeScreen();
|
||||
const dynamicPageSize = isLargeScreen ? Math.ceil(defaultPageSize * 3) : defaultPageSize;
|
||||
|
||||
const isInitialized = Boolean(activeLivestreamForChannel) || activeLivestreamInitialized;
|
||||
const isChannelBroadcasting = Boolean(activeLivestreamForChannel);
|
||||
const showScheduledLiveStreams = claimType !== 'collection'; // ie. not on the playlist page.
|
||||
|
||||
function handleInputChange(e) {
|
||||
const { value } = e.target;
|
||||
setSearchQuery(value);
|
||||
|
@ -94,13 +109,8 @@ function ChannelContent(props: Props) {
|
|||
setSearchQuery('');
|
||||
}, [url]);
|
||||
|
||||
const isInitialized = Boolean(activeLivestreamForChannel) || activeLivestreamInitialized;
|
||||
const isChannelBroadcasting = Boolean(activeLivestreamForChannel);
|
||||
|
||||
useFetchLiveStatus(claimId, doFetchChannelLiveStatus, true);
|
||||
|
||||
const showScheduledLiveStreams = claimType !== 'collection'; // ie. not on the playlist page.
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<GeoRestrictionInfo uri={uri} />
|
||||
|
@ -146,64 +156,66 @@ function ChannelContent(props: Props) {
|
|||
{!channelIsMine && claimsInChannel > 0 && <HiddenNsfwClaims uri={uri} />}
|
||||
|
||||
{!fetching && (
|
||||
<ClaimListDiscover
|
||||
ignoreSearchInLanguage
|
||||
hasSource
|
||||
defaultFreshness={CS.FRESH_ALL}
|
||||
showHiddenByUser={viewHiddenChannels}
|
||||
forceShowReposts
|
||||
fetchViewCount
|
||||
hideFilters={!showFilters}
|
||||
hideAdvancedFilter={!showFilters}
|
||||
tileLayout={tileLayout}
|
||||
uris={isSearching ? [] : null}
|
||||
streamType={SIMPLE_SITE ? CS.CONTENT_ALL : undefined}
|
||||
channelIds={[claimId]}
|
||||
claimType={claimType}
|
||||
feeAmount={CS.FEE_AMOUNT_ANY}
|
||||
defaultOrderBy={CS.ORDER_BY_NEW}
|
||||
pageSize={dynamicPageSize}
|
||||
infiniteScroll={defaultInfiniteScroll}
|
||||
injectedItem={
|
||||
!hasPremiumPlus && {
|
||||
node: (index, lastVisibleIndex, pageSize) => {
|
||||
if (pageSize && index < pageSize) {
|
||||
return index === lastVisibleIndex ? <Ads type="video" tileLayout={tileLayout} small /> : null;
|
||||
} else {
|
||||
return index % (pageSize * 2) === 0 ? <Ads type="video" tileLayout={tileLayout} small /> : null;
|
||||
}
|
||||
},
|
||||
<ClaimSearchFilterContext.Provider value={claimSearchFilterCtx}>
|
||||
<ClaimListDiscover
|
||||
ignoreSearchInLanguage
|
||||
hasSource
|
||||
defaultFreshness={CS.FRESH_ALL}
|
||||
showHiddenByUser={viewHiddenChannels}
|
||||
hideRepostsOverride={hideReposts}
|
||||
fetchViewCount
|
||||
hideFilters={!showFilters}
|
||||
hideAdvancedFilter={!showFilters}
|
||||
tileLayout={tileLayout}
|
||||
uris={isSearching ? [] : null}
|
||||
streamType={SIMPLE_SITE ? CS.CONTENT_ALL : undefined}
|
||||
channelIds={[claimId]}
|
||||
claimType={claimType}
|
||||
feeAmount={CS.FEE_AMOUNT_ANY}
|
||||
defaultOrderBy={CS.ORDER_BY_NEW}
|
||||
pageSize={dynamicPageSize}
|
||||
infiniteScroll={defaultInfiniteScroll}
|
||||
injectedItem={
|
||||
!hasPremiumPlus && {
|
||||
node: (index, lastVisibleIndex, pageSize) => {
|
||||
if (pageSize && index < pageSize) {
|
||||
return index === lastVisibleIndex ? <Ads type="video" tileLayout={tileLayout} small /> : null;
|
||||
} else {
|
||||
return index % (pageSize * 2) === 0 ? <Ads type="video" tileLayout={tileLayout} small /> : null;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
meta={
|
||||
showFilters && (
|
||||
<Form onSubmit={() => {}} className="wunderbar--inline">
|
||||
<Icon icon={ICONS.SEARCH} />
|
||||
<FormField
|
||||
name="channel_search"
|
||||
className="wunderbar__input--inline"
|
||||
value={searchQuery}
|
||||
onChange={handleInputChange}
|
||||
type="text"
|
||||
placeholder={__('Search')}
|
||||
/>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
subSection={
|
||||
<SearchResults
|
||||
searchQuery={searchQuery}
|
||||
claimId={claimId}
|
||||
showMature={showMature}
|
||||
tileLayout={tileLayout}
|
||||
onResults={(results) => setIsSearching(results !== null)}
|
||||
doResolveUris={doResolveUris}
|
||||
/>
|
||||
}
|
||||
isChannel
|
||||
channelIsMine={channelIsMine}
|
||||
empty={isSearching ? ' ' : empty}
|
||||
/>
|
||||
meta={
|
||||
showFilters && (
|
||||
<Form onSubmit={() => {}} className="wunderbar--inline">
|
||||
<Icon icon={ICONS.SEARCH} />
|
||||
<FormField
|
||||
name="channel_search"
|
||||
className="wunderbar__input--inline"
|
||||
value={searchQuery}
|
||||
onChange={handleInputChange}
|
||||
type="text"
|
||||
placeholder={__('Search')}
|
||||
/>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
subSection={
|
||||
<SearchResults
|
||||
searchQuery={searchQuery}
|
||||
claimId={claimId}
|
||||
showMature={showMature}
|
||||
tileLayout={tileLayout}
|
||||
onResults={(results) => setIsSearching(results !== null)}
|
||||
doResolveUris={doResolveUris}
|
||||
/>
|
||||
}
|
||||
isChannel
|
||||
channelIsMine={channelIsMine}
|
||||
empty={isSearching ? ' ' : empty}
|
||||
/>
|
||||
</ClaimSearchFilterContext.Provider>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
|
|
|
@ -31,7 +31,7 @@ type Props = {
|
|||
pageSize?: number,
|
||||
|
||||
fetchViewCount?: boolean,
|
||||
forceShowReposts?: boolean,
|
||||
hideRepostsOverride?: boolean, // undefined = use SETTINGS.HIDE_REPOSTS; true/false: use this.
|
||||
hasNoSource?: boolean,
|
||||
hasSource?: boolean,
|
||||
hideAdvancedFilter?: boolean,
|
||||
|
@ -165,7 +165,7 @@ function ClaimListDiscover(props: Props) {
|
|||
hideFilters = false,
|
||||
claimIds,
|
||||
maxPages,
|
||||
forceShowReposts = false,
|
||||
hideRepostsOverride,
|
||||
languageSetting,
|
||||
searchLanguages,
|
||||
searchInLanguage,
|
||||
|
@ -214,6 +214,7 @@ function ClaimListDiscover(props: Props) {
|
|||
new Set(mutedUris.concat(blockedUris).map((uri) => splitBySeparator(uri)[1]))
|
||||
);
|
||||
const [hiddenBuffer, setHiddenBuffer] = React.useState([]);
|
||||
const hideRepostsEffective = resolveHideReposts(hideReposts, hideRepostsOverride);
|
||||
|
||||
const langParam = urlParams.get(CS.LANGUAGE_KEY) || null;
|
||||
const searchInSelectedLang = searchInLanguage && !ignoreSearchInLanguage;
|
||||
|
@ -438,7 +439,7 @@ function ClaimListDiscover(props: Props) {
|
|||
}
|
||||
}
|
||||
|
||||
if (hideReposts && !options.reposted_claim_id && !forceShowReposts) {
|
||||
if (hideRepostsEffective && !options.reposted_claim_id) {
|
||||
if (Array.isArray(options.claim_type)) {
|
||||
if (options.claim_type.length > 1) {
|
||||
options.claim_type = options.claim_type.filter((claimType) => claimType !== 'repost');
|
||||
|
@ -602,6 +603,14 @@ function ClaimListDiscover(props: Props) {
|
|||
}
|
||||
}
|
||||
|
||||
function resolveHideReposts(hideRepostSetting, hideRepostOverride) {
|
||||
if (hideRepostOverride === undefined || hideRepostOverride === null) {
|
||||
return hideRepostSetting;
|
||||
} else {
|
||||
return hideRepostOverride;
|
||||
}
|
||||
}
|
||||
|
||||
function resolveOrderByOption(orderBy: string | Array<string>, sortBy: string | Array<string>) {
|
||||
let order_by;
|
||||
|
||||
|
|
|
@ -88,7 +88,8 @@ function ClaimListHeader(props: Props) {
|
|||
urlParams.get(CS.DURATION_KEY) ||
|
||||
urlParams.get(CS.TAGS_KEY) ||
|
||||
urlParams.get(CS.FEE_AMOUNT_KEY) ||
|
||||
urlParams.get(CS.LANGUAGE_KEY)
|
||||
urlParams.get(CS.LANGUAGE_KEY) ||
|
||||
filterCtx?.repost?.hideReposts
|
||||
);
|
||||
|
||||
const languageValue = searchInLanguage
|
||||
|
@ -103,6 +104,27 @@ function ClaimListHeader(props: Props) {
|
|||
? languageParam !== languageSetting && languageParam !== null
|
||||
: languageParam !== CS.LANGUAGES_ALL && languageParam !== null;
|
||||
|
||||
function getHideRepostsElem(filterCtx, contentType) {
|
||||
if (filterCtx?.repost) {
|
||||
return (
|
||||
<div className={classnames(`card claim-search__menus`)}>
|
||||
<FormField
|
||||
label={__('Hide reposts')}
|
||||
name="hide_reposts"
|
||||
type="checkbox"
|
||||
checked={filterCtx.repost.hideReposts}
|
||||
disabled={contentType === CS.CLAIM_REPOST}
|
||||
onChange={() => {
|
||||
filterCtx.repost.setHideReposts((prev) => !prev);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
if (action !== 'POP' && isFiltered()) {
|
||||
setExpanded(true);
|
||||
|
@ -507,6 +529,7 @@ function ClaimListHeader(props: Props) {
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
{getHideRepostsElem(filterCtx, contentTypeParam)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -270,7 +270,7 @@ function DiscoverPage(props: Props) {
|
|||
}
|
||||
meta={getMeta()}
|
||||
hasSource
|
||||
forceShowReposts={dynamicRouteProps}
|
||||
hideRepostsOverride={dynamicRouteProps ? true : undefined}
|
||||
searchLanguages={dynamicRouteProps?.options?.searchLanguages}
|
||||
/>
|
||||
</ClaimSearchFilterContext.Provider>
|
||||
|
|
Loading…
Reference in a new issue