FYP: setting to hide section

This commit is contained in:
infinite-persistence 2022-03-17 08:23:16 +08:00 committed by Thomas Zarebczan
parent ae56058384
commit f01004e9b6
8 changed files with 77 additions and 6 deletions

View file

@ -2156,6 +2156,9 @@
"Hide Scheduled Livestreams": "Hide Scheduled Livestreams", "Hide Scheduled Livestreams": "Hide Scheduled Livestreams",
"You will not see scheduled livestreams by people you follow on the home or following page.": "You will not see scheduled livestreams by people you follow on the home or following page.", "You will not see scheduled livestreams by people you follow on the home or following page.": "You will not see scheduled livestreams by people you follow on the home or following page.",
"Scheduled streams hidden, you can re-enable them in settings.": "Scheduled streams hidden, you can re-enable them in settings.", "Scheduled streams hidden, you can re-enable them in settings.": "Scheduled streams hidden, you can re-enable them in settings.",
"Hide Personal Recommendations": "Hide Personal Recommendations",
"Recommendations hidden; you can re-enable them in Settings.": "Recommendations hidden; you can re-enable them in Settings.",
"You will not see the personal recommendations in the homepage.": "You will not see the personal recommendations in the homepage.",
"Sorry, the service is currently unavailable.": "Sorry, the service is currently unavailable.", "Sorry, the service is currently unavailable.": "Sorry, the service is currently unavailable.",
"Started %time_date%": "Started %time_date%", "Started %time_date%": "Started %time_date%",
"Live %time_date%": "Live %time_date%", "Live %time_date%": "Live %time_date%",

View file

@ -1,6 +1,10 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import * as SETTINGS from 'constants/settings';
import { doToast } from 'redux/actions/notifications';
import { doFetchPersonalRecommendations } from 'redux/actions/search'; import { doFetchPersonalRecommendations } from 'redux/actions/search';
import { doSetClientSetting } from 'redux/actions/settings';
import { selectPersonalRecommendations } from 'redux/selectors/search'; import { selectPersonalRecommendations } from 'redux/selectors/search';
import { selectClientSetting } from 'redux/selectors/settings';
import { selectHasOdyseeMembership, selectUser } from 'redux/selectors/user'; import { selectHasOdyseeMembership, selectUser } from 'redux/selectors/user';
import RecommendedPersonal from './view'; import RecommendedPersonal from './view';
@ -11,11 +15,14 @@ const select = (state) => {
userId: user && user.id, userId: user && user.id,
personalRecommendations: selectPersonalRecommendations(state), personalRecommendations: selectPersonalRecommendations(state),
hasMembership: selectHasOdyseeMembership(state), hasMembership: selectHasOdyseeMembership(state),
hideFyp: selectClientSetting(state, SETTINGS.HIDE_FYP),
}; };
}; };
const perform = { const perform = {
doFetchPersonalRecommendations, doFetchPersonalRecommendations,
doSetClientSetting,
doToast,
}; };
export default connect(select, perform)(RecommendedPersonal); export default connect(select, perform)(RecommendedPersonal);

View file

