Fix everything I broke (I hope) - Use react-router #2408

Merged
neb-b merged 1 commit from routing-fixes into master 2019-04-04 23:14:05 +02:00
39 changed files with 352 additions and 350 deletions

View file

@ -59,7 +59,6 @@
"@hot-loader/react-dom": "16.8",
"@lbry/color": "^1.0.2",
"@lbry/components": "^2.3.3",
"@reach/router": "^1.2.1",
"@types/three": "^0.93.1",
"async-exit-hook": "^2.0.1",
"babel-eslint": "^10.0.1",
@ -70,6 +69,7 @@
"chalk": "^2.4.2",
"classnames": "^2.2.5",
"codemirror": "^5.39.2",
"connected-react-router": "^6.3.2",
"copy-webpack-plugin": "^4.6.0",
"country-data": "^0.0.31",
"cross-env": "^5.2.0",
@ -104,6 +104,7 @@
"flow-typed": "^2.3.0",
"formik": "^0.10.4",
"hast-util-sanitize": "^1.1.2",
"history": "^4.9.0",
"husky": "^0.14.3",
"json-loader": "^0.5.4",
"lbry-format": "https://github.com/lbryio/lbry-format.git",
@ -134,7 +135,8 @@
"react-modal": "^3.1.7",
"react-paginate": "^5.2.1",
"react-pose": "^4.0.5",
"react-redux": "^5.0.3",
"react-redux": "^6.0.1",
"react-router-dom": "^5.0.0",
"react-simplemde-editor": "^4.0.0",
"react-toggle": "^4.0.2",
"react-virtualized": "^9.21.0",

View file

@ -1,7 +1,6 @@
// @flow
import { Lbryio } from 'lbryinc';
import ReactGA from 'react-ga';
import { globalHistory } from '@reach/router';
neb-b commented 2019-04-04 22:41:39 +02:00 (Migrated from github.com)
Review

Will add back analytics stuff in another PR. They were busted anyway. Just want to get this in.

