display repost counts on file pages, link to all reposts

This commit is contained in:
Jeremy Kauffman 2020-03-19 12:54:37 -04:00 committed by Sean Yesmunt
parent 3cc260e56c
commit 73d2eebb07
6 changed files with 93 additions and 49 deletions

View file

@ -103,25 +103,27 @@ export default function ClaimList(props: Props) {
{header !== false && (
<React.Fragment>
{headerLabel && <label className="claim-list__header-label">{headerLabel}</label>}
<div className={classnames('claim-list__header', { 'section__title--small': type === 'small' })}>
{header}
{loading && <Spinner type="small" />}
<div className="claim-list__alt-controls">
{headerAltControls}
{defaultSort && (
<FormField
className="claim-list__dropdown"
type="select"
name="file_sort"
value={currentSort}
onChange={handleSortChange}
>
<option value={SORT_NEW}>{__('Newest First')}</option>
<option value={SORT_OLD}>{__('Oldest First')}</option>
</FormField>
)}
{header && (
<div className={classnames('claim-list__header', { 'section__title--small': type === 'small' })}>
{header}
{loading && <Spinner type="small" />}
<div className="claim-list__alt-controls">
{headerAltControls}
{defaultSort && (
<FormField
className="claim-list__dropdown"
type="select"
name="file_sort"
value={currentSort}
onChange={handleSortChange}
>
<option value={SORT_NEW}>{__('Newest First')}</option>
<option value={SORT_OLD}>{__('Oldest First')}</option>
</FormField>
)}
</div>
</div>
</div>
)}
</React.Fragment>
)}

View file

@ -23,7 +23,7 @@ type Props = {
doToggleTagFollowDesktop: string => void,
meta?: Node,
showNsfw: boolean,
showReposts: boolean,
// showReposts: boolean,
history: { action: string, push: string => void, replace: string => void },
location: { search: string, pathname: string },
claimSearchByQuery: {
@ -49,6 +49,7 @@ type Props = {
defaultStreamType?: string | Array<string>,
renderProperties?: Claim => Node,
includeSupportAction?: boolean,
repostedClaimId?: string,
pageSize?: number,
followedTags?: Array<Tag>,
};
@ -83,6 +84,7 @@ function ClaimListDiscover(props: Props) {
defaultFreshness = CS.FRESH_WEEK,
renderProperties,
includeSupportAction,
repostedClaimId,
hideFilter,
followedTags,
} = props;
@ -121,7 +123,7 @@ function ClaimListDiscover(props: Props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const options: {
let options: {
page_size: number,
page: number,
no_totals: boolean,
@ -134,6 +136,7 @@ function ClaimListDiscover(props: Props) {
claim_type?: Array<string>,
name?: string,
duration?: string,
reposted_claim_id: string,
stream_types?: any,
} = {
page_size: pageSize || CS.PAGE_SIZE,
@ -155,6 +158,12 @@ function ClaimListDiscover(props: Props) {
? CS.ORDER_BY_NEW_VALUE
: CS.ORDER_BY_TOP_VALUE, // Sort by top
};
if (repostedClaimId) {
// SDK chokes on reposted_claim_id of null or false, needs to not be present if no value
options.reposted_claim_id = repostedClaimId;
}
if (orderParam === CS.ORDER_BY_TOP && freshnessParam !== CS.FRESH_ALL) {
options.release_time = `>${Math.floor(
moment()
@ -364,7 +373,7 @@ function ClaimListDiscover(props: Props) {
}
}, [doClaimSearch, shouldPerformSearch, optionsStringForEffect, forceRefresh]);
const defaultHeader = (
const defaultHeader = repostedClaimId ? null : (
<Fragment>
<div className={'claim-search__wrapper'}>
<div className={'claim-search__top'}>

View file

@ -1,10 +1,12 @@
// @flow
import * as MODALS from 'constants/modal_types';
import * as ICONS from 'constants/icons';
import React from 'react';
import React, { Fragment } from 'react';
import Button from 'component/button';
import FileDownloadLink from 'component/fileDownloadLink';
import { buildURI } from 'lbry-redux';
import * as PAGES from '../../constants/pages';
import * as CS from '../../constants/claim_search';
type Props = {
uri: string,
@ -42,6 +44,20 @@ function FileActions(props: Props) {
editUri = buildURI(uriObject);
}
let repostLabel = <span>{__('Repost')}</span>;
if (claim.meta.reposted > 0) {
repostLabel = (
<Fragment>
{repostLabel}{' '}
<Button
button="alt"
label={__('(%count%)', { count: claim.meta.reposted })}
navigate={`/$/${PAGES.DISCOVER}?${CS.REPOSTED_URI_KEY}=${encodeURIComponent(uri)}`}
/>
</Fragment>
);
}
return (
<div className="media__actions">
<div className="section__actions">
@ -54,7 +70,7 @@ function FileActions(props: Props) {
<Button
button="alt"
icon={ICONS.REPOST}
label={__('Repost')}
label={repostLabel}
requiresAuth={IS_WEB}
onClick={() => openModal(MODALS.REPOST, { uri })}
/>

View file

@ -5,6 +5,7 @@ export const ORDER_BY_KEY = 'order';
export const DURATION_KEY = 'duration';
export const TAGS_KEY = 't';
export const CONTENT_KEY = 'content';
export const REPOSTED_URI_KEY = 'reposted_uri';
export const TAGS_ALL = 'tags_any';
export const TAGS_FOLLOWED = 'tags_followed';

View file

@ -1,15 +1,20 @@
import { connect } from 'react-redux';
import { selectFollowedTags } from 'lbry-redux';
import { makeSelectClaimForUri, selectFollowedTags } from 'lbry-redux';
import { doToggleTagFollowDesktop } from 'redux/actions/tags';
import * as CS from 'constants/claim_search';
import Tags from './view';
const select = state => ({
followedTags: selectFollowedTags(state),
});
const select = (state, props) => {
const urlParams = new URLSearchParams(props.location.search);
const repostedUri = decodeURIComponent(urlParams.get(CS.REPOSTED_URI_KEY));
export default connect(
select,
{
doToggleTagFollowDesktop,
}
)(Tags);
return {
followedTags: selectFollowedTags(state),
repostedUri: repostedUri,
repostedClaim: repostedUri ? makeSelectClaimForUri(repostedUri)(state) : null,
};
};
export default connect(select, {
doToggleTagFollowDesktop,
})(Tags);

View file

@ -13,6 +13,8 @@ import * as CS from 'constants/claim_search';
type Props = {
location: { search: string },
followedTags: Array<Tag>,
repostedUri: string,
repostedClaim: ?GenericClaim,
doToggleTagFollowDesktop: string => void,
};
@ -20,6 +22,8 @@ function TagsPage(props: Props) {
const {
location: { search },
followedTags,
repostedClaim,
repostedUri,
doToggleTagFollowDesktop,
} = props;
const buttonRef = useRef();
@ -29,6 +33,7 @@ function TagsPage(props: Props) {
const claimType = urlParams.get('claim_type');
const tagsQuery = urlParams.get('t') || null;
const tags = tagsQuery ? tagsQuery.split(',') : null;
// Eventually allow more than one tag on this page
// Restricting to one to make follow/unfollow simpler
const tag = (tags && tags[0]) || null;
@ -48,27 +53,33 @@ function TagsPage(props: Props) {
}
}
let headerLabel;
if (repostedClaim) {
headerLabel = __('Reposts of %uri%', { uri: repostedUri });
} else if (tag) {
headerLabel = (
<span>
<Icon icon={ICONS.TAG} size={10} />
{tag}
</span>
);
} else {
headerLabel = (
<span>
<Icon icon={ICONS.DISCOVER} size={10} />
{__('All Content')}
</span>
);
}
return (
<Page>
<ClaimListDiscover
claimType={claimType ? [claimType] : undefined}
headerLabel={
tag ? (
<span>
<Icon icon={ICONS.TAG} size={10} />
{(tag === CS.TAGS_ALL && __('All Content')) ||
(tag === CS.TAGS_FOLLOWED && __('Followed Tags')) ||
__(tag)}
</span>
) : (
<span>
<Icon icon={ICONS.DISCOVER} size={10} />
{__('All Content')}
</span>
)
}
defaultTags={CS.TAGS_ALL}
headerLabel={headerLabel}
tags={tags}
hiddenNsfwMessage={<HiddenNsfw type="page" />}
repostedClaimId={repostedClaim ? repostedClaim.claim_id : null}
meta={
tag && (
<Button