@ -7,6 +7,7 @@ import ClaimList from 'component/claimList';
import { URL, SHARE_DOMAIN_URL } from 'config'; import { URL, SHARE_DOMAIN_URL } from 'config';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import * as PAGES from 'constants/pages'; import * as PAGES from 'constants/pages';
import * as SETTINGS from 'constants/settings';
import { useIsLargeScreen, useIsMediumScreen } from 'effects/use-screensize'; import { useIsLargeScreen, useIsMediumScreen } from 'effects/use-screensize';
// TODO: recsysFyp will be moved into 'RecSys', so the redux import in a jsx // TODO: recsysFyp will be moved into 'RecSys', so the redux import in a jsx
@ -22,9 +23,10 @@ type SectionHeaderProps = {
navigate?: string, navigate?: string,
icon?: string, icon?: string,
help?: string, help?: string,
onHide?: () => void,
}; };
const SectionHeader = ({ title, icon = '', help }: SectionHeaderProps) => { const SectionHeader = ({ title, icon = '', help, onHide }: SectionHeaderProps) => {
const SHARE_DOMAIN = SHARE_DOMAIN_URL || URL; const SHARE_DOMAIN = SHARE_DOMAIN_URL || URL;
return ( return (
<h1 className="claim-grid__header"> <h1 className="claim-grid__header">
@ -32,6 +34,7 @@ const SectionHeader = ({ title, icon = '', help }: SectionHeaderProps) => {
<span className="claim-grid__title">{title}</span> <span className="claim-grid__title">{title}</span>
{help} {help}
<HelpLink href={`${SHARE_DOMAIN}/$/${PAGES.FYP}`} iconSize={24} description={__('Learn more')} /> <HelpLink href={`${SHARE_DOMAIN}/$/${PAGES.FYP}`} iconSize={24} description={__('Learn more')} />
<Button button="link" label={__('Hide')} onClick={onHide} className={'ml-m text-s'} />
</h1> </h1>
); );
}; };
@ -52,11 +55,23 @@ type Props = {
userId: ?string, userId: ?string,
personalRecommendations: { gid: string, uris: Array<string> }, personalRecommendations: { gid: string, uris: Array<string> },
hasMembership: boolean, hasMembership: boolean,
hideFyp: boolean,
doFetchPersonalRecommendations: () => void, doFetchPersonalRecommendations: () => void,
doSetClientSetting: (key: string, value: any, pushPreferences: boolean) => void,
doToast: ({ isError?: boolean, message: string }) => void,
}; };
export default function RecommendedPersonal(props: Props) { export default function RecommendedPersonal(props: Props) {
const { onLoad, userId, personalRecommendations, hasMembership, doFetchPersonalRecommendations } = props; const {
onLoad,
userId,
personalRecommendations,
hasMembership,
hideFyp,
doFetchPersonalRecommendations,
doSetClientSetting,
doToast,
} = props;
const [markedGid, setMarkedGid] = React.useState(''); const [markedGid, setMarkedGid] = React.useState('');
const [view, setView] = React.useState(VIEW.ALL_VISIBLE); const [view, setView] = React.useState(VIEW.ALL_VISIBLE);
const isLargeScreen = useIsLargeScreen(); const isLargeScreen = useIsLargeScreen();
@ -66,6 +81,11 @@ export default function RecommendedPersonal(props: Props) {
const countCollapsed = getSuitablePageSizeForScreen(8, isLargeScreen, isMediumScreen); const countCollapsed = getSuitablePageSizeForScreen(8, isLargeScreen, isMediumScreen);
const finalCount = view === VIEW.ALL_VISIBLE ? count : view === VIEW.COLLAPSED ? countCollapsed : count; const finalCount = view === VIEW.ALL_VISIBLE ? count : view === VIEW.COLLAPSED ? countCollapsed : count;
function doHideFyp() {
doSetClientSetting(SETTINGS.HIDE_FYP, true, true);
doToast({ message: __('Recommendations hidden; you can re-enable them in Settings.') });
}
// ************************************************************************** // **************************************************************************
// Effects // Effects
// ************************************************************************** // **************************************************************************
@ -103,7 +123,7 @@ export default function RecommendedPersonal(props: Props) {
React.useEffect(() => { React.useEffect(() => {
// -- Fetch FYP // -- Fetch FYP
if (hasMembership || process.env.ENABLE_WIP_FEATURES) { if (hasMembership) {
doFetchPersonalRecommendations(); doFetchPersonalRecommendations();
} }
}, [hasMembership, doFetchPersonalRecommendations]); }, [hasMembership, doFetchPersonalRecommendations]);
@ -111,13 +131,14 @@ export default function RecommendedPersonal(props: Props) {
// ************************************************************************** // **************************************************************************
// ************************************************************************** // **************************************************************************
if ((!hasMembership && !process.env.ENABLE_WIP_FEATURES) || count < 1) { if (hideFyp || !hasMembership || count < 1) {
return null; return null;
} }
return ( return (
<> <>
<SectionHeader title={__('Recommended For You')} icon={ICONS.WEB} /> <SectionHeader title={__('Recommended For You')} icon={ICONS.WEB} onHide={doHideFyp} />
<ClaimList <ClaimList
tileLayout tileLayout
uris={personalRecommendations.uris.slice(0, finalCount)} uris={personalRecommendations.uris.slice(0, finalCount)}

View file

@ -3,9 +3,11 @@ import { selectMyChannelUrls } from 'redux/selectors/claims';
import * as SETTINGS from 'constants/settings'; import * as SETTINGS from 'constants/settings';
import { doOpenModal } from 'redux/actions/app'; import { doOpenModal } from 'redux/actions/app';
import { doSetPlayingUri } from 'redux/actions/content'; import { doSetPlayingUri } from 'redux/actions/content';
import { doFetchPersonalRecommendations } from 'redux/actions/search';
import { doSetClientSetting } from 'redux/actions/settings'; import { doSetClientSetting } from 'redux/actions/settings';
import { selectPersonalRecommendations } from 'redux/selectors/search';
import { selectShowMatureContent, selectClientSetting } from 'redux/selectors/settings'; import { selectShowMatureContent, selectClientSetting } from 'redux/selectors/settings';
import { selectUserVerifiedEmail } from 'redux/selectors/user'; import { selectHasOdyseeMembership, selectUserVerifiedEmail } from 'redux/selectors/user';
import SettingContent from './view'; import SettingContent from './view';
@ -16,17 +18,21 @@ const select = (state) => ({
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), hideScheduledLivestreams: selectClientSetting(state, SETTINGS.HIDE_SCHEDULED_LIVESTREAMS),
hideFyp: selectClientSetting(state, SETTINGS.HIDE_FYP),
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),
instantPurchaseMax: selectClientSetting(state, SETTINGS.INSTANT_PURCHASE_MAX), instantPurchaseMax: selectClientSetting(state, SETTINGS.INSTANT_PURCHASE_MAX),
enablePublishPreview: selectClientSetting(state, SETTINGS.ENABLE_PUBLISH_PREVIEW), enablePublishPreview: selectClientSetting(state, SETTINGS.ENABLE_PUBLISH_PREVIEW),
hasMembership: selectHasOdyseeMembership(state),
personalRecommendations: selectPersonalRecommendations(state),
}); });
const perform = (dispatch) => ({ const perform = (dispatch) => ({
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)), setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
clearPlayingUri: () => dispatch(doSetPlayingUri({ uri: null })), clearPlayingUri: () => dispatch(doSetPlayingUri({ uri: null })),
openModal: (id, params) => dispatch(doOpenModal(id, params)), openModal: (id, params) => dispatch(doOpenModal(id, params)),
doFetchPersonalRecommendations: () => dispatch(doFetchPersonalRecommendations()),
}); });
export default connect(select, perform)(SettingContent); export default connect(select, perform)(SettingContent);

View file

@ -27,14 +27,18 @@ type Props = {
hideReposts: ?boolean, hideReposts: ?boolean,
showNsfw: boolean, showNsfw: boolean,
hideScheduledLivestreams: boolean, hideScheduledLivestreams: boolean,
hideFyp: boolean,
myChannelUrls: ?Array<string>, myChannelUrls: ?Array<string>,
instantPurchaseEnabled: boolean, instantPurchaseEnabled: boolean,
instantPurchaseMax: Price, instantPurchaseMax: Price,
enablePublishPreview: boolean, enablePublishPreview: boolean,
hasMembership: ?boolean,
personalRecommendations: { gid: string, uris: Array<string> },
// --- perform --- // --- perform ---
setClientSetting: (string, boolean | string | number) => void, setClientSetting: (string, boolean | string | number) => void,
clearPlayingUri: () => void, clearPlayingUri: () => void,
openModal: (string) => void, openModal: (string) => void,
doFetchPersonalRecommendations: () => void,
}; };
export default function SettingContent(props: Props) { export default function SettingContent(props: Props) {
@ -46,15 +50,27 @@ export default function SettingContent(props: Props) {
hideReposts, hideReposts,
showNsfw, showNsfw,
hideScheduledLivestreams, hideScheduledLivestreams,
hideFyp,
myChannelUrls, myChannelUrls,
instantPurchaseEnabled, instantPurchaseEnabled,
instantPurchaseMax, instantPurchaseMax,
enablePublishPreview, enablePublishPreview,
hasMembership,
personalRecommendations,
setClientSetting, setClientSetting,
clearPlayingUri, clearPlayingUri,
openModal, openModal,
doFetchPersonalRecommendations,
} = props; } = props;
const fypExists = personalRecommendations && personalRecommendations.uris.length > 0;
React.useEffect(() => {
if (hasMembership) {
doFetchPersonalRecommendations();
}
}, []);
return ( return (
<> <>
<div className="card__title-section"> <div className="card__title-section">
@ -119,6 +135,20 @@ export default function SettingContent(props: Props) {
/> />
</SettingsRow> </SettingsRow>
<SettingsRow
membersOnly
title={__('Hide Personal Recommendations')}
subtitle={__(HELP.HIDE_FYP)}
disabled={!hasMembership || !fypExists}
>
<FormField
type="checkbox"
name="hide_fyp"
onChange={() => setClientSetting(SETTINGS.HIDE_FYP, !hideFyp)}
checked={hideFyp}
/>
</SettingsRow>
{!SIMPLE_SITE && ( {!SIMPLE_SITE && (
<> <>
{/* {/*
@ -235,6 +265,7 @@ const HELP = {
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.', HIDE_SCHEDULED_LIVESTREAMS: 'You will not see scheduled livestreams by people you follow on the home or following page.',
HIDE_FYP: 'You will not see the personal recommendations in the homepage.',
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.",

View file

@ -36,6 +36,7 @@ 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 HIDE_SCHEDULED_LIVESTREAMS = 'hide_scheduled_livestreams';
export const HIDE_FYP = 'hide_fyp';
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';

View file

@ -18,6 +18,7 @@ export const CLIENT_SYNC_KEYS = [
SETTINGS.SHOW_MATURE, SETTINGS.SHOW_MATURE,
SETTINGS.HIDE_REPOSTS, SETTINGS.HIDE_REPOSTS,
SETTINGS.HIDE_SCHEDULED_LIVESTREAMS, SETTINGS.HIDE_SCHEDULED_LIVESTREAMS,
SETTINGS.HIDE_FYP,
SETTINGS.SHOW_ANONYMOUS, SETTINGS.SHOW_ANONYMOUS,
SETTINGS.INSTANT_PURCHASE_ENABLED, SETTINGS.INSTANT_PURCHASE_ENABLED,
SETTINGS.INSTANT_PURCHASE_MAX, SETTINGS.INSTANT_PURCHASE_MAX,

View file

@ -72,6 +72,7 @@ const defaultState = {
[SETTINGS.AUTO_DOWNLOAD]: true, [SETTINGS.AUTO_DOWNLOAD]: true,
[SETTINGS.HIDE_REPOSTS]: false, [SETTINGS.HIDE_REPOSTS]: false,
[SETTINGS.HIDE_SCHEDULED_LIVESTREAMS]: false, [SETTINGS.HIDE_SCHEDULED_LIVESTREAMS]: false,
[SETTINGS.HIDE_REPOSTS]: false,
// OS // OS
[SETTINGS.AUTO_LAUNCH]: true, [SETTINGS.AUTO_LAUNCH]: true,