Will add back analytics stuff in another PR. They were busted anyway. Just want to get this in.
type Analytics = {
pageView: string => void,
@ -15,7 +14,7 @@ let analyticsEnabled: boolean = true;
const analytics: Analytics = {
pageView: path => {
if (analyticsEnabled) {
ReactGA.pageview(path);
// ReactGA.pageview(path);
}
},
setUser: user => {
@ -72,19 +71,19 @@ const analytics: Analytics = {
// Initialize google analytics
// Set `debug: true` for debug info
ReactGA.initialize('UA-60403362-12', {
gaOptions: { name: IS_WEB ? 'web' : 'desktop' },
testMode: process.env.NODE_ENV !== 'production',
});
// ReactGA.initialize('UA-60403362-12', {
// gaOptions: { name: IS_WEB ? 'web' : 'desktop' },
// testMode: process.env.NODE_ENV !== 'production',
// });
// Manually call the first page view
// Reach Router doesn't include this on `history.listen`
analytics.pageView(window.location.pathname + window.location.search);
// analytics.pageView(window.location.pathname + window.location.search);
// Listen for url changes and report
// This will include search queries/filter options
globalHistory.listen(({ location }) =>
analytics.pageView(window.location.pathname + window.location.search)
);
// globalHistory.listen(({ location }) =>
// analytics.pageView(window.location.pathname + window.location.search)
// );
export default analytics;

View file

@ -1,4 +1,4 @@
import store from 'store';
import { store } from 'store';
const env = process.env.NODE_ENV || 'production';

View file

@ -3,7 +3,6 @@ import React from 'react';
import Router from 'component/router/index';
import ModalRouter from 'modal/modalRouter';
import ReactModal from 'react-modal';
import throttle from 'util/throttle';
import SideBar from 'component/sideBar';
import Header from 'component/header';
import { openContextMenu } from 'util/context-menu';

View file

@ -2,7 +2,7 @@
import * as React from 'react';
import Icon from 'component/common/icon';
import classnames from 'classnames';
import { Link } from '@reach/router';
import { NavLink } from 'react-router-dom';
import { formatLbryUriForWeb } from 'util/uri';
import { OutboundLink } from 'react-ga';
@ -109,19 +109,16 @@ class Button extends React.PureComponent<Props> {
}
return path ? (
<Link
<NavLink
exact
to={path}
title={title}
onClick={e => e.stopPropagation()}
getProps={({ isCurrent, isPartiallyCurrent }) => ({
className:
(path === '/' ? isCurrent : isPartiallyCurrent) && activeClass
? `${combinedClassName} ${activeClass}`
: combinedClassName,
})}
className={combinedClassName}
activeClassName={activeClass}
>
{content}
</Link>
</NavLink>
) : (
<button
title={title}

View file

@ -5,7 +5,7 @@ import TruncatedText from 'component/common/truncated-text';
import classnames from 'classnames';
import SubscribeButton from 'component/subscribeButton';
import type { Claim } from 'types/claim';
import { navigate } from '@reach/router';
import { withRouter } from 'react-router-dom';
import { formatLbryUriForWeb } from 'util/uri';
type Props = {
@ -15,6 +15,7 @@ type Props = {
size: string,
claim: ?Claim,
resolveUri: string => void,
history: { push: string => void },
};
class ChannelTile extends React.PureComponent<Props> {
@ -37,7 +38,7 @@ class ChannelTile extends React.PureComponent<Props> {
}
render() {
const { claim, isResolvingUri, totalItems, uri, size } = this.props;
const { claim, isResolvingUri, totalItems, uri, size, history } = this.props;
let channelName;
let subscriptionUri;
@ -46,7 +47,7 @@ class ChannelTile extends React.PureComponent<Props> {
subscriptionUri = `lbry://${claim.permanent_url}`;
}
const onClick = () => navigate(formatLbryUriForWeb(uri));
const onClick = () => history.push(formatLbryUriForWeb(uri));
return (
<section
@ -86,4 +87,4 @@ class ChannelTile extends React.PureComponent<Props> {
}
}
export default ChannelTile;
export default withRouter(ChannelTile);

View file

@ -4,13 +4,11 @@ import * as ICONS from 'constants/icons';
import * as React from 'react';
import { isURIValid } from 'lbry-redux';
import Button from 'component/button';
import { navigate } from '@reach/router';
type Props = {
href: string,
title?: string,
children: React.Node,
navigate: (string, ?{}) => void,
openModal: (id: string, { uri: string }) => void,
};
@ -21,7 +19,7 @@ class ExternalLink extends React.PureComponent<Props> {
};
createLink() {
const { href, title, children, openModal, navigate } = this.props;
const { href, title, children, openModal } = this.props;
// Regex for url protocol
const protocolRegex = new RegExp('^(https?|lbry)+:', 'i');

View file

@ -11,7 +11,7 @@ import classnames from 'classnames';
import FilePrice from 'component/filePrice';
import { openCopyLinkMenu } from 'util/context-menu';
import DateTime from 'component/dateTime';
import { navigate } from '@reach/router';
import { withRouter } from 'react-router-dom';
import { formatLbryUriForWeb } from 'util/uri';
type Props = {
@ -29,6 +29,7 @@ type Props = {
isNew: boolean,
placeholder: boolean,
preventResolve: boolean,
history: { push: string => void },
};
class FileCard extends React.PureComponent<Props> {
@ -70,6 +71,7 @@ class FileCard extends React.PureComponent<Props> {
isNew,
isResolvingUri,
placeholder,
history,
} = this.props;
const abandoned = !isResolvingUri && !claim && !pending && !placeholder;
@ -110,7 +112,7 @@ class FileCard extends React.PureComponent<Props> {
const onClick = e => {
e.stopPropagation();
navigate(formatLbryUriForWeb(uri));
history.push(formatLbryUriForWeb(uri));
};
return (
@ -147,4 +149,4 @@ class FileCard extends React.PureComponent<Props> {
}
}
export default FileCard;
export default withRouter(FileCard);

View file

@ -12,7 +12,7 @@ import FilePrice from 'component/filePrice';
import UriIndicator from 'component/uriIndicator';
import DateTime from 'component/dateTime';
import Yrbl from 'component/yrbl';
import { navigate } from '@reach/router';
import { withRouter } from 'react-router-dom';
import { formatLbryUriForWeb } from 'util/uri';
type Props = {
@ -32,6 +32,7 @@ type Props = {
size: string,
isSubscribed: boolean,
isNew: boolean,
history: { push: string => void },
};
class FileTile extends React.PureComponent<Props> {
@ -91,6 +92,7 @@ class FileTile extends React.PureComponent<Props> {
hideNoResult,
displayHiddenMessage,
size,
history,
} = this.props;
if (!claim && isResolvingUri) {
@ -136,7 +138,7 @@ class FileTile extends React.PureComponent<Props> {
const wrapperProps = name
? {
onClick: () => navigate(formatLbryUriForWeb(uri)),
onClick: () => history.push(formatLbryUriForWeb(uri)),
role: 'button',
}
: {};
@ -209,7 +211,7 @@ class FileTile extends React.PureComponent<Props> {
clearPublish(); // to remove any existing publish data
updatePublishForm({ name: claimName }); // to populate the name
navigate('/publish');
history.push('/publish');
}}
/>
}
@ -221,4 +223,4 @@ class FileTile extends React.PureComponent<Props> {
}
}
export default FileTile;
export default withRouter(FileTile);

View file

@ -88,7 +88,7 @@ const Header = (props: Props) => {
{roundedBalance} <LbcSymbol />
</React.Fragment>
}
navigate="/$/wallet"
navigate="/$/account"
/>
<Button

View file

@ -11,7 +11,7 @@ const select = (state, props) => {
return {
page,
pageCount: selectHistoryPageCount(state),
history: makeSelectHistoryForPage(page)(state),
historyItems: makeSelectHistoryForPage(page)(state),
};
};

View file

@ -4,7 +4,7 @@ import Button from 'component/button';
import { Form, FormField } from 'component/common/form';
import ReactPaginate from 'react-paginate';
import NavigationHistoryItem from 'component/navigationHistoryItem';
import { navigate } from '@reach/router';
import { withRouter } from 'react-router-dom';
type HistoryItem = {
uri: string,
@ -12,11 +12,12 @@ type HistoryItem = {
};
type Props = {
history: Array<HistoryItem>,
historyItems: Array<HistoryItem>,
page: number,
pageCount: number,
clearHistoryUri: string => void,
params: { page: number },
history: { push: string => void },
};
type State = {
@ -52,7 +53,8 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
}
changePage(pageNumber: number) {
navigate(`?page=${pageNumber}`);
const { history } = this.props;
history.push(`?page=${pageNumber}`);
}
paginate(e: SyntheticKeyboardEvent<*>) {
@ -69,9 +71,9 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
}
selectAll() {
const { history } = this.props;
const { historyItems } = this.props;
const newSelectedState = {};
history.forEach(({ uri }) => (newSelectedState[uri] = true));
historyItems.forEach(({ uri }) => (newSelectedState[uri] = true));
this.setState({ itemsSelected: newSelectedState });
}
@ -92,7 +94,7 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
}
render() {
const { history = [], page, pageCount } = this.props;
const { historyItems = [], page, pageCount } = this.props;
const { itemsSelected } = this.state;
const allSelected = Object.keys(itemsSelected).length === history.length;
const selectHandler = allSelected ? this.unselectAll : this.selectAll;
@ -113,9 +115,9 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
onClick={selectHandler}
/>
</div>
{!!history.length && (
{!!historyItems.length && (
<section className="card__content item-list">
{history.map(item => (
{historyItems.map(item => (
<NavigationHistoryItem
key={item.uri}
uri={item.uri}
@ -182,4 +184,4 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
);
}
}
export default UserHistoryPage;
export default withRouter(UserHistoryPage);

View file

@ -5,7 +5,7 @@ import moment from 'moment';
import classnames from 'classnames';
import Button from 'component/button';
import { FormField } from 'component/common/form';
import { navigate } from '@reach/router';
import { withRouter } from 'react-router-dom';
import { formatLbryUriForWeb } from 'util/uri';
type Props = {
@ -16,6 +16,7 @@ type Props = {
onSelect?: () => void,
resolveUri: string => void,
slim: boolean,
history: { push: string => void },
};
class NavigationHistoryItem extends React.PureComponent<Props> {
@ -32,7 +33,7 @@ class NavigationHistoryItem extends React.PureComponent<Props> {
}
render() {
const { lastViewed, selected, onSelect, claim, uri, slim } = this.props;
const { lastViewed, selected, onSelect, claim, uri, slim, history } = this.props;
let name;
let title;
@ -45,7 +46,7 @@ class NavigationHistoryItem extends React.PureComponent<Props> {
const onClick =
onSelect ||
function() {
navigate(navigatePath);
history.push(navigatePath);
};
return (
@ -65,4 +66,4 @@ class NavigationHistoryItem extends React.PureComponent<Props> {
}
}
export default NavigationHistoryItem;
export default withRouter(NavigationHistoryItem);

View file

@ -4,7 +4,6 @@ import Button from 'component/button';
import { Form, FormField } from 'component/common/form';
import ReactPaginate from 'react-paginate';
import NavigationHistoryItem from 'component/navigationHistoryItem';
import { navigate } from '@reach/router';
type HistoryItem = {
uri: string,

View file

@ -1,6 +1,6 @@
import * as PAGES from 'constants/pages';
import React, { useEffect } from 'react';
import { Router } from '@reach/router';
import { Route, Switch } from 'react-router-dom';
import SettingsPage from 'page/settings';
import HelpPage from 'page/help';
import ReportPage from 'page/report';
@ -21,49 +21,32 @@ import UserHistoryPage from 'page/userHistory';
import SendCreditsPage from 'page/sendCredits';
import NavigationHistory from 'page/navigationHistory';
const ScrollHandler = props => {
const { key } = props.location;
useEffect(() => {
// This shouldn't scroll to top when you click "back"
// Might take some more work but fixes scroll position being stuck on navigation for now
const main = document.querySelector('main');
if (main) {
main.scrollIntoView();
}
}, [key]);
return props.children;
};
export default function AppRouter() {
return (
<Router>
<ScrollHandler path="/">
<DiscoverPage path="/" />
<ShowPage path="/:claimName/:claimId" />
<ShowPage path="/:claimName" />
{/* <ShowPage path="/" uri="five" /> */}
<Switch>
<Route path="/" exact component={DiscoverPage} />
<Route path={`/$/${PAGES.AUTH}`} exact component={AuthPage} />
<Route path={`/$/${PAGES.BACKUP}`} exact component={BackupPage} />
<Route path={`/$/${PAGES.INVITE}`} exact component={InvitePage} />
<Route path={`/$/${PAGES.DOWNLOADED}`} exact component={FileListDownloaded} />
<Route path={`/$/${PAGES.PUBLISHED}`} exact component={FileListPublished} />
neb-b commented 2019-04-04 22:43:51 +02:00 (Migrated from github.com)
Review

Will add this back later, it will be a little different with react-router

Will add this back later, it will be a little different with react-router
<Route path={`/$/${PAGES.HELP}`} exact component={HelpPage} />
<Route path={`/$/${PAGES.PUBLISH}`} exact component={PublishPage} />
<Route path={`/$/${PAGES.REPORT}`} exact component={ReportPage} />
<Route path={`/$/${PAGES.REWARDS}`} exact component={RewardsPage} />
<Route path={`/$/${PAGES.SEARCH}`} exact component={SearchPage} />
<Route path={`/$/${PAGES.SETTINGS}`} exact component={SettingsPage} />
<Route path={`/$/${PAGES.SUBSCRIPTIONS}`} exact component={SubscriptionsPage} />
<Route path={`/$/${PAGES.TRANSACTIONS}`} exact component={TransactionHistoryPage} />
<Route path={`/$/${PAGES.HISTORY}`} exact component={UserHistoryPage} />
<Route path={`/$/${PAGES.ACCOUNT}`} exact component={AccountPage} />
<Route path={`/$/${PAGES.SEND}`} exact component={SendCreditsPage} />
<Route path={`/$/${PAGES.HISTORY}`} exact component={UserHistoryPage} />
<Route path={`/$/${PAGES.HISTORY}/all`} exact component={NavigationHistory} />
<AuthPage path={`$/${PAGES.AUTH}`} />
<BackupPage path={`$/${PAGES.BACKUP}`} />
<InvitePage path={`$/${PAGES.INVITE}`} />
<FileListDownloaded path={`$/${PAGES.DOWNLOADED}`} />
<FileListPublished path={`$/${PAGES.PUBLISHED}`} />
<HelpPage path={`$/${PAGES.HELP}`} />
<PublishPage path={`$/${PAGES.PUBLISH}`} />
<ReportPage path={`$/${PAGES.REPORT}`} />
<RewardsPage path={`$/${PAGES.REWARDS}`} />
<SearchPage path={`$/${PAGES.SEARCH}`} />
<SettingsPage path={`$/${PAGES.SETTINGS}`} />
<SubscriptionsPage path={`$/${PAGES.SUBSCRIPTIONS}`} />
<TransactionHistoryPage path={`$/${PAGES.TRANSACTIONS}`} />
<UserHistoryPage path={`$/${PAGES.HISTORY}`} />
<AccountPage path={`$/${PAGES.ACCOUNT}`} />
<SendCreditsPage path={`$/${PAGES.SEND}`} />
<UserHistoryPage path={`$/${PAGES.HISTORY}`} />
<NavigationHistory path={`$/${PAGES.HISTORY}/all`} />
</ScrollHandler>
</Router>
{/* Below need to go at the end to make sure we don't match any of our pages first */}
<Route path="/:claimName/:claimId" component={ShowPage} />
<Route path="/:claimName" component={ShowPage} />
</Switch>
);
}

View file

@ -11,7 +11,7 @@ import {
} from 'lbry-redux';
import analytics from 'analytics';
import Wunderbar from './view';
import { navigate } from '@reach/router';
import { withRouter } from 'react-router-dom';
import { formatLbryUriForWeb } from 'util/uri';
const select = state => ({
@ -20,14 +20,14 @@ const select = state => ({
isFocused: selectSearchBarFocused(state),
});
const perform = dispatch => ({
const perform = (dispatch, ownProps) => ({
onSearch: query => {
navigate(`/$/search?q=${query}`);
ownProps.history.push({ pathname: `/$/search`, search: `?q=${query}` });
analytics.apiLogSearch();
},
onSubmit: uri => {
const path = formatLbryUriForWeb(uri);
navigate(path);
ownProps.history.push(path);
dispatch(doUpdateSearchQuery(''));
},
updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)),
@ -35,7 +35,9 @@ const perform = dispatch => ({
doBlur: () => dispatch(doBlurSearchInput()),
});
export default connect(
select,
perform
)(Wunderbar);
export default withRouter(
connect(
select,
perform
)(Wunderbar)
);

View file

@ -7,7 +7,6 @@ import { normalizeURI, SEARCH_TYPES, isURIValid, buildURI } from 'lbry-redux';
import Icon from 'component/common/icon';
import { parseQueryParams } from 'util/query-params';
import Autocomplete from './internal/autocomplete';
import { Location, navigate } from '@reach/router';
const L_KEY_CODE = 76;
const ESC_KEY_CODE = 27;

View file

@ -22,11 +22,12 @@ import { Lbry, doToast, isURIValid, setSearchApi } from 'lbry-redux';
import { doDownloadLanguages, doUpdateIsNightAsync } from 'redux/actions/settings';
import { doAuthenticate, Lbryio, rewards, doBlackListedOutpointsSubscribe } from 'lbryinc';
import 'scss/all.scss';
import store from 'store';
import { store, history } from 'store';
import pjson from 'package.json';
import app from './app';
import analytics from './analytics';
import doLogWarningConsoleMessage from './logWarningConsoleMessage';
import { ConnectedRouter } from 'connected-react-router';
const APPPAGEURL = 'lbry://?';
@ -219,10 +220,12 @@ const init = () => {
app.store.dispatch(doDaemonReady());
ReactDOM.render(
<Provider store={store}>
<ErrorBoundary>
<App />
<SnackBar />
</ErrorBoundary>
<ConnectedRouter history={history}>
<ErrorBoundary>
<App />
<SnackBar />
</ErrorBoundary>
</ConnectedRouter>
</Provider>,
document.getElementById('app')
);

View file

@ -1,7 +1,6 @@
import { connect } from 'react-redux';
import { doHideModal } from 'redux/actions/app';
import { selectPhoneToVerify, selectUser } from 'lbryinc';
import { navigate } from '@reach/router';
import ModalPhoneCollection from './view';
const select = state => ({
@ -10,10 +9,7 @@ const select = state => ({
});
const perform = dispatch => () => ({
closeModal: () => {
dispatch(doHideModal());
navigate('/$/rewards');
},
closeModal: () => dispatch(doHideModal()),
});
export default connect(

View file

@ -4,6 +4,7 @@ import { Modal } from 'modal/modal';
import Button from 'component/button';
import UserPhoneNew from 'component/userPhoneNew';
import UserPhoneVerify from 'component/userPhoneVerify';
import { withRouter } from 'react-router-dom';
type Props = {
phone: ?number,
@ -11,6 +12,7 @@ type Props = {
phone_number: ?number,
},
closeModal: () => void,
history: { push: string => void },
};
class ModalPhoneCollection extends React.PureComponent<Props> {
@ -24,7 +26,7 @@ class ModalPhoneCollection extends React.PureComponent<Props> {
}
renderInner() {
const { closeModal, phone, user } = this.props;
const { closeModal, phone, user, history } = this.props;
const cancelButton = <Button button="link" onClick={closeModal} label={__('Not Now')} />;
@ -33,6 +35,8 @@ class ModalPhoneCollection extends React.PureComponent<Props> {
} else if (!user.phone_number) {
return <UserPhoneVerify cancelButton={cancelButton} />;
}
history.push('/$/rewards');
return closeModal();
}
@ -52,4 +56,4 @@ class ModalPhoneCollection extends React.PureComponent<Props> {
}
}
export default ModalPhoneCollection;
export default withRouter(ModalPhoneCollection);

View file

@ -1,12 +1,11 @@
import { connect } from 'react-redux';
import { doHideModal } from 'redux/actions/app';
import { doAuthNavigate } from 'redux/actions/navigation';
import ModalRewardApprovalRequired from './view';
const perform = dispatch => ({
doAuth: () => {
dispatch(doHideModal());
dispatch(doAuthNavigate());
// dispatch(doAuthNavigate());
},
closeModal: () => dispatch(doHideModal()),
});

View file

@ -7,13 +7,13 @@ import UserEmailNew from 'component/userEmailNew';
import UserEmailVerify from 'component/userEmailVerify';
import UserVerify from 'component/userVerify';
import Page from 'component/page';
import { navigate } from '@reach/router';
type Props = {
isPending: boolean,
email: string,
pathAfterAuth: string,
location: UrlLocation,
history: { push: string => void },
user: ?{
has_verified_email: boolean,
is_reward_approved: boolean,
@ -31,7 +31,7 @@ class AuthPage extends React.PureComponent<Props> {
}
navigateIfAuthenticated = (props: Props) => {
const { isPending, user, location } = props;
const { isPending, user, location, history } = props;
if (
!isPending &&
user &&
@ -42,7 +42,7 @@ class AuthPage extends React.PureComponent<Props> {
const urlParams = new URLSearchParams(search);
const redirectTo = urlParams.get('redirect');
const path = redirectTo ? `/$/${redirectTo}` : '/';
navigate(path);
history.push(path);
}
};

View file

@ -12,7 +12,7 @@ import Page from 'component/page';
import FileList from 'component/fileList';
import HiddenNsfwClaims from 'component/hiddenNsfwClaims';
import Button from 'component/button';
import { navigate } from '@reach/router';
import { withRouter } from 'react-router-dom';
type Props = {
uri: string,
@ -23,7 +23,7 @@ type Props = {
claimsInChannel: Array<Claim>,
channelIsMine: boolean,
fetchClaims: (string, number) => void,
navigate: (string, {}) => void,
history: { push: string => void },
openModal: (id: string, { uri: string }) => void,
location: UrlLocation,
};
@ -39,6 +39,7 @@ function ChannelPage(props: Props) {
openModal,
fetchClaims,
location,
history,
} = props;
const { name, permanent_url: permanentUrl } = claim;
@ -56,7 +57,7 @@ function ChannelPage(props: Props) {
return;
}
navigate(`?page=${pageNumber}`);
history.push(`?page=${pageNumber}`);
};
const paginate = (e: SyntheticKeyboardEvent<*>) => {
@ -143,4 +144,4 @@ function ChannelPage(props: Props) {
);
}
export default ChannelPage;
export default withRouter(ChannelPage);

View file

@ -1,5 +1,4 @@
import { connect } from 'react-redux';
import { doAuthNavigate } from 'redux/actions/navigation';
import { doFetchAccessToken, selectAccessToken, selectUser } from 'lbryinc';
import { selectDaemonSettings } from 'redux/selectors/settings';
import HelpPage from './view';
@ -11,7 +10,7 @@ const select = state => ({
});
const perform = dispatch => ({
doAuth: () => dispatch(doAuthNavigate('/help')),
// doAuth: () => dispatch(doAuthNavigate('/help')),
fetchAccessToken: () => dispatch(doFetchAccessToken()),
});

View file

@ -1,3 +1,3 @@
import UserHistoryPage from './view';
import NavigationHistoryPage from './view';
export default UserHistoryPage;
export default NavigationHistoryPage;

View file

@ -6,7 +6,6 @@ import {
selectUser,
doRewardList,
} from 'lbryinc';
import { navigate } from '@reach/router';
import { selectDaemonSettings } from 'redux/selectors/settings';
import RewardsPage from './view';
@ -20,9 +19,6 @@ const select = state => ({
const perform = dispatch => ({
fetchRewards: () => dispatch(doRewardList()),
doAuth: () => {
navigate('/$/auth?redirect=rewards');
},
});
export default connect(

View file

@ -27,7 +27,7 @@ type Props = {
class RewardsPage extends PureComponent<Props> {
renderPageHeader() {
const { doAuth, user, daemonSettings } = this.props;
const { user, daemonSettings } = this.props;
if (user && !user.is_reward_approved && daemonSettings && daemonSettings.share_usage_data) {
if (!user.primary_email || !user.has_verified_email || !user.is_identity_verified) {
@ -42,7 +42,7 @@ class RewardsPage extends PureComponent<Props> {
</header>
<div className="card__content">
<Button onClick={doAuth} button="primary" label="Prove Humanity" />
<Button navigate="/$/auth?redirect=rewards" button="primary" label="Prove Humanity" />
</div>
</section>
);

View file

@ -10,7 +10,6 @@ import Page from 'component/page';
import ToolTip from 'component/common/tooltip';
import Icon from 'component/common/icon';
import SearchOptions from 'component/searchOptions';
import { Location } from '@reach/router';
type Props = { doSearch: string => void, location: UrlLocation };
@ -19,9 +18,17 @@ export default function SearchPage(props: Props) {
doSearch,
location: { search },
} = props;
const urlParams = new URLSearchParams(location.search);
const urlParams = new URLSearchParams(search);
const urlQuery = urlParams.get('q');
const isValid = isURIValid(urlQuery);
let uri;
let isChannel;
let label;
if (isValid) {
uri = normalizeURI(urlQuery);
({ isChannel } = parseURI(uri));
}
useEffect(() => {
if (urlQuery) {
@ -31,67 +38,33 @@ export default function SearchPage(props: Props) {
return (
<Page noPadding>
<Location>
{(locationProps: {
location: {
search: string,
},
}) => {
const { location } = locationProps;
const urlParams = new URLSearchParams(location.search);
const query = urlParams.get('q');
const isValid = isURIValid(query);
let uri;
let isChannel;
let label;
if (isValid) {
uri = normalizeURI(query);
({ isChannel } = parseURI(uri));
// label = (
// <Fragment>
// {`lbry://${query}`}
// <ToolTip
// icon
// body={__('This is the resolution of a LBRY URL and not controlled by LBRY Inc.')}
// >
// <Icon icon={ICONS.HELP} />
// </ToolTip>
// </Fragment>
// );
}
return (
<section className="search">
{query && (
<section className="search">
{urlQuery && (
<Fragment>
<header className="search__header">
{isValid && (
<Fragment>
<header className="search__header">
{isValid && (
<Fragment>
<SearchOptions />
<SearchOptions />
<h1 className="media__uri">{uri}</h1>
{isChannel ? (
<ChannelTile size="large" isSearchResult uri={uri} />
) : (
<FileTile size="large" isSearchResult displayHiddenMessage uri={uri} />
)}
</Fragment>
)}
</header>
<div className="search__results-wrapper">
<FileListSearch query={query} />
<div className="card__content help">
{__('These search results are provided by LBRY, Inc.')}
</div>
</div>
<h1 className="media__uri">{uri}</h1>
{isChannel ? (
<ChannelTile size="large" isSearchResult uri={uri} />
) : (
<FileTile size="large" isSearchResult displayHiddenMessage uri={uri} />
)}
</Fragment>
)}
</section>
);
}}
</Location>
</header>
<div className="search__results-wrapper">
<FileListSearch query={urlQuery} />
<div className="card__content help">
{__('These search results are provided by LBRY, Inc.')}
</div>
</div>
</Fragment>
)}
</section>
</Page>
);
}

View file

@ -11,8 +11,14 @@ import { selectBlackListedOutpoints } from 'lbryinc';
import ShowPage from './view';
const select = (state, props) => {
const { pathname } = props.location;
const urlParts = pathname.split('/');
const claimName = urlParts[1];
const claimId = urlParts[2];
// claimName and claimId come from the url `lbry.tv/{claimName}/{claimId}"
const uri = buildURI({ contentName: props.claimName, claimId: props.claimId });
const uri = buildURI({ contentName: claimName, claimId: claimId });
return {
claim: makeSelectClaimForUri(uri)(state),
isResolvingUri: makeSelectIsUriResolving(uri)(state),

45
src/ui/reducers.js Normal file
View file

@ -0,0 +1,45 @@
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
import {
claimsReducer,
fileInfoReducer,
searchReducer,
walletReducer,
notificationsReducer,
} from 'lbry-redux';
import {
userReducer,
rewardsReducer,
costInfoReducer,
blacklistReducer,
homepageReducer,
statsReducer,
} from 'lbryinc';
import appReducer from 'redux/reducers/app';
import availabilityReducer from 'redux/reducers/availability';
import contentReducer from 'redux/reducers/content';
import settingsReducer from 'redux/reducers/settings';
import subscriptionsReducer from 'redux/reducers/subscriptions';
import publishReducer from 'redux/reducers/publish';
export default history =>
combineReducers({
router: connectRouter(history),
app: appReducer,
availability: availabilityReducer,
blacklist: blacklistReducer,
claims: claimsReducer,
content: contentReducer,
costInfo: costInfoReducer,
fileInfo: fileInfoReducer,
homepage: homepageReducer,
notifications: notificationsReducer,
publish: publishReducer,
rewards: rewardsReducer,
search: searchReducer,
settings: settingsReducer,
stats: statsReducer,
subscriptions: subscriptionsReducer,
user: userReducer,
wallet: walletReducer,
});

View file

@ -4,13 +4,11 @@ import isDev from 'electron-is-dev';
import { ipcRenderer, remote } from 'electron';
// @endif
import path from 'path';
import * as ACTIONS from 'constants/action_types';
import * as MODALS from 'constants/modal_types';
import { Lbry, doBalanceSubscribe, doFetchFileInfosAndPublishedClaims, doError } from 'lbry-redux';
import Native from 'native';
import { doFetchDaemonSettings } from 'redux/actions/settings';
import { doAuthNavigate } from 'redux/actions/navigation';
import { doCheckSubscriptionsInit } from 'redux/actions/subscriptions';
import {
selectIsUpgradeSkipped,
@ -390,7 +388,7 @@ export function doConditionalAuthNavigate(newSession) {
const modal = selectModal(state);
if (newSession || (modal && modal.id !== MODALS.EMAIL_COLLECTION)) {
dispatch(doAuthNavigate());
// dispatch(doAuthNavigate());
}
};
}

View file

@ -7,7 +7,7 @@ import * as MODALS from 'constants/modal_types';
import { ipcRenderer } from 'electron';
// @endif
import { doOpenModal } from 'redux/actions/app';
import { navigate } from '@reach/router';
import { push } from 'connected-react-router';
import { setSubscriptionLatest, doUpdateUnreadSubscriptions } from 'redux/actions/subscriptions';
import { makeSelectUnreadByChannel } from 'redux/selectors/subscriptions';
import {
@ -83,7 +83,7 @@ export function doUpdateLoadStatus(uri: string, outpoint: string) {
silent: false,
});
notif.onclick = () => {
navigate(formatLbryUriForWeb(uri));
dispatch(push(formatLbryUriForWeb(uri)));
};
}

View file

@ -21,7 +21,7 @@ import {
} from 'lbry-redux';
import { doOpenModal } from 'redux/actions/app';
import { selectosNotificationsEnabled } from 'redux/selectors/settings';
import { navigate } from '@reach/router';
import { push } from 'connected-react-router';
import analytics from 'analytics';
import { formatLbryUriForWeb } from 'util/uri';
// @if TARGET='app'
@ -328,7 +328,7 @@ export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetS
silent: false,
});
notif.onclick = () => {
navigate(formatLbryUriForWeb(claim.permanent_url));
dispatch(push(formatLbryUriForWeb(claim.permanent_url)));
};
}
}

View file

@ -1,72 +0,0 @@
import * as ACTIONS from 'constants/action_types';
const getCurrentPath = () => {
const { hash } = document.location;
if (hash !== '') return hash.replace(/^#/, '');
return '/discover';
};
const reducers = {};
const defaultState = {
currentPath: getCurrentPath(),
pathAfterAuth: '/discover',
index: 0,
stack: [],
};
reducers[ACTIONS.DAEMON_READY] = state => {
const { currentPath } = state;
return Object.assign({}, state, {
stack: [{ path: currentPath, scrollY: 0 }],
});
};
reducers[ACTIONS.CHANGE_AFTER_AUTH_PATH] = (state, action) =>
Object.assign({}, state, {
pathAfterAuth: action.data.path,
});
reducers[ACTIONS.HISTORY_NAVIGATE] = (state, action) => {
const { stack, index } = state;
const { url: path, index: newIndex } = action.data;
const newState = {
currentPath: path,
};
if (newIndex >= 0) {
newState.index = newIndex;
} else if (!stack[index] || stack[index].path !== path) {
// ^ Check for duplicated
newState.stack = [...stack.slice(0, index + 1), { path, scrollY: 0 }];
newState.index = newState.stack.length - 1;
}
return Object.assign({}, state, newState);
};
reducers[ACTIONS.WINDOW_SCROLLED] = (state, action) => {
const { index } = state;
const { scrollY } = action.data;
return Object.assign({}, state, {
stack: state.stack.map((stackItem, itemIndex) => {
if (itemIndex !== index) {
return stackItem;
}
return {
...stackItem,
scrollY,
};
}),
});
};
export default function reducer(state = defaultState, action) {
const handler = reducers[action.type];
if (handler) {
return handler(state, action);
}
return state;
}

View file

@ -1,31 +1,12 @@
import appReducer from 'redux/reducers/app';
import availabilityReducer from 'redux/reducers/availability';
import contentReducer from 'redux/reducers/content';
import {
claimsReducer,
fileInfoReducer,
searchReducer,
walletReducer,
notificationsReducer,
} from 'lbry-redux';
import {
userReducer,
rewardsReducer,
costInfoReducer,
blacklistReducer,
homepageReducer,
statsReducer,
} from 'lbryinc';
import navigationReducer from 'redux/reducers/navigation';
import settingsReducer from 'redux/reducers/settings';
import subscriptionsReducer from 'redux/reducers/subscriptions';
import publishReducer from 'redux/reducers/publish';
import { persistStore, autoRehydrate } from 'redux-persist';
import createCompressor from 'redux-persist-transform-compress';
import createFilter from 'redux-persist-transform-filter';
import localForage from 'localforage';
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { createHashHistory, createBrowserHistory } from 'history';
import { connectRouter, routerMiddleware } from 'connected-react-router';
import createRootReducer from './reducers';
function isFunction(object) {
return typeof object === 'function';
@ -55,34 +36,18 @@ function enableBatching(reducer) {
};
}
const reducers = combineReducers({
app: appReducer,
navigation: navigationReducer,
availability: availabilityReducer,
claims: claimsReducer,
fileInfo: fileInfoReducer,
content: contentReducer,
costInfo: costInfoReducer,
rewards: rewardsReducer,
search: searchReducer,
settings: settingsReducer,
wallet: walletReducer,
user: userReducer,
subscriptions: subscriptionsReducer,
publish: publishReducer,
notifications: notificationsReducer,
blacklist: blacklistReducer,
homepage: homepageReducer,
stats: statsReducer,
});
// @if TARGET='app'
const history = createHashHistory();
// @endif
// @if TARGET='web'
const history = createBrowserHistory();
// @endif
const bulkThunk = createBulkThunkMiddleware();
const middleware = [thunk, bulkThunk];
const middleware = [routerMiddleware(history), thunk, bulkThunk];
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
enableBatching(reducers),
enableBatching(createRootReducer(history)),
{}, // initial state
composeEnhancers(
autoRehydrate({
@ -126,4 +91,4 @@ window.cacheStore = persistStore(store, persistOptions, err => {
});
// @endif
export default store;
export { store, history };

View file

@ -7,6 +7,18 @@
<body>
<div id="app"></div>
<script type="text/javascript" src="ui.js"></script>
<script type="text/javascript">
// Use relative path if we are in electron
let src = 'ui.js';
const userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf('electron') === -1) {
src = `/${src}`;
}
const script = document.createElement('script');
script.setAttribute('src', src);
document.body.appendChild(script);
</script>
</body>
</html>

View file

@ -53,7 +53,7 @@ let baseConfig = {
use: {
loader: 'file-loader',
options: {
outputPath: '$/static/img',
outputPath: 'static/img',
name: '[name].[ext]',
},
},
@ -63,7 +63,7 @@ let baseConfig = {
use: {
loader: 'file-loader',
options: {
outputPath: '$/static/font',
outputPath: 'static/font',
},
},
},

139
yarn.lock
View file

@ -734,6 +734,13 @@
dependencies:
regenerator-runtime "^0.12.0"
"@babel/runtime@^7.3.1":
version "7.4.3"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.3.tgz#79888e452034223ad9609187a0ad1fe0d2ad4bdc"
integrity sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA==
dependencies:
regenerator-runtime "^0.13.2"
"@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2":
version "7.2.2"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907"
@ -850,17 +857,6 @@
resolved "https://registry.yarnpkg.com/@posthtml/esm/-/esm-1.0.0.tgz#09bcb28a02438dcee22ad1970ca1d85a000ae0cf"
integrity sha512-dEVG+ITnvqKGa4v040tP+n8LOKOqr94qjLva7bE5pnfm2KHJwsKz69J4KMxgWLznbpBJzy8vQfCayEk3vLZnZQ==
"@reach/router@^1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.2.1.tgz#34ae3541a5ac44fa7796e5506a5d7274a162be4e"
integrity sha512-kTaX08X4g27tzIFQGRukaHmNbtMYDS3LEWIS8+l6OayGIw6Oyo1HIF/JzeuR2FoF9z6oV+x/wJSVSq4v8tcUGQ==
dependencies:
create-react-context "^0.2.1"
invariant "^2.2.3"
prop-types "^15.6.1"
react-lifecycles-compat "^3.0.4"
warning "^3.0.0"
"@samverschueren/stream-to-observable@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f"
@ -2545,6 +2541,14 @@ connect-history-api-fallback@^1.3.0:
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
connected-react-router@^6.3.2:
version "6.3.2"
resolved "https://registry.yarnpkg.com/connected-react-router/-/connected-react-router-6.3.2.tgz#8c90b77f1d7b783608cd50e4f69bf60e47265425"
integrity sha512-YxrAfMExl/OBsi+ojA4ywZeC7cmQ52MnZ4bhzqLhhjuOiXcQogC4kW0kodouXAXrXDovb2l3yEhDfpH99/wYcw==
dependencies:
immutable "^3.8.1"
seamless-immutable "^7.1.3"
console-browserify@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10"
@ -2697,7 +2701,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
create-react-context@^0.2.1:
create-react-context@^0.2.2:
version "0.2.3"
resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.3.tgz#9ec140a6914a22ef04b8b09b7771de89567cb6f3"
integrity sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==
@ -5104,6 +5108,18 @@ highlight.js@^9.3.0:
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.6.tgz#72d4d8d779ec066af9a17cb14360c3def0aa57c4"
integrity sha512-zozTAWM1D6sozHo8kqhfYgsac+B+q0PmsjXeyDrYIHHcBN0zTVT66+s2GW1GZv7DbyaROdLXKdabwS/WqPyIdQ==
history@^4.9.0:
version "4.9.0"
resolved "https://registry.yarnpkg.com/history/-/history-4.9.0.tgz#84587c2068039ead8af769e9d6a6860a14fa1bca"
integrity sha512-H2DkjCjXf0Op9OAr6nJ56fcRkTSNrUiv41vNJ6IswJjif6wlpZK0BTfFbi7qK9dXLSYZxkq5lBsj3vUjlYBYZA==
dependencies:
"@babel/runtime" "^7.1.2"
loose-envify "^1.2.0"
resolve-pathname "^2.2.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
value-equal "^0.4.0"
hmac-drbg@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@ -5374,6 +5390,11 @@ immediate@~3.0.5:
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
immutable@^3.8.1:
version "3.8.2"
resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3"
integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=
import-fresh@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
@ -5495,7 +5516,7 @@ interpret@^1.0.0, interpret@^1.1.0:
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==
invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4:
invariant@^2.2.2, invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
@ -6510,7 +6531,7 @@ longest-streak@^2.0.1:
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e"
integrity sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.0, loose-envify@^1.4.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@ -7798,6 +7819,13 @@ path-to-regexp@0.1.7:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
path-to-regexp@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
integrity sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=
dependencies:
isarray "0.0.1"
path-type@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@ -8385,7 +8413,7 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@ -8641,7 +8669,12 @@ react-hot-loader@^4.7.2:
shallowequal "^1.0.2"
source-map "^0.7.3"
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
react-is@^16.6.0, react-is@^16.8.2:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
react-is@^16.7.0, react-is@^16.8.1:
version "16.8.3"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.3.tgz#4ad8b029c2a718fc0cfc746c8d4e1b7221e5387d"
integrity sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA==
@ -8678,18 +8711,46 @@ react-pose@^4.0.5:
popmotion-pose "^3.4.0"
tslib "^1.9.1"
react-redux@^5.0.3:
version "5.1.1"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.1.1.tgz#88e368682c7fa80e34e055cd7ac56f5936b0f52f"
integrity sha512-LE7Ned+cv5qe7tMV5BPYkGQ5Lpg8gzgItK07c67yHvJ8t0iaD9kPFPAli/mYkiyJYrs2pJgExR2ZgsGqlrOApg==
react-redux@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-6.0.1.tgz#0d423e2c1cb10ada87293d47e7de7c329623ba4d"
integrity sha512-T52I52Kxhbqy/6TEfBv85rQSDz6+Y28V/pf52vDWs1YRXG19mcFOGfHnY2HsNFHyhP+ST34Aih98fvt6tqwVcQ==
dependencies:
"@babel/runtime" "^7.3.1"
hoist-non-react-statics "^3.3.0"
invariant "^2.2.4"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^16.8.2"
react-router-dom@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.0.tgz#542a9b86af269a37f0b87218c4c25ea8dcf0c073"
integrity sha512-wSpja5g9kh5dIteZT3tUoggjnsa+TPFHSMrpHXMpFsaHhQkm/JNVGh2jiF9Dkh4+duj4MKCkwO6H08u6inZYgQ==
dependencies:
"@babel/runtime" "^7.1.2"
history "^4.9.0"
loose-envify "^1.3.1"
prop-types "^15.6.2"
react-router "5.0.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-router@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.0.0.tgz#349863f769ffc2fa10ee7331a4296e86bc12879d"
integrity sha512-6EQDakGdLG/it2x9EaCt9ZpEEPxnd0OCLBHQ1AcITAAx7nCnyvnzf76jKWG1s2/oJ7SSviUgfWHofdYljFexsA==
dependencies:
"@babel/runtime" "^7.1.2"
create-react-context "^0.2.2"
history "^4.9.0"
hoist-non-react-statics "^3.1.0"
invariant "^2.2.4"
loose-envify "^1.1.0"
prop-types "^15.6.1"
loose-envify "^1.3.1"
path-to-regexp "^1.7.0"
prop-types "^15.6.2"
react-is "^16.6.0"
react-lifecycles-compat "^3.0.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-simplemde-editor@^4.0.0:
version "4.0.0"
@ -8926,6 +8987,11 @@ regenerator-runtime@^0.12.0:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==
regenerator-runtime@^0.13.2:
version "0.13.2"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447"
integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==
regenerator-transform@^0.13.4:
version "0.13.4"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.4.tgz#18f6763cf1382c69c36df76c6ce122cc694284fb"
@ -9209,6 +9275,11 @@ resolve-from@^4.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
resolve-pathname@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879"
integrity sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==
resolve-url@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
@ -9386,6 +9457,11 @@ scss-tokenizer@^0.2.3:
js-base64 "^2.1.8"
source-map "^0.4.2"
seamless-immutable@^7.1.3:
version "7.1.4"
resolved "https://registry.yarnpkg.com/seamless-immutable/-/seamless-immutable-7.1.4.tgz#6e9536def083ddc4dea0207d722e0e80d0f372f8"
integrity sha512-XiUO1QP4ki4E2PHegiGAlu6r82o5A+6tRh7IkGGTVg/h+UoeX4nFBeCGPOhb4CYjvkqsfm/TUtvOMYC1xmV30A==
seek-bzip@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc"
@ -10315,6 +10391,16 @@ timers-browserify@^2.0.4:
dependencies:
setimmediate "^1.0.4"
tiny-invariant@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.4.tgz#346b5415fd93cb696b0c4e8a96697ff590f92463"
integrity sha512-lMhRd/djQJ3MoaHEBrw8e2/uM4rs9YMNk0iOr8rHQ0QdbM7D4l0gFl3szKdeixrlyfm9Zqi4dxHCM2qVG8ND5g==
tiny-warning@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.2.tgz#1dfae771ee1a04396bdfde27a3adcebc6b648b28"
integrity sha512-rru86D9CpQRLvsFG5XFdy0KdLAvjdQDyZCsRcuu60WtzFylDM3eAWSxEVz5kzL2Gp544XiUvPbVKtOA/txLi9Q==
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@ -10887,6 +10973,11 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
value-equal@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7"
integrity sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==
vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"