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 LivestreamLink from 'component/livestreamLink';
|
||||||
import { Form, FormField } from 'component/common/form';
|
import { Form, FormField } from 'component/common/form';
|
||||||
import ScheduledStreams from 'component/scheduledStreams';
|
import ScheduledStreams from 'component/scheduledStreams';
|
||||||
|
import { ClaimSearchFilterContext } from 'contexts/claimSearchFilterContext';
|
||||||
import { SearchResults } from './internal/searchResults';
|
import { SearchResults } from './internal/searchResults';
|
||||||
import useFetchLiveStatus from 'effects/use-fetch-live';
|
import useFetchLiveStatus from 'effects/use-fetch-live';
|
||||||
import { useIsLargeScreen } from 'effects/use-screensize';
|
import { useIsLargeScreen } from 'effects/use-screensize';
|
||||||
|
import usePersistedState from 'effects/use-persisted-state';
|
||||||
|
|
||||||
const TYPES_TO_ALLOW_FILTER = ['stream', 'repost'];
|
const TYPES_TO_ALLOW_FILTER = ['stream', 'repost'];
|
||||||
|
|
||||||
|
@ -74,6 +76,15 @@ function ChannelContent(props: Props) {
|
||||||
const {
|
const {
|
||||||
location: { pathname, search },
|
location: { pathname, search },
|
||||||
} = useHistory();
|
} = 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 url = `${pathname}${search}`;
|
||||||
const claimId = claim && claim.claim_id;
|
const claimId = claim && claim.claim_id;
|
||||||
const isChannelEmpty = !claim || !claim.meta;
|
const isChannelEmpty = !claim || !claim.meta;
|
||||||
|
@ -85,6 +96,10 @@ function ChannelContent(props: Props) {
|
||||||
const isLargeScreen = useIsLargeScreen();
|
const isLargeScreen = useIsLargeScreen();
|
||||||
const dynamicPageSize = isLargeScreen ? Math.ceil(defaultPageSize * 3) : defaultPageSize;
|
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) {
|
function handleInputChange(e) {
|
||||||
const { value } = e.target;
|
const { value } = e.target;
|
||||||
setSearchQuery(value);
|
setSearchQuery(value);
|
||||||
|
@ -94,13 +109,8 @@ function ChannelContent(props: Props) {
|
||||||
setSearchQuery('');
|
setSearchQuery('');
|
||||||
}, [url]);
|
}, [url]);
|
||||||
|
|
||||||
const isInitialized = Boolean(activeLivestreamForChannel) || activeLivestreamInitialized;
|
|
||||||
const isChannelBroadcasting = Boolean(activeLivestreamForChannel);
|
|
||||||
|
|
||||||
useFetchLiveStatus(claimId, doFetchChannelLiveStatus, true);
|
useFetchLiveStatus(claimId, doFetchChannelLiveStatus, true);
|
||||||
|
|
||||||
const showScheduledLiveStreams = claimType !== 'collection'; // ie. not on the playlist page.
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<GeoRestrictionInfo uri={uri} />
|
<GeoRestrictionInfo uri={uri} />
|
||||||
|
@ -146,64 +156,66 @@ function ChannelContent(props: Props) {
|
||||||
{!channelIsMine && claimsInChannel > 0 && <HiddenNsfwClaims uri={uri} />}
|
{!channelIsMine && claimsInChannel > 0 && <HiddenNsfwClaims uri={uri} />}
|
||||||
|
|
||||||
{!fetching && (
|
{!fetching && (
|
||||||
<ClaimListDiscover
|
<ClaimSearchFilterContext.Provider value={claimSearchFilterCtx}>
|
||||||
ignoreSearchInLanguage
|
<ClaimListDiscover
|
||||||
hasSource
|
ignoreSearchInLanguage
|
||||||
defaultFreshness={CS.FRESH_ALL}
|
hasSource
|
||||||
showHiddenByUser={viewHiddenChannels}
|
defaultFreshness={CS.FRESH_ALL}
|
||||||
forceShowReposts
|
showHiddenByUser={viewHiddenChannels}
|
||||||
fetchViewCount
|
hideRepostsOverride={hideReposts}
|
||||||
hideFilters={!showFilters}
|
fetchViewCount
|
||||||
hideAdvancedFilter={!showFilters}
|
hideFilters={!showFilters}
|
||||||
tileLayout={tileLayout}
|
hideAdvancedFilter={!showFilters}
|
||||||
uris={isSearching ? [] : null}
|
tileLayout={tileLayout}
|
||||||
streamType={SIMPLE_SITE ? CS.CONTENT_ALL : undefined}
|
uris={isSearching ? [] : null}
|
||||||
channelIds={[claimId]}
|
streamType={SIMPLE_SITE ? CS.CONTENT_ALL : undefined}
|
||||||
claimType={claimType}
|
channelIds={[claimId]}
|
||||||
feeAmount={CS.FEE_AMOUNT_ANY}
|
claimType={claimType}
|
||||||
defaultOrderBy={CS.ORDER_BY_NEW}
|
feeAmount={CS.FEE_AMOUNT_ANY}
|
||||||
pageSize={dynamicPageSize}
|
defaultOrderBy={CS.ORDER_BY_NEW}
|
||||||
infiniteScroll={defaultInfiniteScroll}
|
pageSize={dynamicPageSize}
|
||||||
injectedItem={
|
infiniteScroll={defaultInfiniteScroll}
|
||||||
!hasPremiumPlus && {
|
injectedItem={
|
||||||
node: (index, lastVisibleIndex, pageSize) => {
|
!hasPremiumPlus && {
|
||||||
if (pageSize && index < pageSize) {
|
node: (index, lastVisibleIndex, pageSize) => {
|
||||||
return index === lastVisibleIndex ? <Ads type="video" tileLayout={tileLayout} small /> : null;
|
if (pageSize && index < pageSize) {
|
||||||
} else {
|
return index === lastVisibleIndex ? <Ads type="video" tileLayout={tileLayout} small /> : null;
|
||||||
return index % (pageSize * 2) === 0 ? <Ads type="video" tileLayout={tileLayout} small /> : null;
|
} else {
|
||||||
}
|
return index % (pageSize * 2) === 0 ? <Ads type="video" tileLayout={tileLayout} small /> : null;
|
||||||
},
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
meta={
|
||||||
meta={
|
showFilters && (
|
||||||
showFilters && (
|
<Form onSubmit={() => {}} className="wunderbar--inline">
|
||||||
<Form onSubmit={() => {}} className="wunderbar--inline">
|
<Icon icon={ICONS.SEARCH} />
|
||||||
<Icon icon={ICONS.SEARCH} />
|
<FormField
|
||||||
<FormField
|
name="channel_search"
|
||||||
name="channel_search"
|
className="wunderbar__input--inline"
|
||||||
className="wunderbar__input--inline"
|
value={searchQuery}
|
||||||
value={searchQuery}
|
onChange={handleInputChange}
|
||||||
onChange={handleInputChange}
|
type="text"
|
||||||
type="text"
|
placeholder={__('Search')}
|
||||||
placeholder={__('Search')}
|
/>
|
||||||
/>
|
</Form>
|
||||||
</Form>
|
)
|
||||||
)
|
}
|
||||||
}
|
subSection={
|
||||||
subSection={
|
<SearchResults
|
||||||
<SearchResults
|
searchQuery={searchQuery}
|
||||||
searchQuery={searchQuery}
|
claimId={claimId}
|
||||||
claimId={claimId}
|
showMature={showMature}
|
||||||
showMature={showMature}
|
tileLayout={tileLayout}
|
||||||
tileLayout={tileLayout}
|
onResults={(results) => setIsSearching(results !== null)}
|
||||||
onResults={(results) => setIsSearching(results !== null)}
|
doResolveUris={doResolveUris}
|
||||||
doResolveUris={doResolveUris}
|
/>
|
||||||
/>
|
}
|
||||||
}
|
isChannel
|
||||||
isChannel
|
channelIsMine={channelIsMine}
|
||||||
channelIsMine={channelIsMine}
|
empty={isSearching ? ' ' : empty}
|
||||||
empty={isSearching ? ' ' : empty}
|
/>
|
||||||
/>
|
</ClaimSearchFilterContext.Provider>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|
|
@ -31,7 +31,7 @@ type Props = {
|
||||||
pageSize?: number,
|
pageSize?: number,
|
||||||
|
|
||||||
fetchViewCount?: boolean,
|
fetchViewCount?: boolean,
|
||||||
forceShowReposts?: boolean,
|
hideRepostsOverride?: boolean, // undefined = use SETTINGS.HIDE_REPOSTS; true/false: use this.
|
||||||
hasNoSource?: boolean,
|
hasNoSource?: boolean,
|
||||||
hasSource?: boolean,
|
hasSource?: boolean,
|
||||||
hideAdvancedFilter?: boolean,
|
hideAdvancedFilter?: boolean,
|
||||||
|
@ -165,7 +165,7 @@ function ClaimListDiscover(props: Props) {
|
||||||
hideFilters = false,
|
hideFilters = false,
|
||||||
claimIds,
|
claimIds,
|
||||||
maxPages,
|
maxPages,
|
||||||
forceShowReposts = false,
|
hideRepostsOverride,
|
||||||
languageSetting,
|
languageSetting,
|
||||||
searchLanguages,
|
searchLanguages,
|
||||||
searchInLanguage,
|
searchInLanguage,
|
||||||
|
@ -214,6 +214,7 @@ function ClaimListDiscover(props: Props) {
|
||||||
new Set(mutedUris.concat(blockedUris).map((uri) => splitBySeparator(uri)[1]))
|
new Set(mutedUris.concat(blockedUris).map((uri) => splitBySeparator(uri)[1]))
|
||||||
);
|
);
|
||||||
const [hiddenBuffer, setHiddenBuffer] = React.useState([]);
|
const [hiddenBuffer, setHiddenBuffer] = React.useState([]);
|
||||||
|
const hideRepostsEffective = resolveHideReposts(hideReposts, hideRepostsOverride);
|
||||||
|
|
||||||
const langParam = urlParams.get(CS.LANGUAGE_KEY) || null;
|
const langParam = urlParams.get(CS.LANGUAGE_KEY) || null;
|
||||||
const searchInSelectedLang = searchInLanguage && !ignoreSearchInLanguage;
|
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 (Array.isArray(options.claim_type)) {
|
||||||
if (options.claim_type.length > 1) {
|
if (options.claim_type.length > 1) {
|
||||||
options.claim_type = options.claim_type.filter((claimType) => claimType !== 'repost');
|
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>) {
|
function resolveOrderByOption(orderBy: string | Array<string>, sortBy: string | Array<string>) {
|
||||||
let order_by;
|
let order_by;
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,8 @@ function ClaimListHeader(props: Props) {
|
||||||
urlParams.get(CS.DURATION_KEY) ||
|
urlParams.get(CS.DURATION_KEY) ||
|
||||||
urlParams.get(CS.TAGS_KEY) ||
|
urlParams.get(CS.TAGS_KEY) ||
|
||||||
urlParams.get(CS.FEE_AMOUNT_KEY) ||
|
urlParams.get(CS.FEE_AMOUNT_KEY) ||
|
||||||
urlParams.get(CS.LANGUAGE_KEY)
|
urlParams.get(CS.LANGUAGE_KEY) ||
|
||||||
|
filterCtx?.repost?.hideReposts
|
||||||
);
|
);
|
||||||
|
|
||||||
const languageValue = searchInLanguage
|
const languageValue = searchInLanguage
|
||||||
|
@ -103,6 +104,27 @@ function ClaimListHeader(props: Props) {
|
||||||
? languageParam !== languageSetting && languageParam !== null
|
? languageParam !== languageSetting && languageParam !== null
|
||||||
: languageParam !== CS.LANGUAGES_ALL && 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(() => {
|
React.useEffect(() => {
|
||||||
if (action !== 'POP' && isFiltered()) {
|
if (action !== 'POP' && isFiltered()) {
|
||||||
setExpanded(true);
|
setExpanded(true);
|
||||||
|
@ -507,6 +529,7 @@ function ClaimListHeader(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{getHideRepostsElem(filterCtx, contentTypeParam)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -270,7 +270,7 @@ function DiscoverPage(props: Props) {
|
||||||
}
|
}
|
||||||
meta={getMeta()}
|
meta={getMeta()}
|
||||||
hasSource
|
hasSource
|
||||||
forceShowReposts={dynamicRouteProps}
|
hideRepostsOverride={dynamicRouteProps ? true : undefined}
|
||||||
searchLanguages={dynamicRouteProps?.options?.searchLanguages}
|
searchLanguages={dynamicRouteProps?.options?.searchLanguages}
|
||||||
/>
|
/>
|
||||||
</ClaimSearchFilterContext.Provider>
|
</ClaimSearchFilterContext.Provider>
|
||||||
|
|
Loading…
Reference in a new issue