Consolidate legal/requirements
fetch
Ticket: 1128 Requirements: - Fetch once per refresh. This is to cover the case of switching to VPNs, etc. - 1 call per refreshed session.
This commit is contained in:
parent
f01004e9b6
commit
51079ea611
13 changed files with 73 additions and 85 deletions
1
flow-typed/user.js
vendored
1
flow-typed/user.js
vendored
|
@ -65,6 +65,7 @@ declare type UserState ={
|
|||
referrerSetIsPending: boolean,
|
||||
referrerSetError: string,
|
||||
odyseeMembershipsPerClaimIds: ?{ [string]: string },
|
||||
locale: ?LocaleInfo,
|
||||
};
|
||||
|
||||
declare type LocaleInfo = {
|
||||
|
|
|
@ -2,7 +2,7 @@ import { hot } from 'react-hot-loader/root';
|
|||
import { connect } from 'react-redux';
|
||||
import { selectGetSyncErrorMessage, selectSyncFatalError, selectSyncIsLocked } from 'redux/selectors/sync';
|
||||
import { doUserSetReferrer } from 'redux/actions/user';
|
||||
import { selectUser, selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import { selectUser, selectUserLocale, selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import { selectUnclaimedRewards } from 'redux/selectors/rewards';
|
||||
import { doFetchChannelListMine, doFetchCollectionListMine, doResolveUris } from 'redux/actions/claims';
|
||||
import { selectMyChannelClaimIds } from 'redux/selectors/claims';
|
||||
|
@ -24,6 +24,7 @@ import App from './view';
|
|||
|
||||
const select = (state) => ({
|
||||
user: selectUser(state),
|
||||
locale: selectUserLocale(state),
|
||||
theme: selectThemePath(state),
|
||||
language: selectLanguage(state),
|
||||
languages: selectLoadedLanguages(state),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// @flow
|
||||
import * as PAGES from 'constants/pages';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import React, { useEffect, useRef, useState, useLayoutEffect } from 'react';
|
||||
import { lazyImport } from 'util/lazyImport';
|
||||
import { tusUnlockAndNotify, tusHandleTabUpdates } from 'util/tus';
|
||||
|
@ -35,7 +34,6 @@ import {
|
|||
} from 'web/effects/use-degraded-performance';
|
||||
import LANGUAGE_MIGRATIONS from 'constants/language-migrations';
|
||||
import { useIsMobile } from 'effects/use-screensize';
|
||||
import { fetchLocaleApi } from 'locale';
|
||||
import getLanguagesForCountry from 'constants/country_languages';
|
||||
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
|
||||
|
||||
|
@ -64,6 +62,7 @@ type Props = {
|
|||
languages: Array<string>,
|
||||
theme: string,
|
||||
user: ?{ id: string, has_verified_email: boolean, is_reward_approved: boolean },
|
||||
locale: ?LocaleInfo,
|
||||
location: { pathname: string, hash: string, search: string },
|
||||
history: { push: (string) => void },
|
||||
fetchChannelListMine: () => void,
|
||||
|
@ -98,6 +97,7 @@ function App(props: Props) {
|
|||
const {
|
||||
theme,
|
||||
user,
|
||||
locale,
|
||||
fetchChannelListMine,
|
||||
fetchCollectionListMine,
|
||||
signIn,
|
||||
|
@ -137,10 +137,7 @@ function App(props: Props) {
|
|||
const previousHasVerifiedEmail = usePrevious(hasVerifiedEmail);
|
||||
const previousRewardApproved = usePrevious(isRewardApproved);
|
||||
|
||||
const [gdprRequired, setGdprRequired] = usePersistedState('gdprRequired');
|
||||
const [localeLangs, setLocaleLangs] = React.useState();
|
||||
const [localeSwitchDismissed] = usePersistedState('locale-switch-dismissed', false);
|
||||
|
||||
const [showAnalyticsNag, setShowAnalyticsNag] = usePersistedState('analytics-nag', true);
|
||||
const [lbryTvApiStatus, setLbryTvApiStatus] = useState(STATUS_OK);
|
||||
|
||||
|
@ -365,17 +362,6 @@ function App(props: Props) {
|
|||
}
|
||||
}, [previousRewardApproved, isRewardApproved]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchLocaleApi().then((response) => {
|
||||
const locale: LocaleInfo = response?.data;
|
||||
if (locale) {
|
||||
// Put in 'window' for now. Can be moved to localStorage or wherever,
|
||||
// but the key should remain the same so clients are not affected.
|
||||
window[SETTINGS.LOCALE] = locale;
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
// Load IMA3 SDK for aniview
|
||||
// useEffect(() => {
|
||||
// if (!isAuthenticated && SHOW_ADS) {
|
||||
|
@ -402,7 +388,7 @@ function App(props: Props) {
|
|||
}
|
||||
}
|
||||
|
||||
if (inIframe()) {
|
||||
if (inIframe() || !locale || !locale.gdpr_required) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -422,47 +408,10 @@ function App(props: Props) {
|
|||
// OneTrust asks to add this
|
||||
secondScript.innerHTML = 'function OptanonWrapper() { }';
|
||||
|
||||
// gdpr is known to be required, add script
|
||||
if (gdprRequired) {
|
||||
// $FlowFixMe
|
||||
document.head.appendChild(script);
|
||||
// $FlowFixMe
|
||||
document.head.appendChild(secondScript);
|
||||
}
|
||||
|
||||
const shouldFetchLanguage = !localeLangs && !localeSwitchDismissed;
|
||||
const shouldFetchGdpr = gdprRequired === null || gdprRequired === undefined;
|
||||
|
||||
if (shouldFetchLanguage || shouldFetchGdpr) {
|
||||
fetchLocaleApi().then((response) => {
|
||||
if (shouldFetchLanguage) {
|
||||
const countryCode = response?.data?.country;
|
||||
const langs = getLanguagesForCountry(countryCode);
|
||||
|
||||
const supportedLangs = [];
|
||||
langs.forEach((lang) => lang !== 'en' && SUPPORTED_LANGUAGES[lang] && supportedLangs.push(lang));
|
||||
|
||||
if (supportedLangs.length > 0) setLocaleLangs(supportedLangs);
|
||||
}
|
||||
|
||||
// haven't done a gdpr check, do it now
|
||||
if (shouldFetchGdpr) {
|
||||
const gdprRequiredBasedOnLocation = response?.data?.gdpr_required;
|
||||
|
||||
// note we need gdpr and load script
|
||||
if (gdprRequiredBasedOnLocation) {
|
||||
setGdprRequired(true);
|
||||
// $FlowFixMe
|
||||
document.head.appendChild(script);
|
||||
// $FlowFixMe
|
||||
document.head.appendChild(secondScript);
|
||||
// note we don't need gdpr, save to session
|
||||
} else if (gdprRequiredBasedOnLocation === false) {
|
||||
setGdprRequired(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// $FlowFixMe
|
||||
document.head.appendChild(script);
|
||||
// $FlowFixMe
|
||||
document.head.appendChild(secondScript);
|
||||
|
||||
return () => {
|
||||
try {
|
||||
|
@ -472,11 +421,23 @@ function App(props: Props) {
|
|||
document.head.removeChild(secondScript);
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(err);
|
||||
// console.log(err); <-- disabling this ... it's clogging up Sentry logs.
|
||||
}
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps, (one time after locale is fetched)
|
||||
}, [locale]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (locale) {
|
||||
const countryCode = locale.country;
|
||||
const langs = getLanguagesForCountry(countryCode) || [];
|
||||
const supportedLangs = langs.filter((lang) => lang !== 'en' && SUPPORTED_LANGUAGES[lang]);
|
||||
|
||||
if (supportedLangs.length > 0) {
|
||||
setLocaleLangs(supportedLangs);
|
||||
}
|
||||
}
|
||||
}, [locale]);
|
||||
|
||||
// ready for sync syncs, however after signin when hasVerifiedEmail, that syncs too.
|
||||
useEffect(() => {
|
||||
|
@ -563,7 +524,7 @@ function App(props: Props) {
|
|||
/>
|
||||
) : (
|
||||
<React.Fragment>
|
||||
<Router />
|
||||
<Router />
|
||||
<ModalRouter />
|
||||
<React.Suspense fallback={null}>{renderFiledrop && <FileDrop />}</React.Suspense>
|
||||
|
||||
|
|
|
@ -302,6 +302,7 @@ export const USER_SET_REFERRER_SUCCESS = 'USER_SET_REFERRER_SUCCESS';
|
|||
export const USER_SET_REFERRER_FAILURE = 'USER_SET_REFERRER_FAILURE';
|
||||
export const USER_SET_REFERRER_RESET = 'USER_SET_REFERRER_RESET';
|
||||
export const USER_EMAIL_VERIFY_RETRY = 'USER_EMAIL_VERIFY_RETRY';
|
||||
export const USER_FETCH_LOCALE_DONE = 'USER_FETCH_LOCALE_DONE';
|
||||
export const ADD_ODYSEE_MEMBERSHIP_DATA = 'ADD_ODYSEE_MEMBERSHIP_DATA';
|
||||
export const ADD_CLAIMIDS_MEMBERSHIP_DATA = 'ADD_CLAIMIDS_MEMBERSHIP_DATA';
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ export const SUPPORT_OPTION = 'support_option';
|
|||
export const TILE_LAYOUT = 'tile_layout';
|
||||
export const VIDEO_THEATER_MODE = 'video_theater_mode';
|
||||
export const VIDEO_PLAYBACK_RATE = 'video_playback_rate';
|
||||
export const LOCALE = 'odysee_user_locale';
|
||||
|
||||
export const SETTINGS_GRP = {
|
||||
APPEARANCE: 'appearance',
|
||||
|
|
|
@ -18,6 +18,7 @@ import Lbry, { apiCall } from 'lbry';
|
|||
import { isURIValid } from 'util/lbryURI';
|
||||
import { setSearchApi } from 'redux/actions/search';
|
||||
import { doSetLanguage, doFetchLanguage, doUpdateIsNightAsync, doFetchHomepages } from 'redux/actions/settings';
|
||||
import { doFetchUserLocale } from 'redux/actions/user';
|
||||
import { Lbryio, doBlackListedOutpointsSubscribe, doFilteredOutpointsSubscribe } from 'lbryinc';
|
||||
import rewards from 'rewards';
|
||||
import { store, persistor, history } from 'store';
|
||||
|
@ -246,6 +247,7 @@ function AppWrapper() {
|
|||
app.store.dispatch(doUpdateIsNightAsync());
|
||||
app.store.dispatch(doBlackListedOutpointsSubscribe());
|
||||
app.store.dispatch(doFilteredOutpointsSubscribe());
|
||||
app.store.dispatch(doFetchUserLocale());
|
||||
}, 25);
|
||||
|
||||
analytics.startupEvent(Date.now());
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
// @flow
|
||||
import { LOCALE_API } from 'config';
|
||||
|
||||
export async function fetchLocaleApi() {
|
||||
return fetch(LOCALE_API).then((res) => res.json());
|
||||
}
|
|
@ -4,7 +4,7 @@ import OdyseeMembership from './view';
|
|||
import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app';
|
||||
import { selectMyChannelClaims, selectClaimsByUri } from 'redux/selectors/claims';
|
||||
import { doFetchUserMemberships, doCheckUserOdyseeMemberships } from 'redux/actions/user';
|
||||
import { selectUser } from 'redux/selectors/user';
|
||||
import { selectUser, selectUserLocale } from 'redux/selectors/user';
|
||||
|
||||
const select = (state) => {
|
||||
const activeChannelClaim = selectActiveChannelClaim(state);
|
||||
|
@ -15,6 +15,7 @@ const select = (state) => {
|
|||
claimsByUri: selectClaimsByUri(state),
|
||||
incognito: selectIncognito(state),
|
||||
user: selectUser(state),
|
||||
locale: selectUserLocale(state),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ import PremiumBadge from 'component/common/premium-badge';
|
|||
import I18nMessage from 'component/i18nMessage';
|
||||
import useGetUserMemberships from 'effects/use-get-user-memberships';
|
||||
import usePersistedState from 'effects/use-persisted-state';
|
||||
import { fetchLocaleApi } from 'locale';
|
||||
|
||||
let stripeEnvironment = getStripeEnvironment();
|
||||
|
||||
|
@ -39,6 +38,7 @@ type Props = {
|
|||
incognito: boolean,
|
||||
updateUserOdyseeMembershipStatus: () => void,
|
||||
user: ?User,
|
||||
locale: ?LocaleInfo,
|
||||
};
|
||||
|
||||
const OdyseeMembershipPage = (props: Props) => {
|
||||
|
@ -51,6 +51,7 @@ const OdyseeMembershipPage = (props: Props) => {
|
|||
updateUserOdyseeMembershipStatus,
|
||||
incognito,
|
||||
user,
|
||||
locale,
|
||||
} = props;
|
||||
|
||||
const userChannelName = activeChannelClaim ? activeChannelClaim.name : '';
|
||||
|
@ -183,13 +184,8 @@ const OdyseeMembershipPage = (props: Props) => {
|
|||
console.log(err);
|
||||
}
|
||||
|
||||
try {
|
||||
// use EUR if from European continent
|
||||
const localeResponse = await fetchLocaleApi();
|
||||
const isFromEurope = localeResponse?.data?.continent === 'EU';
|
||||
if (isFromEurope) setCurrencyToUse('eur');
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (locale?.continent === 'EU') {
|
||||
setCurrencyToUse('eur');
|
||||
}
|
||||
|
||||
populateMembershipData();
|
||||
|
|
|
@ -12,7 +12,7 @@ import { selectEmailToVerify, selectPhoneToVerify, selectUserCountryCode, select
|
|||
import { doToast } from 'redux/actions/notifications';
|
||||
import rewards from 'rewards';
|
||||
import { Lbryio } from 'lbryinc';
|
||||
import { DOMAIN } from 'config';
|
||||
import { DOMAIN, LOCALE_API } from 'config';
|
||||
import { getDefaultLanguage } from 'util/default-languages';
|
||||
const AUTH_IN_PROGRESS = 'authInProgress';
|
||||
export let sessionStorageAvailable = false;
|
||||
|
@ -899,3 +899,29 @@ export function doFetchUserMemberships(claimIdCsv) {
|
|||
dispatch({ type: ACTIONS.ADD_CLAIMIDS_MEMBERSHIP_DATA, data: { response: updatedResponse } });
|
||||
};
|
||||
}
|
||||
|
||||
export function doFetchUserLocale(isRetry = false) {
|
||||
return (dispatch) => {
|
||||
fetch(LOCALE_API)
|
||||
.then((res) => res.json())
|
||||
.then((json) => {
|
||||
const locale = json.data; // [flow] local: LocaleInfo
|
||||
if (locale) {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_FETCH_LOCALE_DONE,
|
||||
data: locale,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (!isRetry) {
|
||||
// If failed, retry one more time after N seconds. This removes the
|
||||
// need to fetch at each component level. If it failed twice, probably
|
||||
// don't need to fetch anymore.
|
||||
setTimeout(() => {
|
||||
dispatch(doFetchUserLocale(true));
|
||||
}, 10000);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ const defaultState: UserState = {
|
|||
referrerSetIsPending: false,
|
||||
referrerSetError: '',
|
||||
odyseeMembershipsPerClaimIds: undefined,
|
||||
locale: undefined,
|
||||
};
|
||||
|
||||
reducers[ACTIONS.AUTHENTICATION_STARTED] = (state) =>
|
||||
|
@ -365,6 +366,11 @@ reducers[ACTIONS.USER_PASSWORD_SET_FAILURE] = (state, action) =>
|
|||
passwordSetError: action.data.error,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_FETCH_LOCALE_DONE] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
locale: action.data,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.ADD_ODYSEE_MEMBERSHIP_DATA] = (state, action) => {
|
||||
return Object.assign({}, state, {
|
||||
odyseeMembershipName: action.data.odyseeMembershipName,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { CHANNEL_CREATION_LIMIT } from 'config';
|
||||
import { normalizeURI, parseURI, isURIValid } from 'util/lbryURI';
|
||||
import { selectGeoBlockLists } from 'redux/selectors/blocked';
|
||||
import { selectYoutubeChannels } from 'redux/selectors/user';
|
||||
import { selectUserLocale, selectYoutubeChannels } from 'redux/selectors/user';
|
||||
import { selectSupportsByOutpoint } from 'redux/selectors/wallet';
|
||||
import { createSelector } from 'reselect';
|
||||
import { createCachedSelector } from 're-reselect';
|
||||
|
@ -14,7 +14,6 @@ import {
|
|||
getThumbnailFromClaim,
|
||||
} from 'util/claim';
|
||||
import * as CLAIM from 'constants/claim';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import { INTERNAL_TAGS } from 'constants/tags';
|
||||
|
||||
type State = { claims: any, user: UserState };
|
||||
|
@ -844,9 +843,8 @@ export const selectOdyseeMembershipForChannelId = function (state: State, channe
|
|||
export const selectGeoRestrictionForUri = createCachedSelector(
|
||||
selectClaimForUri,
|
||||
selectGeoBlockLists,
|
||||
(claim, geoBlockLists) => {
|
||||
const locale: LocaleInfo = window[SETTINGS.LOCALE]; // <-- NOTE: not handled by redux updates
|
||||
|
||||
selectUserLocale,
|
||||
(claim, geoBlockLists, locale: LocaleInfo) => {
|
||||
if (locale && geoBlockLists && claim) {
|
||||
const claimId: ?string = claim.claim_id;
|
||||
const channelId: ?string = getChannelIdFromClaim(claim);
|
||||
|
|
|
@ -127,3 +127,5 @@ export const selectYouTubeImportVideosComplete = createSelector(selectState, (st
|
|||
});
|
||||
|
||||
export const makeSelectUserPropForProp = (prop) => createSelector(selectUser, (user) => (user ? user[prop] : null));
|
||||
|
||||
export const selectUserLocale = (state) => selectState(state).locale;
|
||||
|
|
Loading…
Reference in a new issue