Livestream category improvements #7115
6 changed files with 66 additions and 10 deletions
|
@ -1,13 +1,18 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { SETTINGS } from 'lbry-redux';
|
import { SETTINGS } from 'lbry-redux';
|
||||||
|
import { doFetchActiveLivestreams } from 'redux/actions/livestream';
|
||||||
|
import { selectActiveLivestreams } from 'redux/selectors/livestream';
|
||||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
|
|
||||||
import ChannelsFollowingPage from './view';
|
import ChannelsFollowingPage from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = (state) => ({
|
||||||
subscribedChannels: selectSubscriptions(state),
|
subscribedChannels: selectSubscriptions(state),
|
||||||
tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state),
|
tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state),
|
||||||
|
activeLivestreams: selectActiveLivestreams(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select)(ChannelsFollowingPage);
|
export default connect(select, {
|
||||||
|
doFetchActiveLivestreams,
|
||||||
|
})(ChannelsFollowingPage);
|
||||||
|
|
|
@ -10,21 +10,31 @@ import Page from 'component/page';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import { splitBySeparator } from 'lbry-redux';
|
import { splitBySeparator } from 'lbry-redux';
|
||||||
|
import { getLivestreamUris } from 'util/livestream';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
subscribedChannels: Array<Subscription>,
|
subscribedChannels: Array<Subscription>,
|
||||||
tileLayout: boolean,
|
tileLayout: boolean,
|
||||||
|
activeLivestreams: ?LivestreamInfo,
|
||||||
|
doFetchActiveLivestreams: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
function ChannelsFollowingPage(props: Props) {
|
function ChannelsFollowingPage(props: Props) {
|
||||||
const { subscribedChannels, tileLayout } = props;
|
const { subscribedChannels, tileLayout, activeLivestreams, doFetchActiveLivestreams } = props;
|
||||||
|
|
||||||
const hasSubsribedChannels = subscribedChannels.length > 0;
|
const hasSubsribedChannels = subscribedChannels.length > 0;
|
||||||
|
const channelIds = subscribedChannels.map((sub) => splitBySeparator(sub.uri)[1]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
doFetchActiveLivestreams();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return !hasSubsribedChannels ? (
|
return !hasSubsribedChannels ? (
|
||||||
<ChannelsFollowingDiscoverPage />
|
<ChannelsFollowingDiscoverPage />
|
||||||
) : (
|
) : (
|
||||||
<Page noFooter fullWidthPage={tileLayout}>
|
<Page noFooter fullWidthPage={tileLayout}>
|
||||||
<ClaimListDiscover
|
<ClaimListDiscover
|
||||||
|
prefixUris={getLivestreamUris(activeLivestreams, channelIds)}
|
||||||
hideAdvancedFilter={SIMPLE_SITE}
|
hideAdvancedFilter={SIMPLE_SITE}
|
||||||
streamType={SIMPLE_SITE ? CS.CONTENT_ALL : undefined}
|
streamType={SIMPLE_SITE ? CS.CONTENT_ALL : undefined}
|
||||||
tileLayout={tileLayout}
|
tileLayout={tileLayout}
|
||||||
|
@ -35,7 +45,7 @@ function ChannelsFollowingPage(props: Props) {
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
defaultOrderBy={CS.ORDER_BY_NEW}
|
defaultOrderBy={CS.ORDER_BY_NEW}
|
||||||
channelIds={subscribedChannels.map((sub) => splitBySeparator(sub.uri)[1])}
|
channelIds={channelIds}
|
||||||
meta={
|
meta={
|
||||||
<Button
|
<Button
|
||||||
icon={ICONS.SEARCH}
|
icon={ICONS.SEARCH}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import * as CS from 'constants/claim_search';
|
import * as CS from 'constants/claim_search';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { makeSelectClaimForUri, doResolveUri, SETTINGS } from 'lbry-redux';
|
import { makeSelectClaimForUri, doResolveUri, SETTINGS } from 'lbry-redux';
|
||||||
|
import { doFetchActiveLivestreams } from 'redux/actions/livestream';
|
||||||
|
import { selectActiveLivestreams } from 'redux/selectors/livestream';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
import { selectFollowedTags } from 'redux/selectors/tags';
|
import { selectFollowedTags } from 'redux/selectors/tags';
|
||||||
import { doToggleTagFollowDesktop } from 'redux/actions/tags';
|
import { doToggleTagFollowDesktop } from 'redux/actions/tags';
|
||||||
|
@ -18,10 +20,12 @@ const select = (state, props) => {
|
||||||
repostedClaim: repostedUri ? makeSelectClaimForUri(repostedUri)(state) : null,
|
repostedClaim: repostedUri ? makeSelectClaimForUri(repostedUri)(state) : null,
|
||||||
isAuthenticated: selectUserVerifiedEmail(state),
|
isAuthenticated: selectUserVerifiedEmail(state),
|
||||||
tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state),
|
tileLayout: makeSelectClientSetting(SETTINGS.TILE_LAYOUT)(state),
|
||||||
|
activeLivestreams: selectActiveLivestreams(state),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(select, {
|
export default connect(select, {
|
||||||
doToggleTagFollowDesktop,
|
doToggleTagFollowDesktop,
|
||||||
doResolveUri,
|
doResolveUri,
|
||||||
|
doFetchActiveLivestreams,
|
||||||
})(Tags);
|
})(Tags);
|
||||||
|
|
|
@ -16,6 +16,7 @@ import Ads from 'web/component/ads';
|
||||||
import LbcSymbol from 'component/common/lbc-symbol';
|
import LbcSymbol from 'component/common/lbc-symbol';
|
||||||
import I18nMessage from 'component/i18nMessage';
|
import I18nMessage from 'component/i18nMessage';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import { getLivestreamUris } from 'util/livestream';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
location: { search: string },
|
location: { search: string },
|
||||||
|
@ -27,6 +28,8 @@ type Props = {
|
||||||
isAuthenticated: boolean,
|
isAuthenticated: boolean,
|
||||||
dynamicRouteProps: RowDataItem,
|
dynamicRouteProps: RowDataItem,
|
||||||
tileLayout: boolean,
|
tileLayout: boolean,
|
||||||
|
activeLivestreams: ?LivestreamInfo,
|
||||||
|
doFetchActiveLivestreams: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
function DiscoverPage(props: Props) {
|
function DiscoverPage(props: Props) {
|
||||||
|
@ -39,6 +42,8 @@ function DiscoverPage(props: Props) {
|
||||||
doResolveUri,
|
doResolveUri,
|
||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
tileLayout,
|
tileLayout,
|
||||||
|
activeLivestreams,
|
||||||
|
doFetchActiveLivestreams,
|
||||||
dynamicRouteProps,
|
dynamicRouteProps,
|
||||||
} = props;
|
} = props;
|
||||||
const buttonRef = useRef();
|
const buttonRef = useRef();
|
||||||
|
@ -56,6 +61,8 @@ function DiscoverPage(props: Props) {
|
||||||
// Eventually allow more than one tag on this page
|
// Eventually allow more than one tag on this page
|
||||||
// Restricting to one to make follow/unfollow simpler
|
// Restricting to one to make follow/unfollow simpler
|
||||||
const tag = (tags && tags[0]) || null;
|
const tag = (tags && tags[0]) || null;
|
||||||
|
const channelIds =
|
||||||
|
(dynamicRouteProps && dynamicRouteProps.options && dynamicRouteProps.options.channelIds) || undefined;
|
||||||
|
|
||||||
const isFollowing = followedTags.map(({ name }) => name).includes(tag);
|
const isFollowing = followedTags.map(({ name }) => name).includes(tag);
|
||||||
let label = isFollowing ? __('Following --[button label indicating a channel has been followed]--') : __('Follow');
|
let label = isFollowing ? __('Following --[button label indicating a channel has been followed]--') : __('Follow');
|
||||||
|
@ -104,9 +111,14 @@ function DiscoverPage(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
doFetchActiveLivestreams();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page noFooter fullWidthPage={tileLayout}>
|
<Page noFooter fullWidthPage={tileLayout}>
|
||||||
<ClaimListDiscover
|
<ClaimListDiscover
|
||||||
|
prefixUris={getLivestreamUris(activeLivestreams, channelIds)}
|
||||||
hideAdvancedFilter={SIMPLE_SITE}
|
hideAdvancedFilter={SIMPLE_SITE}
|
||||||
hideFilters={SIMPLE_SITE ? !dynamicRouteProps : undefined}
|
hideFilters={SIMPLE_SITE ? !dynamicRouteProps : undefined}
|
||||||
header={repostedUri ? <span /> : undefined}
|
header={repostedUri ? <span /> : undefined}
|
||||||
|
@ -131,9 +143,7 @@ function DiscoverPage(props: Props) {
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
feeAmount={SIMPLE_SITE ? !dynamicRouteProps && CS.FEE_AMOUNT_ANY : undefined}
|
feeAmount={SIMPLE_SITE ? !dynamicRouteProps && CS.FEE_AMOUNT_ANY : undefined}
|
||||||
channelIds={
|
channelIds={channelIds}
|
||||||
(dynamicRouteProps && dynamicRouteProps.options && dynamicRouteProps.options.channelIds) || undefined
|
|
||||||
}
|
|
||||||
limitClaimsPerChannel={
|
limitClaimsPerChannel={
|
||||||
SIMPLE_SITE
|
SIMPLE_SITE
|
||||||
? (dynamicRouteProps && dynamicRouteProps.options && dynamicRouteProps.options.limitClaimsPerChannel) ||
|
? (dynamicRouteProps && dynamicRouteProps.options && dynamicRouteProps.options.limitClaimsPerChannel) ||
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { doFetchActiveLivestreams } from 'redux/actions/livestream';
|
||||||
|
import { selectActiveLivestreams } from 'redux/selectors/livestream';
|
||||||
import { selectFollowedTags } from 'redux/selectors/tags';
|
import { selectFollowedTags } from 'redux/selectors/tags';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||||
|
@ -12,8 +14,11 @@ const select = (state) => ({
|
||||||
authenticated: selectUserVerifiedEmail(state),
|
authenticated: selectUserVerifiedEmail(state),
|
||||||
showNsfw: selectShowMatureContent(state),
|
showNsfw: selectShowMatureContent(state),
|
||||||
homepageData: selectHomepageData(state),
|
homepageData: selectHomepageData(state),
|
||||||
|
activeLivestreams: selectActiveLivestreams(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = {};
|
const perform = (dispatch) => ({
|
||||||
|
doFetchActiveLivestreams: () => dispatch(doFetchActiveLivestreams()),
|
||||||
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(DiscoverPage);
|
export default connect(select, perform)(DiscoverPage);
|
||||||
|
|
|
@ -10,6 +10,7 @@ import ClaimPreviewTile from 'component/claimPreviewTile';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import WaitUntilOnPage from 'component/common/wait-until-on-page';
|
import WaitUntilOnPage from 'component/common/wait-until-on-page';
|
||||||
import { GetLinksData } from 'util/buildHomepage';
|
import { GetLinksData } from 'util/buildHomepage';
|
||||||
|
import { getLivestreamUris } from 'util/livestream';
|
||||||
|
|
||||||
// @if TARGET='web'
|
// @if TARGET='web'
|
||||||
import Pixel from 'web/component/pixel';
|
import Pixel from 'web/component/pixel';
|
||||||
|
@ -22,10 +23,20 @@ type Props = {
|
||||||
subscribedChannels: Array<Subscription>,
|
subscribedChannels: Array<Subscription>,
|
||||||
showNsfw: boolean,
|
showNsfw: boolean,
|
||||||
homepageData: any,
|
homepageData: any,
|
||||||
|
activeLivestreams: any,
|
||||||
|
doFetchActiveLivestreams: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
function HomePage(props: Props) {
|
function HomePage(props: Props) {
|
||||||
const { followedTags, subscribedChannels, authenticated, showNsfw, homepageData } = props;
|
const {
|
||||||
|
followedTags,
|
||||||
|
subscribedChannels,
|
||||||
|
authenticated,
|
||||||
|
showNsfw,
|
||||||
|
homepageData,
|
||||||
|
activeLivestreams,
|
||||||
|
doFetchActiveLivestreams,
|
||||||
|
} = props;
|
||||||
const showPersonalizedChannels = (authenticated || !IS_WEB) && subscribedChannels && subscribedChannels.length > 0;
|
const showPersonalizedChannels = (authenticated || !IS_WEB) && subscribedChannels && subscribedChannels.length > 0;
|
||||||
const showPersonalizedTags = (authenticated || !IS_WEB) && followedTags && followedTags.length > 0;
|
const showPersonalizedTags = (authenticated || !IS_WEB) && followedTags && followedTags.length > 0;
|
||||||
const showIndividualTags = showPersonalizedTags && followedTags.length < 5;
|
const showIndividualTags = showPersonalizedTags && followedTags.length < 5;
|
||||||
|
@ -50,8 +61,15 @@ function HomePage(props: Props) {
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
|
|
||||||
const claimTiles = (
|
const claimTiles = (
|
||||||
<ClaimTilesDiscover {...options} showNoSourceClaims={ENABLE_NO_SOURCE_CLAIMS} hasSource pinUrls={pinUrls} />
|
<ClaimTilesDiscover
|
||||||
|
{...options}
|
||||||
|
showNoSourceClaims={ENABLE_NO_SOURCE_CLAIMS}
|
||||||
|
hasSource
|
||||||
|
prefixUris={getLivestreamUris(activeLivestreams, options.channelIds)}
|
||||||
|
pinUrls={pinUrls}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -86,6 +104,10 @@ function HomePage(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
doFetchActiveLivestreams();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page fullWidthPage>
|
<Page fullWidthPage>
|
||||||
{!SIMPLE_SITE && (authenticated || !IS_WEB) && !subscribedChannels.length && (
|
{!SIMPLE_SITE && (authenticated || !IS_WEB) && !subscribedChannels.length && (
|
||||||
|
|
Loading…
Reference in a new issue