Add a setting to hide scheduled livestreams from home/following (#626)
* Add a setting to hide scheduled livestreams from home/following * Add a hide button in the scheduled stream header. * Fix typo + make sure pref is synced
This commit is contained in:
parent
4624188a85
commit
bbe68a3319
12 changed files with 69 additions and 11 deletions
|
@ -1,4 +1,11 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import ScheduledStreams from './view';
|
import ScheduledStreams from './view';
|
||||||
|
import { doSetClientSetting } from 'redux/actions/settings';
|
||||||
|
import { doToast } from 'redux/actions/notifications';
|
||||||
|
|
||||||
export default connect()(ScheduledStreams);
|
const perform = (dispatch) => ({
|
||||||
|
setClientSetting: (key, value, pushPrefs) => dispatch(doSetClientSetting(key, value, pushPrefs)),
|
||||||
|
doShowSnackBar: (message) => dispatch(doToast({ isError: false, message })),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(null, perform)(ScheduledStreams);
|
||||||
|
|
|
@ -9,16 +9,20 @@ import ClaimListDiscover from 'component/claimListDiscover';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { LIVESTREAM_UPCOMING_BUFFER } from 'constants/livestream';
|
import { LIVESTREAM_UPCOMING_BUFFER } from 'constants/livestream';
|
||||||
// import { SCHEDULED_LIVESTREAM_TAG } from 'constants/tags';
|
// import { SCHEDULED_LIVESTREAM_TAG } from 'constants/tags';
|
||||||
|
import * as SETTINGS from 'constants/settings';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
channelIds: Array<string>,
|
channelIds: Array<string>,
|
||||||
tileLayout: boolean,
|
tileLayout: boolean,
|
||||||
liveUris: Array<string>,
|
liveUris: Array<string>,
|
||||||
limitClaimsPerChannel?: number,
|
limitClaimsPerChannel?: number,
|
||||||
|
// --- perform ---
|
||||||
|
setClientSetting: (string, boolean | string | number, boolean) => void,
|
||||||
|
doShowSnackBar: (string) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ScheduledStreams = (props: Props) => {
|
const ScheduledStreams = (props: Props) => {
|
||||||
const { channelIds, tileLayout, liveUris = [], limitClaimsPerChannel } = props;
|
const { channelIds, tileLayout, liveUris = [], limitClaimsPerChannel, setClientSetting, doShowSnackBar } = props;
|
||||||
const isMediumScreen = useIsMediumScreen();
|
const isMediumScreen = useIsMediumScreen();
|
||||||
const isLargeScreen = useIsLargeScreen();
|
const isLargeScreen = useIsLargeScreen();
|
||||||
|
|
||||||
|
@ -38,6 +42,20 @@ const ScheduledStreams = (props: Props) => {
|
||||||
setTotalUpcomingLivestreams(total);
|
setTotalUpcomingLivestreams(total);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const hideScheduledStreams = () => {
|
||||||
|
setClientSetting(SETTINGS.HIDE_SCHEDULED_LIVESTREAMS, true, true);
|
||||||
|
doShowSnackBar(__('Scheduled streams hidden, you can re-enable them in settings.'));
|
||||||
|
};
|
||||||
|
|
||||||
|
const Header = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{__('Upcoming Livestreams')}
|
||||||
|
<Button button="link" label={__('Hide')} onClick={hideScheduledStreams} className={'ml-s text-s'} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'mb-xl'} style={{ display: showUpcomingLivestreams ? 'block' : 'none' }}>
|
<div className={'mb-xl'} style={{ display: showUpcomingLivestreams ? 'block' : 'none' }}>
|
||||||
<ClaimListDiscover
|
<ClaimListDiscover
|
||||||
|
@ -55,7 +73,7 @@ const ScheduledStreams = (props: Props) => {
|
||||||
infiniteScroll={false}
|
infiniteScroll={false}
|
||||||
showNoSourceClaims
|
showNoSourceClaims
|
||||||
hideLayoutButton
|
hideLayoutButton
|
||||||
header={__('Upcoming Livestreams')}
|
header={<Header />}
|
||||||
maxClaimRender={upcomingMax}
|
maxClaimRender={upcomingMax}
|
||||||
excludeUris={liveUris}
|
excludeUris={liveUris}
|
||||||
loadedCallback={loadedCallback}
|
loadedCallback={loadedCallback}
|
||||||
|
|
|
@ -15,6 +15,7 @@ const select = (state) => ({
|
||||||
autoplayMedia: selectClientSetting(state, SETTINGS.AUTOPLAY_MEDIA),
|
autoplayMedia: selectClientSetting(state, SETTINGS.AUTOPLAY_MEDIA),
|
||||||
autoplayNext: selectClientSetting(state, SETTINGS.AUTOPLAY_NEXT),
|
autoplayNext: selectClientSetting(state, SETTINGS.AUTOPLAY_NEXT),
|
||||||
hideReposts: selectClientSetting(state, SETTINGS.HIDE_REPOSTS),
|
hideReposts: selectClientSetting(state, SETTINGS.HIDE_REPOSTS),
|
||||||
|
hideScheduledLivestreams: selectClientSetting(state, SETTINGS.HIDE_SCHEDULED_LIVESTREAMS),
|
||||||
showNsfw: selectShowMatureContent(state),
|
showNsfw: selectShowMatureContent(state),
|
||||||
myChannelUrls: selectMyChannelUrls(state),
|
myChannelUrls: selectMyChannelUrls(state),
|
||||||
instantPurchaseEnabled: selectClientSetting(state, SETTINGS.INSTANT_PURCHASE_ENABLED),
|
instantPurchaseEnabled: selectClientSetting(state, SETTINGS.INSTANT_PURCHASE_ENABLED),
|
||||||
|
|
|
@ -26,6 +26,7 @@ type Props = {
|
||||||
autoplayNext: boolean,
|
autoplayNext: boolean,
|
||||||
hideReposts: ?boolean,
|
hideReposts: ?boolean,
|
||||||
showNsfw: boolean,
|
showNsfw: boolean,
|
||||||
|
hideScheduledLivestreams: boolean,
|
||||||
myChannelUrls: ?Array<string>,
|
myChannelUrls: ?Array<string>,
|
||||||
instantPurchaseEnabled: boolean,
|
instantPurchaseEnabled: boolean,
|
||||||
instantPurchaseMax: Price,
|
instantPurchaseMax: Price,
|
||||||
|
@ -44,6 +45,7 @@ export default function SettingContent(props: Props) {
|
||||||
autoplayNext,
|
autoplayNext,
|
||||||
hideReposts,
|
hideReposts,
|
||||||
showNsfw,
|
showNsfw,
|
||||||
|
hideScheduledLivestreams,
|
||||||
myChannelUrls,
|
myChannelUrls,
|
||||||
instantPurchaseEnabled,
|
instantPurchaseEnabled,
|
||||||
instantPurchaseMax,
|
instantPurchaseMax,
|
||||||
|
@ -108,6 +110,15 @@ export default function SettingContent(props: Props) {
|
||||||
/>
|
/>
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
|
|
||||||
|
<SettingsRow title={__('Hide Scheduled Livestreams')} subtitle={__(HELP.HIDE_SCHEDULED_LIVESTREAMS)}>
|
||||||
|
<FormField
|
||||||
|
type="checkbox"
|
||||||
|
name="hide_scheduled_livestreams"
|
||||||
|
onChange={() => setClientSetting(SETTINGS.HIDE_SCHEDULED_LIVESTREAMS, !hideScheduledLivestreams)}
|
||||||
|
checked={hideScheduledLivestreams}
|
||||||
|
/>
|
||||||
|
</SettingsRow>
|
||||||
|
|
||||||
{!SIMPLE_SITE && (
|
{!SIMPLE_SITE && (
|
||||||
<>
|
<>
|
||||||
{/*
|
{/*
|
||||||
|
@ -223,6 +234,7 @@ const HELP = {
|
||||||
AUTOPLAY_MEDIA: 'Autoplay video and audio files when navigating to a file.',
|
AUTOPLAY_MEDIA: 'Autoplay video and audio files when navigating to a file.',
|
||||||
AUTOPLAY_NEXT: 'Autoplay the next related item when a file (video or audio) finishes playing.',
|
AUTOPLAY_NEXT: 'Autoplay the next related item when a file (video or audio) finishes playing.',
|
||||||
HIDE_REPOSTS: 'You will not see reposts by people you follow or receive email notifying about them.',
|
HIDE_REPOSTS: 'You will not see reposts by people you follow or receive email notifying about them.',
|
||||||
|
HIDE_SCHEDULED_LIVESTREAMS: 'You will not see scheduled livestreams by people you follow on the home or following page.',
|
||||||
SHOW_MATURE: 'Mature content may include nudity, intense sexuality, profanity, or other adult content. By displaying mature content, you are affirming you are of legal age to view mature content in your country or jurisdiction. ',
|
SHOW_MATURE: 'Mature content may include nudity, intense sexuality, profanity, or other adult content. By displaying mature content, you are affirming you are of legal age to view mature content in your country or jurisdiction. ',
|
||||||
MAX_PURCHASE_PRICE: 'This will prevent you from purchasing any content over a certain cost, as a safety measure.',
|
MAX_PURCHASE_PRICE: 'This will prevent you from purchasing any content over a certain cost, as a safety measure.',
|
||||||
ONLY_CONFIRM_OVER_AMOUNT: '', // [feel redundant. Disable for now] "When this option is chosen, LBRY won't ask you to confirm purchases or tips below your chosen amount.",
|
ONLY_CONFIRM_OVER_AMOUNT: '', // [feel redundant. Disable for now] "When this option is chosen, LBRY won't ask you to confirm purchases or tips below your chosen amount.",
|
||||||
|
|
|
@ -35,6 +35,7 @@ export const REWARDS_ACKNOWLEDGED = 'rewards_acknowledged';
|
||||||
export const SEARCH_IN_LANGUAGE = 'search_in_language';
|
export const SEARCH_IN_LANGUAGE = 'search_in_language';
|
||||||
export const HOMEPAGE = 'homepage';
|
export const HOMEPAGE = 'homepage';
|
||||||
export const HIDE_REPOSTS = 'hide_reposts';
|
export const HIDE_REPOSTS = 'hide_reposts';
|
||||||
|
export const HIDE_SCHEDULED_LIVESTREAMS = 'hide_scheduled_livestreams';
|
||||||
export const SUPPORT_OPTION = 'support_option';
|
export const SUPPORT_OPTION = 'support_option';
|
||||||
export const TILE_LAYOUT = 'tile_layout';
|
export const TILE_LAYOUT = 'tile_layout';
|
||||||
export const VIDEO_THEATER_MODE = 'video_theater_mode';
|
export const VIDEO_THEATER_MODE = 'video_theater_mode';
|
||||||
|
|
|
@ -17,6 +17,7 @@ export const SDK_SYNC_KEYS = [DAEMON_SETTINGS.LBRYUM_SERVERS, DAEMON_SETTINGS.SH
|
||||||
export const CLIENT_SYNC_KEYS = [
|
export const CLIENT_SYNC_KEYS = [
|
||||||
SETTINGS.SHOW_MATURE,
|
SETTINGS.SHOW_MATURE,
|
||||||
SETTINGS.HIDE_REPOSTS,
|
SETTINGS.HIDE_REPOSTS,
|
||||||
|
SETTINGS.HIDE_SCHEDULED_LIVESTREAMS,
|
||||||
SETTINGS.SHOW_ANONYMOUS,
|
SETTINGS.SHOW_ANONYMOUS,
|
||||||
SETTINGS.INSTANT_PURCHASE_ENABLED,
|
SETTINGS.INSTANT_PURCHASE_ENABLED,
|
||||||
SETTINGS.INSTANT_PURCHASE_MAX,
|
SETTINGS.INSTANT_PURCHASE_MAX,
|
||||||
|
|
|
@ -12,6 +12,7 @@ const select = (state) => ({
|
||||||
tileLayout: selectClientSetting(state, SETTINGS.TILE_LAYOUT),
|
tileLayout: selectClientSetting(state, SETTINGS.TILE_LAYOUT),
|
||||||
activeLivestreams: selectActiveLivestreams(state),
|
activeLivestreams: selectActiveLivestreams(state),
|
||||||
fetchingActiveLivestreams: selectFetchingActiveLivestreams(state),
|
fetchingActiveLivestreams: selectFetchingActiveLivestreams(state),
|
||||||
|
hideScheduledLivestreams: selectClientSetting(state, SETTINGS.HIDE_SCHEDULED_LIVESTREAMS),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, {
|
export default connect(select, {
|
||||||
|
|
|
@ -19,6 +19,7 @@ type Props = {
|
||||||
activeLivestreams: ?LivestreamInfo,
|
activeLivestreams: ?LivestreamInfo,
|
||||||
doFetchActiveLivestreams: () => void,
|
doFetchActiveLivestreams: () => void,
|
||||||
fetchingActiveLivestreams: boolean,
|
fetchingActiveLivestreams: boolean,
|
||||||
|
hideScheduledLivestreams: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
function ChannelsFollowingPage(props: Props) {
|
function ChannelsFollowingPage(props: Props) {
|
||||||
|
@ -28,6 +29,7 @@ function ChannelsFollowingPage(props: Props) {
|
||||||
activeLivestreams,
|
activeLivestreams,
|
||||||
doFetchActiveLivestreams,
|
doFetchActiveLivestreams,
|
||||||
fetchingActiveLivestreams,
|
fetchingActiveLivestreams,
|
||||||
|
hideScheduledLivestreams,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const hasSubscribedChannels = subscribedChannels.length > 0;
|
const hasSubscribedChannels = subscribedChannels.length > 0;
|
||||||
|
@ -43,12 +45,14 @@ function ChannelsFollowingPage(props: Props) {
|
||||||
<Page noFooter fullWidthPage={tileLayout}>
|
<Page noFooter fullWidthPage={tileLayout}>
|
||||||
{!fetchingActiveLivestreams && (
|
{!fetchingActiveLivestreams && (
|
||||||
<>
|
<>
|
||||||
<ScheduledStreams
|
{!hideScheduledLivestreams && (
|
||||||
channelIds={channelIds}
|
<ScheduledStreams
|
||||||
tileLayout={tileLayout}
|
channelIds={channelIds}
|
||||||
liveUris={getLivestreamUris(activeLivestreams, channelIds)}
|
tileLayout={tileLayout}
|
||||||
limitClaimsPerChannel={2}
|
liveUris={getLivestreamUris(activeLivestreams, channelIds)}
|
||||||
/>
|
limitClaimsPerChannel={2}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<ClaimListDiscover
|
<ClaimListDiscover
|
||||||
prefixUris={getLivestreamUris(activeLivestreams, channelIds)}
|
prefixUris={getLivestreamUris(activeLivestreams, channelIds)}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import * as SETTINGS from 'constants/settings';
|
||||||
import { doFetchActiveLivestreams } from 'redux/actions/livestream';
|
import { doFetchActiveLivestreams } from 'redux/actions/livestream';
|
||||||
import { selectActiveLivestreams, selectFetchingActiveLivestreams } from 'redux/selectors/livestream';
|
import { selectActiveLivestreams, selectFetchingActiveLivestreams } 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';
|
||||||
import { selectShowMatureContent, selectHomepageData } from 'redux/selectors/settings';
|
import { selectShowMatureContent, selectHomepageData, selectClientSetting } from 'redux/selectors/settings';
|
||||||
|
|
||||||
import DiscoverPage from './view';
|
import DiscoverPage from './view';
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ const select = (state) => ({
|
||||||
homepageData: selectHomepageData(state),
|
homepageData: selectHomepageData(state),
|
||||||
activeLivestreams: selectActiveLivestreams(state),
|
activeLivestreams: selectActiveLivestreams(state),
|
||||||
fetchingActiveLivestreams: selectFetchingActiveLivestreams(state),
|
fetchingActiveLivestreams: selectFetchingActiveLivestreams(state),
|
||||||
|
hideScheduledLivestreams: selectClientSetting(state, SETTINGS.HIDE_SCHEDULED_LIVESTREAMS),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
|
|
|
@ -30,6 +30,7 @@ type Props = {
|
||||||
activeLivestreams: any,
|
activeLivestreams: any,
|
||||||
doFetchActiveLivestreams: () => void,
|
doFetchActiveLivestreams: () => void,
|
||||||
fetchingActiveLivestreams: boolean,
|
fetchingActiveLivestreams: boolean,
|
||||||
|
hideScheduledLivestreams: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
function HomePage(props: Props) {
|
function HomePage(props: Props) {
|
||||||
|
@ -42,6 +43,7 @@ function HomePage(props: Props) {
|
||||||
activeLivestreams,
|
activeLivestreams,
|
||||||
doFetchActiveLivestreams,
|
doFetchActiveLivestreams,
|
||||||
fetchingActiveLivestreams,
|
fetchingActiveLivestreams,
|
||||||
|
hideScheduledLivestreams,
|
||||||
} = props;
|
} = 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;
|
||||||
|
@ -150,7 +152,7 @@ function HomePage(props: Props) {
|
||||||
|
|
||||||
{!fetchingActiveLivestreams && (
|
{!fetchingActiveLivestreams && (
|
||||||
<>
|
<>
|
||||||
{authenticated && channelIds.length > 0 && (
|
{authenticated && channelIds.length > 0 && !hideScheduledLivestreams && (
|
||||||
<ScheduledStreams
|
<ScheduledStreams
|
||||||
channelIds={channelIds}
|
channelIds={channelIds}
|
||||||
tileLayout
|
tileLayout
|
||||||
|
|
|
@ -74,6 +74,7 @@ const defaultState = {
|
||||||
[SETTINGS.FLOATING_PLAYER]: true,
|
[SETTINGS.FLOATING_PLAYER]: true,
|
||||||
[SETTINGS.AUTO_DOWNLOAD]: true,
|
[SETTINGS.AUTO_DOWNLOAD]: true,
|
||||||
[SETTINGS.HIDE_REPOSTS]: false,
|
[SETTINGS.HIDE_REPOSTS]: false,
|
||||||
|
[SETTINGS.HIDE_SCHEDULED_LIVESTREAMS]: false,
|
||||||
|
|
||||||
// OS
|
// OS
|
||||||
[SETTINGS.AUTO_LAUNCH]: true,
|
[SETTINGS.AUTO_LAUNCH]: true,
|
||||||
|
|
|
@ -41,6 +41,10 @@
|
||||||
margin-bottom: var(--spacing-xl);
|
margin-bottom: var(--spacing-xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ml-s {
|
||||||
|
margin-left: var(--spacing-s);
|
||||||
|
}
|
||||||
|
|
||||||
.ml-m {
|
.ml-m {
|
||||||
margin-left: var(--spacing-m);
|
margin-left: var(--spacing-m);
|
||||||
}
|
}
|
||||||
|
@ -53,6 +57,10 @@
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-s {
|
||||||
|
font-size: var(--font-small);
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: $breakpoint-small) {
|
@media (min-width: $breakpoint-small) {
|
||||||
.md\:items-center {
|
.md\:items-center {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
Loading…
Reference in a new issue