lbry-desktop/ui/component/router/view.jsx

298 lines
12 KiB
React
Raw Normal View History

2019-11-07 20:39:22 +01:00
// @flow
import * as PAGES from 'constants/pages';
import React, { useEffect } from 'react';
import { Route, Redirect, Switch, withRouter } from 'react-router-dom';
2019-11-07 20:39:22 +01:00
import SettingsPage from 'page/settings';
import SettingsNotificationsPage from 'page/settingsNotifications';
import SettingsAdvancedPage from 'page/settingsAdvanced';
2019-11-07 20:39:22 +01:00
import HelpPage from 'page/help';
// @if TARGET='app'
2020-02-21 18:23:04 +01:00
import BackupPage from 'page/backup';
// @endif
2020-05-23 02:18:10 +02:00
// @if TARGET='web'
2020-05-26 18:20:17 +02:00
import Code2257Page from 'web/page/code2257';
2020-05-23 02:18:10 +02:00
// @endif
2019-11-07 20:39:22 +01:00
import ReportPage from 'page/report';
import ShowPage from 'page/show';
import PublishPage from 'page/publish';
import DiscoverPage from 'page/discover';
2020-01-20 17:47:03 +01:00
import HomePage from 'page/home';
2020-01-14 21:44:07 +01:00
import InvitedPage from 'page/invited';
2019-11-07 20:39:22 +01:00
import RewardsPage from 'page/rewards';
import FileListPublished from 'page/fileListPublished';
import InvitePage from 'page/invite';
import SearchPage from 'page/search';
import LibraryPage from 'page/library';
import WalletPage from 'page/wallet';
2020-01-02 17:30:27 +01:00
import TagsFollowingPage from 'page/tagsFollowing';
import ChannelsFollowingPage from 'page/channelsFollowing';
2020-02-17 20:12:28 +01:00
import ChannelsFollowingDiscoverPage from 'page/channelsFollowingDiscover';
import TagsFollowingManagePage from 'page/tagsFollowingManage';
2019-11-07 20:39:22 +01:00
import ListBlockedPage from 'page/listBlocked';
import FourOhFourPage from 'page/fourOhFour';
import SignInPage from 'page/signIn';
import SignUpPage from 'page/signUp';
2020-07-07 09:52:14 +02:00
import PasswordResetPage from 'page/passwordReset';
import PasswordSetPage from 'page/passwordSet';
2019-11-14 01:33:36 +01:00
import SignInVerifyPage from 'page/signInVerify';
2019-11-07 20:39:22 +01:00
import ChannelsPage from 'page/channels';
2021-03-15 15:58:21 +01:00
import LiveStreamSetupPage from 'page/livestreamSetup';
import EmbedWrapperPage from 'page/embedWrapper';
2020-02-11 20:04:51 +01:00
import TopPage from 'page/top';
2020-03-18 18:11:37 +01:00
import Welcome from 'page/welcome';
import CreatorDashboard from 'page/creatorDashboard';
import RewardsVerifyPage from 'page/rewardsVerify';
2020-05-04 18:55:10 +02:00
import CheckoutPage from 'page/checkoutPage';
2020-06-29 21:54:07 +02:00
import ChannelNew from 'page/channelNew';
import RepostNew from 'page/repost';
2020-06-01 19:03:19 +02:00
import BuyPage from 'page/buy';
2020-07-23 16:22:57 +02:00
import NotificationsPage from 'page/notifications';
2020-09-18 17:16:49 +02:00
import SignInWalletPasswordPage from 'page/signInWalletPassword';
2020-09-03 22:05:38 +02:00
import YoutubeSyncPage from 'page/youtubeSync';
2020-10-30 05:19:05 +01:00
import { LINKED_COMMENT_QUERY_PARAM } from 'constants/comment';
import { parseURI, isURIValid } from 'lbry-redux';
2021-03-30 01:05:18 +02:00
import { SITE_TITLE, WELCOME_VERSION, SIMPLE_SITE } from 'config';
2019-11-07 20:39:22 +01:00
// Tell the browser we are handling scroll restoration
if ('scrollRestoration' in history) {
history.scrollRestoration = 'manual';
}
type Props = {
currentScroll: number,
isAuthenticated: boolean,
location: { pathname: string, search: string, hash: string },
2020-01-25 21:37:02 +01:00
history: {
action: string,
2020-01-25 21:37:02 +01:00
entries: { title: string }[],
goBack: () => void,
goForward: () => void,
index: number,
length: number,
location: { pathname: string },
push: (string) => void,
2020-01-25 21:37:02 +01:00
state: {},
replaceState: ({}, string, string) => void,
listen: (any) => () => void,
2020-01-25 21:37:02 +01:00
},
uri: string,
title: string,
welcomeVersion: number,
hasNavigated: boolean,
setHasNavigated: () => void,
setReferrer: (string) => void,
hasUnclaimedRefereeReward: boolean,
homepageData: any,
2019-11-07 20:39:22 +01:00
};
2020-10-30 05:19:05 +01:00
type PrivateRouteProps = Props & {
component: any,
isAuthenticated: boolean,
};
function PrivateRoute(props: PrivateRouteProps) {
const { component: Component, isAuthenticated, ...rest } = props;
const urlSearchParams = new URLSearchParams(props.location.search);
const redirectUrl = urlSearchParams.get('redirect');
2020-10-30 05:19:05 +01:00
return (
<Route
{...rest}
render={(props) =>
2020-10-30 05:19:05 +01:00
isAuthenticated || !IS_WEB ? (
<Component {...props} />
) : (
<Redirect to={`/$/${PAGES.AUTH}?redirect=${redirectUrl || props.location.pathname}`} />
2020-10-30 05:19:05 +01:00
)
}
/>
);
}
2019-11-07 20:39:22 +01:00
function AppRouter(props: Props) {
const {
currentScroll,
location: { pathname, search, hash },
isAuthenticated,
2020-01-25 21:37:02 +01:00
history,
uri,
title,
welcomeVersion,
hasNavigated,
setHasNavigated,
hasUnclaimedRefereeReward,
setReferrer,
homepageData,
} = props;
const { entries, listen, action: historyAction } = history;
2020-01-25 21:37:02 +01:00
const entryIndex = history.index;
const urlParams = new URLSearchParams(search);
const resetScroll = urlParams.get('reset_scroll');
const hasLinkedCommentInUrl = urlParams.get(LINKED_COMMENT_QUERY_PARAM);
2020-01-25 21:37:02 +01:00
const dynamicRoutes = Object.values(homepageData).filter(
(potentialRoute: any) => potentialRoute && potentialRoute.route
);
// For people arriving at settings page from deeplinks, know whether they can "go back"
useEffect(() => {
const unlisten = listen((location, action) => {
if (action === 'PUSH') {
if (!hasNavigated && setHasNavigated) setHasNavigated();
}
});
return unlisten;
}, [listen, hasNavigated, setHasNavigated]);
useEffect(() => {
if (!hasNavigated && hasUnclaimedRefereeReward && !isAuthenticated) {
const valid = isURIValid(uri);
if (valid) {
const { path } = parseURI(uri);
if (path !== 'undefined') setReferrer(path);
}
}
}, [hasNavigated, uri, hasUnclaimedRefereeReward, setReferrer, isAuthenticated]);
2020-01-25 21:37:02 +01:00
useEffect(() => {
2020-02-13 02:48:28 +01:00
if (uri) {
const { channelName, streamName } = parseURI(uri);
if (typeof title !== 'undefined' && title !== '') {
document.title = title;
2021-04-05 03:26:26 +02:00
} else if (streamName !== undefined && streamName !== null) {
2020-02-13 02:48:28 +01:00
document.title = streamName;
2021-04-05 03:26:26 +02:00
} else if (channelName !== undefined && channelName !== null) {
2020-02-13 02:48:28 +01:00
document.title = channelName;
} else {
document.title = IS_WEB ? SITE_TITLE : 'LBRY';
}
2020-01-25 21:37:02 +01:00
} else {
document.title = IS_WEB ? SITE_TITLE : 'LBRY';
}
2020-01-26 04:40:30 +01:00
// @if TARGET='app'
2020-01-25 21:37:02 +01:00
entries[entryIndex].title = document.title;
2020-01-26 04:40:30 +01:00
// @endif
2020-01-25 21:37:02 +01:00
return () => {
document.title = IS_WEB ? SITE_TITLE : 'LBRY';
};
2020-02-13 02:48:28 +01:00
}, [entries, entryIndex, title, uri]);
2019-11-07 20:39:22 +01:00
useEffect(() => {
if (!hasLinkedCommentInUrl) {
if (hash && historyAction === 'PUSH') {
const id = hash.replace('#', '');
const element = document.getElementById(id);
if (element) {
window.scrollTo(0, element.offsetTop);
}
} else {
window.scrollTo(0, currentScroll);
}
}
}, [currentScroll, pathname, search, hash, resetScroll, hasLinkedCommentInUrl, historyAction]);
2019-11-07 20:39:22 +01:00
2020-01-29 21:21:03 +01:00
// react-router doesn't decode pathanmes before doing the route matching check
// We have to redirect here because if we redirect on the server, it might get encoded again
// in the browser causing a redirect loop
const decodedUrl = decodeURIComponent(pathname) + search;
if (decodedUrl !== pathname + search) {
return <Redirect to={decodedUrl} />;
2020-01-29 21:21:03 +01:00
}
2019-11-07 20:39:22 +01:00
return (
<Switch>
{/* @if TARGET='app' */}
{welcomeVersion < WELCOME_VERSION && <Route path="/*" component={Welcome} />}
{/* @endif */}
2020-02-26 20:14:10 +01:00
<Redirect
from={`/$/${PAGES.DEPRECATED__CHANNELS_FOLLOWING_MANAGE}`}
to={`/$/${PAGES.CHANNELS_FOLLOWING_DISCOVER}`}
/>
<Redirect from={`/$/${PAGES.DEPRECATED__CHANNELS_FOLLOWING}`} to={`/$/${PAGES.CHANNELS_FOLLOWING}`} />
<Redirect from={`/$/${PAGES.DEPRECATED__TAGS_FOLLOWING}`} to={`/$/${PAGES.TAGS_FOLLOWING}`} />
<Redirect from={`/$/${PAGES.DEPRECATED__TAGS_FOLLOWING_MANAGE}`} to={`/$/${PAGES.TAGS_FOLLOWING_MANAGE}`} />
2020-07-23 19:02:07 +02:00
<Redirect from={`/$/${PAGES.DEPRECATED__PUBLISH}`} to={`/$/${PAGES.UPLOAD}`} />
<Redirect from={`/$/${PAGES.DEPRECATED__PUBLISHED}`} to={`/$/${PAGES.UPLOADS}`} />
2020-02-26 19:39:03 +01:00
2020-03-18 19:21:33 +01:00
<Route path={`/`} exact component={HomePage} />
<Route path={`/$/${PAGES.DISCOVER}`} exact component={DiscoverPage} />
2021-03-30 01:05:18 +02:00
{SIMPLE_SITE && <Route path={`/$/${PAGES.WILD_WEST}`} exact component={DiscoverPage} />}
2020-10-05 20:24:57 +02:00
{/* $FlowFixMe */}
{dynamicRoutes.map((dynamicRouteProps: RowDataItem) => (
<Route
key={dynamicRouteProps.route}
path={dynamicRouteProps.route}
component={(routerProps) => <DiscoverPage {...routerProps} dynamicRouteProps={dynamicRouteProps} />}
2020-10-05 20:24:57 +02:00
/>
))}
<Route path={`/$/${PAGES.AUTH_SIGNIN}`} exact component={SignInPage} />
2020-07-07 09:52:14 +02:00
<Route path={`/$/${PAGES.AUTH_PASSWORD_RESET}`} exact component={PasswordResetPage} />
<Route path={`/$/${PAGES.AUTH_PASSWORD_SET}`} exact component={PasswordSetPage} />
<Route path={`/$/${PAGES.AUTH}`} exact component={SignUpPage} />
<Route path={`/$/${PAGES.AUTH}/*`} exact component={SignUpPage} />
<Route path={`/$/${PAGES.WELCOME}`} exact component={Welcome} />
2020-08-10 22:47:39 +02:00
<Route path={`/$/${PAGES.HELP}`} exact component={HelpPage} />
{/* @if TARGET='app' */}
2020-02-21 18:23:04 +01:00
<Route path={`/$/${PAGES.BACKUP}`} exact component={BackupPage} />
{/* @endif */}
2020-05-23 02:18:10 +02:00
{/* @if TARGET='web' */}
<Route path={`/$/${PAGES.CODE_2257}`} exact component={Code2257Page} />
{/* @endif */}
<Route path={`/$/${PAGES.AUTH_VERIFY}`} exact component={SignInVerifyPage} />
<Route path={`/$/${PAGES.SEARCH}`} exact component={SearchPage} />
2020-02-11 20:04:51 +01:00
<Route path={`/$/${PAGES.TOP}`} exact component={TopPage} />
<Route path={`/$/${PAGES.SETTINGS}`} exact component={SettingsPage} />
<Route path={`/$/${PAGES.SETTINGS_ADVANCED}`} exact component={SettingsAdvancedPage} />
2020-01-14 21:44:07 +01:00
<Route path={`/$/${PAGES.INVITE}/:referrer`} exact component={InvitedPage} />
2020-05-04 18:55:10 +02:00
<Route path={`/$/${PAGES.CHECKOUT}`} exact component={CheckoutPage} />
2019-11-07 20:39:22 +01:00
2020-10-05 20:24:57 +02:00
<PrivateRoute {...props} exact path={`/$/${PAGES.YOUTUBE_SYNC}`} component={YoutubeSyncPage} />
2020-08-11 22:32:03 +02:00
<PrivateRoute {...props} exact path={`/$/${PAGES.TAGS_FOLLOWING}`} component={TagsFollowingPage} />
2020-08-10 22:47:39 +02:00
<PrivateRoute
{...props}
2020-08-11 22:32:03 +02:00
exact
2020-08-10 22:47:39 +02:00
path={`/$/${PAGES.CHANNELS_FOLLOWING}`}
component={isAuthenticated || !IS_WEB ? ChannelsFollowingPage : DiscoverPage}
/>
<PrivateRoute {...props} path={`/$/${PAGES.SETTINGS_NOTIFICATIONS}`} component={SettingsNotificationsPage} />
2020-07-23 16:22:57 +02:00
<PrivateRoute
{...props}
2020-08-11 22:32:03 +02:00
exact
2020-08-10 22:47:39 +02:00
path={`/$/${PAGES.CHANNELS_FOLLOWING_DISCOVER}`}
component={ChannelsFollowingDiscoverPage}
2020-07-23 16:22:57 +02:00
/>
<PrivateRoute {...props} path={`/$/${PAGES.INVITE}`} component={InvitePage} />
2020-06-29 21:54:07 +02:00
<PrivateRoute {...props} path={`/$/${PAGES.CHANNEL_NEW}`} component={ChannelNew} />
<PrivateRoute {...props} path={`/$/${PAGES.REPOST_NEW}`} component={RepostNew} />
2020-07-23 19:02:07 +02:00
<PrivateRoute {...props} path={`/$/${PAGES.UPLOADS}`} component={FileListPublished} />
2020-03-18 18:11:37 +01:00
<PrivateRoute {...props} path={`/$/${PAGES.CREATOR_DASHBOARD}`} component={CreatorDashboard} />
2020-07-23 19:02:07 +02:00
<PrivateRoute {...props} path={`/$/${PAGES.UPLOAD}`} component={PublishPage} />
<PrivateRoute {...props} path={`/$/${PAGES.REPORT}`} component={ReportPage} />
<PrivateRoute {...props} path={`/$/${PAGES.REWARDS}`} exact component={RewardsPage} />
<PrivateRoute {...props} path={`/$/${PAGES.REWARDS_VERIFY}`} component={RewardsVerifyPage} />
<PrivateRoute {...props} path={`/$/${PAGES.LIBRARY}`} component={LibraryPage} />
<PrivateRoute {...props} path={`/$/${PAGES.TAGS_FOLLOWING_MANAGE}`} component={TagsFollowingManagePage} />
<PrivateRoute {...props} path={`/$/${PAGES.SETTINGS_BLOCKED_MUTED}`} component={ListBlockedPage} />
<PrivateRoute {...props} path={`/$/${PAGES.WALLET}`} exact component={WalletPage} />
<PrivateRoute {...props} path={`/$/${PAGES.CHANNELS}`} component={ChannelsPage} />
2021-03-15 15:58:21 +01:00
<PrivateRoute {...props} path={`/$/${PAGES.LIVESTREAM}`} component={LiveStreamSetupPage} />
2020-06-01 19:03:19 +02:00
<PrivateRoute {...props} path={`/$/${PAGES.BUY}`} component={BuyPage} />
2020-07-23 16:22:57 +02:00
<PrivateRoute {...props} path={`/$/${PAGES.NOTIFICATIONS}`} component={NotificationsPage} />
2020-09-18 17:16:49 +02:00
<PrivateRoute {...props} path={`/$/${PAGES.AUTH_WALLET_PASSWORD}`} component={SignInWalletPasswordPage} />
2019-11-07 20:39:22 +01:00
<Route path={`/$/${PAGES.EMBED}/:claimName`} exact component={EmbedWrapperPage} />
<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="/*" component={FourOhFourPage} />
</Switch>
2019-11-07 20:39:22 +01:00
);
}
export default withRouter(AppRouter);