- some cleanups
- uri was being parsed the same way in different places, so do it only once for simplicity
This commit is contained in:
Rafael 2022-05-13 10:14:05 -03:00 committed by Thomas Zarebczan
parent b75a4014b6
commit bf158ad696
6 changed files with 63 additions and 142 deletions

View file

@ -13,17 +13,11 @@ import { selectUnclaimedRewards } from 'redux/selectors/rewards';
import { doFetchChannelListMine, doFetchCollectionListMine } from 'redux/actions/claims';
import { selectMyChannelClaimIds } from 'redux/selectors/claims';
import { selectLanguage, selectLoadedLanguages, selectThemePath } from 'redux/selectors/settings';
import {
selectIsUpgradeAvailable,
selectAutoUpdateDownloaded,
selectModal,
selectActiveChannelClaim,
selectIsReloadRequired,
} from 'redux/selectors/app';
import { selectModal, selectActiveChannelClaim, selectIsReloadRequired } from 'redux/selectors/app';
import { selectUploadCount } from 'redux/selectors/publish';
import { doSetLanguage } from 'redux/actions/settings';
import { doSyncLoop } from 'redux/actions/sync';
import { doDownloadUpgradeRequested, doSignIn, doSetIncognito } from 'redux/actions/app';
import { doSignIn, doSetIncognito } from 'redux/actions/app';
import { doFetchModBlockedList, doFetchCommentModAmIList } from 'redux/actions/comments';
import App from './view';
@ -33,8 +27,6 @@ const select = (state) => ({
theme: selectThemePath(state),
language: selectLanguage(state),
languages: selectLoadedLanguages(state),
autoUpdateDownloaded: selectAutoUpdateDownloaded(state),
isUpgradeAvailable: selectIsUpgradeAvailable(state),
isReloadRequired: selectIsReloadRequired(state),
syncError: selectGetSyncErrorMessage(state),
syncIsLocked: selectSyncIsLocked(state),
@ -49,17 +41,16 @@ const select = (state) => ({
homepageFetched: selectHomepageFetched(state),
});
const perform = (dispatch) => ({
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
fetchCollectionListMine: () => dispatch(doFetchCollectionListMine()),
setLanguage: (language) => dispatch(doSetLanguage(language)),
signIn: () => dispatch(doSignIn()),
requestDownloadUpgrade: () => dispatch(doDownloadUpgradeRequested()),
syncLoop: (noInterval) => dispatch(doSyncLoop(noInterval)),
setReferrer: (referrer, doClaim) => dispatch(doUserSetReferrer(referrer, doClaim)),
setIncognito: () => dispatch(doSetIncognito()),
fetchModBlockedList: () => dispatch(doFetchModBlockedList()),
fetchModAmIList: () => dispatch(doFetchCommentModAmIList()),
});
const perform = {
fetchChannelListMine: doFetchChannelListMine,
fetchCollectionListMine: doFetchCollectionListMine,
setLanguage: doSetLanguage,
signIn: doSignIn,
syncLoop: doSyncLoop,
setReferrer: doUserSetReferrer,
setIncognito: doSetIncognito,
fetchModBlockedList: doFetchModBlockedList,
fetchModAmIList: doFetchCommentModAmIList,
};
export default hot(connect(select, perform)(App));

View file

@ -3,15 +3,13 @@ import * as PAGES from 'constants/pages';
import React, { useEffect, useRef, useState } from 'react';
import { lazyImport } from 'util/lazyImport';
import { tusUnlockAndNotify, tusHandleTabUpdates } from 'util/tus';
import classnames from 'classnames';
import analytics from 'analytics';
import { setSearchUserId } from 'redux/actions/search';
import { buildURI, parseURI } from 'util/lbryURI';
import { SIMPLE_SITE } from 'config';
import { normalizeURI } from 'util/lbryURI';
import { generateGoogleCacheUrl } from 'util/url';
import Router from 'component/router/index';
import ModalRouter from 'modal/modalRouter';
import ReactModal from 'react-modal';
import { openContextMenu } from 'util/context-menu';
import useKonamiListener from 'util/enhanced-layout';
import Yrbl from 'component/yrbl';
import FileRenderFloating from 'component/fileRenderFloating';
@ -40,8 +38,6 @@ import SUPPORTED_LANGUAGES from 'constants/supported_languages';
const FileDrop = lazyImport(() => import('component/fileDrop' /* webpackChunkName: "fileDrop" */));
const NagContinueFirstRun = lazyImport(() => import('component/nagContinueFirstRun' /* webpackChunkName: "nagCFR" */));
const NagLocaleSwitch = lazyImport(() => import('component/nagLocaleSwitch' /* webpackChunkName: "nagLocaleSwitch" */));
const OpenInAppLink = lazyImport(() => import('web/component/openInAppLink' /* webpackChunkName: "openInAppLink" */));
const NagDataCollection = lazyImport(() => import('web/component/nag-data-collection' /* webpackChunkName: "nagDC" */));
const NagDegradedPerformance = lazyImport(() =>
import('web/component/nag-degraded-performance' /* webpackChunkName: "NagDegradedPerformance" */)
);
@ -63,16 +59,13 @@ type Props = {
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, location: { pathname: string } },
location: { pathname: string, hash: string, search: string, hostname: string, reload: () => void },
history: { push: (string) => void, location: { pathname: string }, replace: (string) => void },
fetchChannelListMine: () => void,
fetchCollectionListMine: () => void,
signIn: () => void,
requestDownloadUpgrade: () => void,
setLanguage: (string) => void,
isUpgradeAvailable: boolean,
isReloadRequired: boolean,
autoUpdateDownloaded: boolean,
uploadCount: number,
balance: ?number,
syncIsLocked: boolean,
@ -97,13 +90,11 @@ function App(props: Props) {
theme,
user,
locale,
location,
fetchChannelListMine,
fetchCollectionListMine,
signIn,
autoUpdateDownloaded,
isUpgradeAvailable,
isReloadRequired,
requestDownloadUpgrade,
uploadCount,
history,
syncError,
@ -137,16 +128,12 @@ function App(props: Props) {
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);
const { pathname, hash, search } = props.location;
const [upgradeNagClosed, setUpgradeNagClosed] = useState(false);
const { pathname, hash, search, hostname } = location;
const [retryingSync, setRetryingSync] = useState(false);
const [langRenderKey, setLangRenderKey] = useState(0);
const [seenSunsestMessage, setSeenSunsetMessage] = usePersistedState('lbrytv-sunset', false);
const showUpgradeButton =
(autoUpdateDownloaded || (process.platform === 'linux' && isUpgradeAvailable)) && !upgradeNagClosed;
// referral claiming
const referredRewardAvailable = rewards && rewards.some((reward) => reward.reward_type === REWARDS.TYPE_REFEREE);
const urlParams = new URLSearchParams(search);
@ -163,14 +150,23 @@ function App(props: Props) {
const renderFiledrop = !isMobile && isAuthenticated;
const connectionStatus = useConnectionStatus();
const urlPath = pathname + hash;
let path = urlPath.slice(1).replace(/:/g, '#');
if (search && search.startsWith('?q=cache:')) {
generateGoogleCacheUrl(search, path);
}
let uri;
try {
const newpath = buildURI(parseURI(pathname.slice(1).replace(/:/g, '#')));
uri = newpath + hash;
} catch (e) {}
uri = normalizeURI(path);
} catch (e) {
const match = path.match(/[#/:]/);
function handleAnalyticsDismiss() {
setShowAnalyticsNag(false);
if (!path.startsWith('$/') && match && match.index) {
uri = `lbry://${path.slice(0, match.index)}`;
}
}
function getStatusNag() {
@ -388,7 +384,7 @@ function App(props: Props) {
}
// $FlowFixMe
const useProductionOneTrust = process.env.NODE_ENV === 'production' && location.hostname === 'odysee.com';
const useProductionOneTrust = process.env.NODE_ENV === 'production' && hostname === 'odysee.com';
const script = document.createElement('script');
script.src = oneTrustScriptSrc;
@ -493,17 +489,8 @@ function App(props: Props) {
}
return (
<div
className={classnames(MAIN_WRAPPER_CLASS, {
// @if TARGET='app'
[`${MAIN_WRAPPER_CLASS}--mac`]: IS_MAC,
// @endif
})}
ref={appRef}
key={langRenderKey}
onContextMenu={IS_WEB ? undefined : (e) => openContextMenu(e)}
>
{IS_WEB && lbryTvApiStatus === STATUS_DOWN ? (
<div className={MAIN_WRAPPER_CLASS} ref={appRef} key={langRenderKey}>
{lbryTvApiStatus === STATUS_DOWN ? (
<Yrbl
className="main--empty"
title={__('odysee.com is currently down')}
@ -511,8 +498,9 @@ function App(props: Props) {
/>
) : (
<React.Fragment>
<Router />
<Router uri={uri} />
<ModalRouter />
<React.Suspense fallback={null}>{renderFiledrop && <FileDrop />}</React.Suspense>
<FileRenderFloating />
@ -520,26 +508,11 @@ function App(props: Props) {
<React.Suspense fallback={null}>
{isEnhancedLayout && <Yrbl className="yrbl--enhanced" />}
{/* @if TARGET='app' */}
{showUpgradeButton && (
<Nag
message={__('An upgrade is available.')}
actionText={__('Install Now')}
onClick={requestDownloadUpgrade}
onClose={() => setUpgradeNagClosed(true)}
/>
)}
{/* @endif */}
<YoutubeWelcome />
{!SIMPLE_SITE && !shouldHideNag && <OpenInAppLink uri={uri} />}
{!shouldHideNag && <NagContinueFirstRun />}
{fromLbrytvParam && !seenSunsestMessage && !shouldHideNag && (
<NagSunset email={hasVerifiedEmail} onClose={() => setSeenSunsetMessage(true)} />
)}
{!SIMPLE_SITE && lbryTvApiStatus === STATUS_OK && showAnalyticsNag && !shouldHideNag && (
<NagDataCollection onClose={handleAnalyticsDismiss} />
)}
{getStatusNag()}
</React.Suspense>
</React.Fragment>

View file

@ -4,29 +4,14 @@ import { selectUserVerifiedEmail } from 'redux/selectors/user';
import { selectHasNavigated, selectScrollStartingPosition } from 'redux/selectors/app';
import { selectClientSetting, selectHomepageData, selectWildWestDisabled } from 'redux/selectors/settings';
import Router from './view';
import { normalizeURI } from 'util/lbryURI';
import { selectTitleForUri } from 'redux/selectors/claims';
import { doSetHasNavigated, doSetActiveChannel } from 'redux/actions/app';
import { doUserSetReferrer } from 'redux/actions/user';
import { selectHasUnclaimedRefereeReward } from 'redux/selectors/rewards';
import { selectUnseenNotificationCount } from 'redux/selectors/notifications';
const select = (state) => {
const { pathname, hash } = state.router.location;
const urlPath = pathname + hash;
// Remove the leading "/" added by the browser
const path = urlPath.slice(1).replace(/:/g, '#');
let uri;
try {
uri = normalizeURI(path);
} catch (e) {
const match = path.match(/[#/:]/);
if (!path.startsWith('$/') && match && match.index) {
uri = `lbry://${path.slice(0, match.index)}`;
}
}
const select = (state, props) => {
const { uri } = props;
return {
uri,

View file

@ -16,17 +16,11 @@ import { buildUnseenCountStr } from 'util/notifications';
import HomePage from 'page/home';
// @if TARGET='app'
const BackupPage = lazyImport(() => import('page/backup' /* webpackChunkName: "backup" */));
// @endif
// @if TARGET='web'
const Code2257Page = lazyImport(() => import('web/page/code2257' /* webpackChunkName: "code2257" */));
const PrivacyPolicyPage = lazyImport(() => import('web/page/privacypolicy' /* webpackChunkName: "privacypolicy" */));
const TOSPage = lazyImport(() => import('web/page/tos' /* webpackChunkName: "tos" */));
const FypPage = lazyImport(() => import('web/page/fyp' /* webpackChunkName: "fyp" */));
const YouTubeTOSPage = lazyImport(() => import('web/page/youtubetos' /* webpackChunkName: "youtubetos" */));
// @endif
const SignInPage = lazyImport(() => import('page/signIn' /* webpackChunkName: "signIn" */));
const SignInWalletPasswordPage = lazyImport(() =>
@ -132,7 +126,6 @@ type Props = {
},
uri: string,
title: string,
welcomeVersion: number,
hasNavigated: boolean,
setHasNavigated: () => void,
setReferrer: (?string) => void,
@ -333,16 +326,13 @@ function AppRouter(props: Props) {
<Route path={`/$/${PAGES.AUTH}/*`} exact component={SignUpPage} />
<Route path={`/$/${PAGES.HELP}`} exact component={HelpPage} />
{/* @if TARGET='app' */}
<Route path={`/$/${PAGES.BACKUP}`} exact component={BackupPage} />
{/* @endif */}
{/* @if TARGET='web' */}
<Route path={`/$/${PAGES.CODE_2257}`} exact component={Code2257Page} />
<Route path={`/$/${PAGES.PRIVACY_POLICY}`} exact component={PrivacyPolicyPage} />
<Route path={`/$/${PAGES.TOS}`} exact component={TOSPage} />
<Route path={`/$/${PAGES.FYP}`} exact component={FypPage} />
<Route path={`/$/${PAGES.YOUTUBE_TOS}`} exact component={YouTubeTOSPage} />
{/* @endif */}
<Route path={`/$/${PAGES.AUTH_VERIFY}`} exact component={SignInVerifyPage} />
<Route path={`/$/${PAGES.SEARCH}`} exact component={SearchPage} />
<Route path={`/$/${PAGES.TOP}`} exact component={TopPage} />
@ -411,8 +401,8 @@ function AppRouter(props: Props) {
<Route path={`/$/${PAGES.EMBED}/:claimName/:claimId`} exact component={EmbedWrapperPage} />
{/* Below need to go at the end to make sure we don't match any of our pages first */}
<Route path="/:claimName" exact component={ShowPage} />
<Route path="/:claimName/:streamName" exact component={ShowPage} />
<Route path="/:claimName" exact render={() => <ShowPage uri={uri} />} />
<Route path="/:claimName/:streamName" exact render={() => <ShowPage uri={uri} />} />
<Route path="/*" component={FourOhFourPage} />
</Switch>
</React.Suspense>

View file

@ -1,4 +1,3 @@
import { DOMAIN } from 'config';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';
import {
@ -19,51 +18,17 @@ import { doBeginPublish } from 'redux/actions/publish';
import { doOpenModal } from 'redux/actions/app';
import { doFetchItemsInCollection } from 'redux/actions/collections';
import { isStreamPlaceholderClaim } from 'util/claim';
import { normalizeURI } from 'util/lbryURI';
import * as COLLECTIONS_CONSTS from 'constants/collections';
import { selectIsSubscribedForUri } from 'redux/selectors/subscriptions';
import { selectBlacklistedOutpointMap } from 'lbryinc';
import ShowPage from './view';
const select = (state, props) => {
const { location, history } = props;
const { pathname, hash, search } = location;
const { uri, location } = props;
const { search } = location;
const urlPath = pathname + hash;
const urlParams = new URLSearchParams(search);
// Remove the leading "/" added by the browser
let path = urlPath.slice(1).replace(/:/g, '#');
// Google cache url
// ex: webcache.googleusercontent.com/search?q=cache:MLwN3a8fCbYJ:https://lbry.tv/%40Bombards_Body_Language:f+&cd=12&hl=en&ct=clnk&gl=us
// Extract the lbry url and use that instead
// Without this it will try to render lbry://search
if (search && search.startsWith('?q=cache:')) {
const googleCacheRegex = new RegExp(`(https://${DOMAIN}/)([^+]*)`);
const [x, y, googleCachedUrl] = search.match(googleCacheRegex); // eslint-disable-line
if (googleCachedUrl) {
const actualUrl = decodeURIComponent(googleCachedUrl);
if (actualUrl) {
path = actualUrl.replace(/:/g, '#');
}
}
}
let uri;
try {
uri = normalizeURI(path);
} catch (e) {
const match = path.match(/[#/:]/);
if (path === '$/') {
history.replace(`/`);
} else if (!path.startsWith('$/') && match && match.index) {
uri = `lbry://${path.slice(0, match.index)}`;
history.replace(`/${path.slice(0, match.index)}`);
}
}
const claim = selectClaimForUri(state, uri);
const collectionId =
urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID) ||

View file

@ -1,5 +1,6 @@
// Can't use aliases here because we're doing exports/require
import { DOMAIN } from 'config';
const PAGES = require('../constants/pages');
const { parseURI, buildURI } = require('../util/lbryURI');
const COLLECTIONS_CONSTS = require('../constants/collections');
@ -165,3 +166,19 @@ export const generateListSearchUrlParams = (collectionId) => {
urlParams.set(COLLECTIONS_CONSTS.COLLECTION_ID, collectionId);
return `?` + urlParams.toString();
};
// Google cache url
// ex: webcache.googleusercontent.com/search?q=cache:MLwN3a8fCbYJ:https://lbry.tv/%40Bombards_Body_Language:f+&cd=12&hl=en&ct=clnk&gl=us
// Extract the lbry url and use that instead
// Without this it will try to render lbry://search
export function generateGoogleCacheUrl(search, path) {
const googleCacheRegex = new RegExp(`(https://${DOMAIN}/)([^+]*)`);
const [x, y, googleCachedUrl] = search.match(googleCacheRegex); // eslint-disable-line
if (googleCachedUrl) {
const actualUrl = decodeURIComponent(googleCachedUrl);
if (actualUrl) {
path = actualUrl.replace(/:/g, '#');
}
}
}