logo

mastofe

My custom branche(s) on git.pleroma.social/pleroma/mastofe
commit: 8f03fdce7fa16fcaa829a40f395cefc85eb957d5
parent: 1fc6cb499742c1a872ad717a689c58a80aeb714d
Author: Sorin Davidoi <sorin.davidoi@gmail.com>
Date:   Tue, 20 Jun 2017 20:40:03 +0200

Upgrade React Router (#3677)

* chore(yarn): Remove react-router

* chore(yarn): Remove react-router-scroll

* chore(yarn): Remove history

* chore(yarn): Add react-router-dom

* chore: Remove usages of react-router-scroll

* refactor: Upgrade to react-router-web

* refactor: Use fork of react-router-scroll

This reverts commit 2ddea9a6c8d39fc64b7d0b587f3fbda7a45a7fa2.

* fix: Issues mentions in the PR feedback

Diffstat:

Mapp/javascript/mastodon/components/column_back_button.js4++--
Mapp/javascript/mastodon/components/column_back_button_slim.js4++--
Mapp/javascript/mastodon/components/column_header.js4++--
Mapp/javascript/mastodon/components/dropdown_menu.js2+-
Mapp/javascript/mastodon/components/permalink.js2+-
Mapp/javascript/mastodon/components/status.js4++--
Mapp/javascript/mastodon/components/status_action_bar.js8++++----
Mapp/javascript/mastodon/components/status_content.js4++--
Mapp/javascript/mastodon/containers/mastodon.js70++++++++--------------------------------------------------------------
Mapp/javascript/mastodon/features/account/components/action_bar.js2+-
Mapp/javascript/mastodon/features/account_timeline/components/header.js4++--
Mapp/javascript/mastodon/features/compose/components/navigation_bar.js2+-
Mapp/javascript/mastodon/features/compose/components/reply_indicator.js2+-
Mapp/javascript/mastodon/features/compose/components/search_results.js2+-
Mapp/javascript/mastodon/features/compose/index.js2+-
Mapp/javascript/mastodon/features/follow_requests/index.js1+
Mapp/javascript/mastodon/features/getting_started/index.js2+-
Mapp/javascript/mastodon/features/home_timeline/index.js2+-
Mapp/javascript/mastodon/features/report/index.js4++--
Mapp/javascript/mastodon/features/status/components/action_bar.js4++--
Mapp/javascript/mastodon/features/status/components/detailed_status.js4++--
Mapp/javascript/mastodon/features/status/index.js2+-
Mapp/javascript/mastodon/features/ui/components/boost_modal.js2+-
Mapp/javascript/mastodon/features/ui/components/column_link.js2+-
Mapp/javascript/mastodon/features/ui/components/tabs_bar.js14+++++++-------
Mapp/javascript/mastodon/features/ui/index.js95++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mpackage.json5++---
Myarn.lock63++++++++++++++++++++++++++++++++++++++++-----------------------
28 files changed, 186 insertions(+), 130 deletions(-)

diff --git a/app/javascript/mastodon/components/column_back_button.js b/app/javascript/mastodon/components/column_back_button.js @@ -9,8 +9,8 @@ class ColumnBackButton extends React.PureComponent { }; handleClick = () => { - if (window.history && window.history.length === 1) this.context.router.push('/'); - else this.context.router.goBack(); + if (window.history && window.history.length === 1) this.context.router.history.push('/'); + else this.context.router.history.goBack(); } render () { diff --git a/app/javascript/mastodon/components/column_back_button_slim.js b/app/javascript/mastodon/components/column_back_button_slim.js @@ -9,8 +9,8 @@ class ColumnBackButtonSlim extends React.PureComponent { }; handleClick = () => { - if (window.history && window.history.length === 1) this.context.router.push('/'); - else this.context.router.goBack(); + if (window.history && window.history.length === 1) this.context.router.history.push('/'); + else this.context.router.history.goBack(); } render () { diff --git a/app/javascript/mastodon/components/column_header.js b/app/javascript/mastodon/components/column_header.js @@ -45,8 +45,8 @@ class ColumnHeader extends React.PureComponent { } handleBackClick = () => { - if (window.history && window.history.length === 1) this.context.router.push('/'); - else this.context.router.goBack(); + if (window.history && window.history.length === 1) this.context.router.history.push('/'); + else this.context.router.history.goBack(); } handleTransitionEnd = () => { diff --git a/app/javascript/mastodon/components/dropdown_menu.js b/app/javascript/mastodon/components/dropdown_menu.js @@ -41,7 +41,7 @@ class DropdownMenu extends React.PureComponent { action(); } else if (to) { e.preventDefault(); - this.context.router.push(to); + this.context.router.history.push(to); } this.dropdown.hide(); diff --git a/app/javascript/mastodon/components/permalink.js b/app/javascript/mastodon/components/permalink.js @@ -17,7 +17,7 @@ class Permalink extends React.PureComponent { handleClick = (e) => { if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { e.preventDefault(); - this.context.router.push(this.props.to); + this.context.router.history.push(this.props.to); } } diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js @@ -144,14 +144,14 @@ class Status extends ImmutablePureComponent { handleClick = () => { const { status } = this.props; - this.context.router.push(`/statuses/${status.getIn(['reblog', 'id'], status.get('id'))}`); + this.context.router.history.push(`/statuses/${status.getIn(['reblog', 'id'], status.get('id'))}`); } handleAccountClick = (e) => { if (e.button === 0) { const id = Number(e.currentTarget.getAttribute('data-id')); e.preventDefault(); - this.context.router.push(`/accounts/${id}`); + this.context.router.history.push(`/accounts/${id}`); } } diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js @@ -53,7 +53,7 @@ class StatusActionBar extends ImmutablePureComponent { ] handleReplyClick = () => { - this.props.onReply(this.props.status, this.context.router); + this.props.onReply(this.props.status, this.context.router.history); } handleFavouriteClick = () => { @@ -69,7 +69,7 @@ class StatusActionBar extends ImmutablePureComponent { } handleMentionClick = () => { - this.props.onMention(this.props.status.get('account'), this.context.router); + this.props.onMention(this.props.status.get('account'), this.context.router.history); } handleMuteClick = () => { @@ -81,12 +81,12 @@ class StatusActionBar extends ImmutablePureComponent { } handleOpen = () => { - this.context.router.push(`/statuses/${this.props.status.get('id')}`); + this.context.router.history.push(`/statuses/${this.props.status.get('id')}`); } handleReport = () => { this.props.onReport(this.props.status); - this.context.router.push('/report'); + this.context.router.history.push('/report'); } handleConversationMuteClick = () => { diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js @@ -56,7 +56,7 @@ class StatusContent extends React.PureComponent { onMentionClick = (mention, e) => { if (e.button === 0) { e.preventDefault(); - this.context.router.push(`/accounts/${mention.get('id')}`); + this.context.router.history.push(`/accounts/${mention.get('id')}`); } } @@ -65,7 +65,7 @@ class StatusContent extends React.PureComponent { if (e.button === 0) { e.preventDefault(); - this.context.router.push(`/timelines/tag/${hashtag}`); + this.context.router.history.push(`/timelines/tag/${hashtag}`); } } diff --git a/app/javascript/mastodon/containers/mastodon.js b/app/javascript/mastodon/containers/mastodon.js @@ -12,35 +12,10 @@ import { } from '../actions/timelines'; import { showOnboardingOnce } from '../actions/onboarding'; import { updateNotifications, refreshNotifications } from '../actions/notifications'; -import createBrowserHistory from 'history/lib/createBrowserHistory'; -import applyRouterMiddleware from 'react-router/lib/applyRouterMiddleware'; -import useRouterHistory from 'react-router/lib/useRouterHistory'; -import Router from 'react-router/lib/Router'; -import Route from 'react-router/lib/Route'; -import IndexRedirect from 'react-router/lib/IndexRedirect'; -import IndexRoute from 'react-router/lib/IndexRoute'; -import { useScroll } from 'react-router-scroll'; +import BrowserRouter from 'react-router-dom/BrowserRouter'; +import Route from 'react-router-dom/Route'; +import ScrollContext from 'react-router-scroll/lib/ScrollBehaviorContext'; import UI from '../features/ui'; -import Status from '../features/status'; -import GettingStarted from '../features/getting_started'; -import PublicTimeline from '../features/public_timeline'; -import CommunityTimeline from '../features/community_timeline'; -import AccountTimeline from '../features/account_timeline'; -import AccountGallery from '../features/account_gallery'; -import HomeTimeline from '../features/home_timeline'; -import Compose from '../features/compose'; -import Followers from '../features/followers'; -import Following from '../features/following'; -import Reblogs from '../features/reblogs'; -import Favourites from '../features/favourites'; -import HashtagTimeline from '../features/hashtag_timeline'; -import Notifications from '../features/notifications'; -import FollowRequests from '../features/follow_requests'; -import GenericNotFound from '../features/generic_not_found'; -import FavouritedStatuses from '../features/favourited_statuses'; -import Blocks from '../features/blocks'; -import Mutes from '../features/mutes'; -import Report from '../features/report'; import { hydrateStore } from '../actions/store'; import createStream from '../stream'; import { IntlProvider, addLocaleData } from 'react-intl'; @@ -52,10 +27,6 @@ const store = configureStore(); const initialState = JSON.parse(document.getElementById('initial-state').textContent); store.dispatch(hydrateStore(initialState)); -const browserHistory = useRouterHistory(createBrowserHistory)({ - basename: '/web', -}); - class Mastodon extends React.PureComponent { componentDidMount() { @@ -136,36 +107,11 @@ class Mastodon extends React.PureComponent { return ( <IntlProvider locale={locale} messages={messages}> <Provider store={store}> - <Router history={browserHistory} render={applyRouterMiddleware(useScroll())}> - <Route path='/' component={UI}> - <IndexRedirect to='/getting-started' /> - <Route path='getting-started' component={GettingStarted} /> - <Route path='timelines/home' component={HomeTimeline} /> - <Route path='timelines/public' component={PublicTimeline} /> - <Route path='timelines/public/local' component={CommunityTimeline} /> - <Route path='timelines/tag/:id' component={HashtagTimeline} /> - - <Route path='notifications' component={Notifications} /> - <Route path='favourites' component={FavouritedStatuses} /> - - <Route path='statuses/new' component={Compose} /> - <Route path='statuses/:statusId' component={Status} /> - <Route path='statuses/:statusId/reblogs' component={Reblogs} /> - <Route path='statuses/:statusId/favourites' component={Favourites} /> - - <Route path='accounts/:accountId' component={AccountTimeline} /> - <Route path='accounts/:accountId/followers' component={Followers} /> - <Route path='accounts/:accountId/following' component={Following} /> - <Route path='accounts/:accountId/media' component={AccountGallery} /> - - <Route path='follow_requests' component={FollowRequests} /> - <Route path='blocks' component={Blocks} /> - <Route path='mutes' component={Mutes} /> - <Route path='report' component={Report} /> - - <Route path='*' component={GenericNotFound} /> - </Route> - </Router> + <BrowserRouter basename='/web'> + <ScrollContext> + <Route path='/' component={UI} /> + </ScrollContext> + </BrowserRouter> </Provider> </IntlProvider> ); diff --git a/app/javascript/mastodon/features/account/components/action_bar.js b/app/javascript/mastodon/features/account/components/action_bar.js @@ -2,7 +2,7 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import DropdownMenu from '../../../components/dropdown_menu'; -import Link from 'react-router/lib/Link'; +import Link from 'react-router-dom/Link'; import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; const messages = defineMessages({ diff --git a/app/javascript/mastodon/features/account_timeline/components/header.js b/app/javascript/mastodon/features/account_timeline/components/header.js @@ -33,12 +33,12 @@ class Header extends ImmutablePureComponent { } handleMention = () => { - this.props.onMention(this.props.account, this.context.router); + this.props.onMention(this.props.account, this.context.router.history); } handleReport = () => { this.props.onReport(this.props.account); - this.context.router.push('/report'); + this.context.router.history.push('/report'); } handleMute = () => { diff --git a/app/javascript/mastodon/features/compose/components/navigation_bar.js b/app/javascript/mastodon/features/compose/components/navigation_bar.js @@ -5,7 +5,7 @@ import IconButton from '../../../components/icon_button'; import DisplayName from '../../../components/display_name'; import Permalink from '../../../components/permalink'; import { FormattedMessage } from 'react-intl'; -import Link from 'react-router/lib/Link'; +import Link from 'react-router-dom/Link'; import ImmutablePureComponent from 'react-immutable-pure-component'; class NavigationBar extends ImmutablePureComponent { diff --git a/app/javascript/mastodon/features/compose/components/reply_indicator.js b/app/javascript/mastodon/features/compose/components/reply_indicator.js @@ -31,7 +31,7 @@ class ReplyIndicator extends ImmutablePureComponent { handleAccountClick = (e) => { if (e.button === 0) { e.preventDefault(); - this.context.router.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`); + this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`); } } diff --git a/app/javascript/mastodon/features/compose/components/search_results.js b/app/javascript/mastodon/features/compose/components/search_results.js @@ -3,7 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import AccountContainer from '../../../containers/account_container'; import StatusContainer from '../../../containers/status_container'; -import Link from 'react-router/lib/Link'; +import Link from 'react-router-dom/Link'; import ImmutablePureComponent from 'react-immutable-pure-component'; class SearchResults extends ImmutablePureComponent { diff --git a/app/javascript/mastodon/features/compose/index.js b/app/javascript/mastodon/features/compose/index.js @@ -5,7 +5,7 @@ import NavigationContainer from './containers/navigation_container'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { mountCompose, unmountCompose } from '../../actions/compose'; -import Link from 'react-router/lib/Link'; +import Link from 'react-router-dom/Link'; import { injectIntl, defineMessages } from 'react-intl'; import SearchContainer from './containers/search_container'; import Motion from 'react-motion/lib/Motion'; diff --git a/app/javascript/mastodon/features/follow_requests/index.js b/app/javascript/mastodon/features/follow_requests/index.js @@ -54,6 +54,7 @@ class FollowRequests extends ImmutablePureComponent { return ( <Column icon='users' heading={intl.formatMessage(messages.heading)}> <ColumnBackButtonSlim /> + <ScrollContainer scrollKey='follow_requests'> <div className='scrollable' onScroll={this.handleScroll}> {accountIds.map(id => diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js @@ -2,7 +2,7 @@ import React from 'react'; import Column from '../ui/components/column'; import ColumnLink from '../ui/components/column_link'; import ColumnSubheading from '../ui/components/column_subheading'; -import Link from 'react-router/lib/Link'; +import Link from 'react-router-dom/Link'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; diff --git a/app/javascript/mastodon/features/home_timeline/index.js b/app/javascript/mastodon/features/home_timeline/index.js @@ -8,7 +8,7 @@ import ColumnHeader from '../../components/column_header'; import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ColumnSettingsContainer from './containers/column_settings_container'; -import Link from 'react-router/lib/Link'; +import Link from 'react-router-dom/Link'; const messages = defineMessages({ title: { id: 'column.home', defaultMessage: 'Home' }, diff --git a/app/javascript/mastodon/features/report/index.js b/app/javascript/mastodon/features/report/index.js @@ -52,7 +52,7 @@ class Report extends React.PureComponent { componentWillMount () { if (!this.props.account) { - this.context.router.replace('/'); + this.context.router.history.replace('/'); } } @@ -76,7 +76,7 @@ class Report extends React.PureComponent { handleSubmit = () => { this.props.dispatch(submitReport()); - this.context.router.replace('/'); + this.context.router.history.replace('/'); } render () { diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js @@ -50,12 +50,12 @@ class ActionBar extends React.PureComponent { } handleMentionClick = () => { - this.props.onMention(this.props.status.get('account'), this.context.router); + this.props.onMention(this.props.status.get('account'), this.context.router.history); } handleReport = () => { this.props.onReport(this.props.status); - this.context.router.push('/report'); + this.context.router.history.push('/report'); } render () { diff --git a/app/javascript/mastodon/features/status/components/detailed_status.js b/app/javascript/mastodon/features/status/components/detailed_status.js @@ -7,7 +7,7 @@ import StatusContent from '../../../components/status_content'; import MediaGallery from '../../../components/media_gallery'; import VideoPlayer from '../../../components/video_player'; import AttachmentList from '../../../components/attachment_list'; -import Link from 'react-router/lib/Link'; +import Link from 'react-router-dom/Link'; import { FormattedDate, FormattedNumber } from 'react-intl'; import CardContainer from '../containers/card_container'; import ImmutablePureComponent from 'react-immutable-pure-component'; @@ -28,7 +28,7 @@ class DetailedStatus extends ImmutablePureComponent { handleAccountClick = (e) => { if (e.button === 0) { e.preventDefault(); - this.context.router.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`); + this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`); } e.stopPropagation(); diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js @@ -93,7 +93,7 @@ class Status extends ImmutablePureComponent { } handleReplyClick = (status) => { - this.props.dispatch(replyCompose(status, this.context.router)); + this.props.dispatch(replyCompose(status, this.context.router.history)); } handleModalReblog = (status) => { diff --git a/app/javascript/mastodon/features/ui/components/boost_modal.js b/app/javascript/mastodon/features/ui/components/boost_modal.js @@ -40,7 +40,7 @@ class BoostModal extends ImmutablePureComponent { if (e.button === 0) { e.preventDefault(); this.props.onClose(); - this.context.router.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`); + this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`); } } diff --git a/app/javascript/mastodon/features/ui/components/column_link.js b/app/javascript/mastodon/features/ui/components/column_link.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import Link from 'react-router/lib/Link'; +import Link from 'react-router-dom/Link'; const ColumnLink = ({ icon, text, to, href, method, hideOnMobile }) => { if (href) { diff --git a/app/javascript/mastodon/features/ui/components/tabs_bar.js b/app/javascript/mastodon/features/ui/components/tabs_bar.js @@ -1,5 +1,5 @@ import React from 'react'; -import Link from 'react-router/lib/Link'; +import NavLink from 'react-router-dom/NavLink'; import { FormattedMessage } from 'react-intl'; class TabsBar extends React.Component { @@ -7,14 +7,14 @@ class TabsBar extends React.Component { render () { return ( <div className='tabs-bar'> - <Link className='tabs-bar__link primary' activeClassName='active' to='/statuses/new'><i className='fa fa-fw fa-pencil' /><FormattedMessage id='tabs_bar.compose' defaultMessage='Compose' /></Link> - <Link className='tabs-bar__link primary' activeClassName='active' to='/timelines/home'><i className='fa fa-fw fa-home' /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></Link> - <Link className='tabs-bar__link primary' activeClassName='active' to='/notifications'><i className='fa fa-fw fa-bell' /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></Link> + <NavLink className='tabs-bar__link primary' activeClassName='active' to='/statuses/new'><i className='fa fa-fw fa-pencil' /><FormattedMessage id='tabs_bar.compose' defaultMessage='Compose' /></NavLink> + <NavLink className='tabs-bar__link primary' activeClassName='active' to='/timelines/home'><i className='fa fa-fw fa-home' /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></NavLink> + <NavLink className='tabs-bar__link primary' activeClassName='active' to='/notifications'><i className='fa fa-fw fa-bell' /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink> - <Link className='tabs-bar__link secondary' activeClassName='active' to='/timelines/public/local'><i className='fa fa-fw fa-users' /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></Link> - <Link className='tabs-bar__link secondary' activeClassName='active' to='/timelines/public'><i className='fa fa-fw fa-globe' /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></Link> + <NavLink className='tabs-bar__link secondary' activeClassName='active' to='/timelines/public/local'><i className='fa fa-fw fa-users' /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></NavLink> + <NavLink className='tabs-bar__link secondary' activeClassName='active' exact to='/timelines/public'><i className='fa fa-fw fa-globe' /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></NavLink> - <Link className='tabs-bar__link primary' activeClassName='active' style={{ flexGrow: '0', flexBasis: '30px' }} to='/getting-started'><i className='fa fa-fw fa-asterisk' /></Link> + <NavLink className='tabs-bar__link primary' activeClassName='active' style={{ flexGrow: '0', flexBasis: '30px' }} to='/getting-started'><i className='fa fa-fw fa-asterisk' /></NavLink> </div> ); } diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js @@ -1,4 +1,7 @@ import React from 'react'; +import Switch from 'react-router-dom/Switch'; +import Route from 'react-router-dom/Route'; +import Redirect from 'react-router-dom/Redirect'; import NotificationsContainer from './containers/notifications_container'; import PropTypes from 'prop-types'; import LoadingBarContainer from './containers/loading_bar_container'; @@ -13,6 +16,67 @@ import { refreshNotifications } from '../../actions/notifications'; import UploadArea from './components/upload_area'; import ColumnsAreaContainer from './containers/columns_area_container'; +import Status from '../../features/status'; +import GettingStarted from '../../features/getting_started'; +import PublicTimeline from '../../features/public_timeline'; +import CommunityTimeline from '../../features/community_timeline'; +import AccountTimeline from '../../features/account_timeline'; +import AccountGallery from '../../features/account_gallery'; +import HomeTimeline from '../../features/home_timeline'; +import Compose from '../../features/compose'; +import Followers from '../../features/followers'; +import Following from '../../features/following'; +import Reblogs from '../../features/reblogs'; +import Favourites from '../../features/favourites'; +import HashtagTimeline from '../../features/hashtag_timeline'; +import Notifications from '../../features/notifications'; +import FollowRequests from '../../features/follow_requests'; +import GenericNotFound from '../../features/generic_not_found'; +import FavouritedStatuses from '../../features/favourited_statuses'; +import Blocks from '../../features/blocks'; +import Mutes from '../../features/mutes'; +import Report from '../../features/report'; + +// Small wrapper to pass multiColumn to the route components +const WrappedSwitch = ({ multiColumn, children }) => ( + <Switch> + {React.Children.map(children, child => React.cloneElement(child, { multiColumn }))} + </Switch> +); + +WrappedSwitch.propTypes = { + multiColumn: PropTypes.bool, + children: PropTypes.node, +}; + +// Small Wraper to extract the params from the route and pass +// them to the rendered component, together with the content to +// be rendered inside (the children) +class WrappedRoute extends React.Component { + + static propTypes = { + component: PropTypes.func.isRequired, + content: PropTypes.node, + multiColumn: PropTypes.bool, + } + + renderComponent = ({ match: { params } }) => { + const { component: Component, content, multiColumn } = this.props; + + return <Component params={params} multiColumn={multiColumn}>{content}</Component>; + } + + render () { + const { component: Component, content, ...rest } = this.props; + + return <Route {...rest} render={this.renderComponent} />; + } + +} + +const noOp = () => false; + + class UI extends React.PureComponent { static propTypes = { @@ -119,7 +183,36 @@ class UI extends React.PureComponent { return ( <div className='ui' ref={this.setRef}> <TabsBar /> - <ColumnsAreaContainer singleColumn={isMobile(width)}>{children}</ColumnsAreaContainer> + <ColumnsAreaContainer singleColumn={isMobile(width)}> + <WrappedSwitch> + <Redirect from='/' to='/getting-started' exact /> + <WrappedRoute path='/getting-started' component={GettingStarted} content={children} /> + <WrappedRoute path='/timelines/home' component={HomeTimeline} content={children} /> + <WrappedRoute path='/timelines/public' exact component={PublicTimeline} content={children} /> + <WrappedRoute path='/timelines/public/local' component={CommunityTimeline} content={children} /> + <WrappedRoute path='/timelines/tag/:id' component={HashtagTimeline} content={children} /> + + <WrappedRoute path='/notifications' component={Notifications} content={children} /> + <WrappedRoute path='/favourites' component={FavouritedStatuses} content={children} /> + + <WrappedRoute path='/statuses/new' component={Compose} content={children} /> + <WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} /> + <WrappedRoute path='/statuses/:statusId/reblogs' component={Reblogs} content={children} /> + <WrappedRoute path='/statuses/:statusId/favourites' component={Favourites} content={children} /> + + <WrappedRoute path='/accounts/:accountId' exact component={AccountTimeline} content={children} /> + <WrappedRoute path='/accounts/:accountId/followers' component={Followers} content={children} /> + <WrappedRoute path='/accounts/:accountId/following' component={Following} content={children} /> + <WrappedRoute path='/accounts/:accountId/media' component={AccountGallery} content={children} /> + + <WrappedRoute path='/follow_requests' component={FollowRequests} content={children} /> + <WrappedRoute path='/blocks' component={Blocks} content={children} /> + <WrappedRoute path='/mutes' component={Mutes} content={children} /> + <WrappedRoute path='/report' component={Report} content={children} /> + + <WrappedRoute component={GenericNotFound} content={children} /> + </WrappedSwitch> + </ColumnsAreaContainer> <NotificationsContainer /> <LoadingBarContainer className='loading-bar' /> <ModalContainer /> diff --git a/package.json b/package.json @@ -52,7 +52,6 @@ "file-loader": "^0.11.2", "font-awesome": "^4.7.0", "glob": "^7.1.1", - "history": "^3.3.0", "http-link-header": "^0.8.0", "immutable": "^3.8.1", "intersection-observer": "^0.3.0", @@ -86,8 +85,8 @@ "react-notification": "^6.7.0", "react-redux": "^5.0.4", "react-redux-loading-bar": "^2.9.2", - "react-router": "^3.0.5", - "react-router-scroll": "^0.4.2", + "react-router-dom": "^4.1.1", + "react-router-scroll": "ytase/react-router-scroll#build", "react-simple-dropdown": "^3.0.0", "react-textarea-autosize": "^5.0.6", "react-toggle": "^4.0.1", diff --git a/yarn.lock b/yarn.lock @@ -1906,7 +1906,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-class@^15.5.1, create-react-class@^15.5.2, create-react-class@^15.5.3: +create-react-class@^15.5.2, create-react-class@^15.5.3: version "15.5.3" resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.5.3.tgz#fb0f7cae79339e9a179e194ef466efa3923820fe" dependencies: @@ -3244,13 +3244,14 @@ hawk@~3.1.3: hoek "2.x.x" sntp "1.x.x" -history@^3.0.0, history@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/history/-/history-3.3.0.tgz#fcedcce8f12975371545d735461033579a6dae9c" +history@^4.5.1, history@^4.6.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/history/-/history-4.6.1.tgz#911cf8eb65728555a94f2b12780a0c531a14d2fd" dependencies: invariant "^2.2.1" loose-envify "^1.2.0" - query-string "^4.2.2" + resolve-pathname "^2.0.0" + value-equal "^0.2.0" warning "^3.0.0" hmac-drbg@^1.0.0: @@ -4806,7 +4807,7 @@ path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" -path-to-regexp@^1.7.0: +path-to-regexp@^1.5.3, 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" dependencies: @@ -5511,7 +5512,7 @@ qs@6.4.0, qs@^6.4.0, qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" -query-string@^4.1.0, query-string@^4.2.2: +query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" dependencies: @@ -5711,24 +5712,32 @@ react-redux@^5.0.4: loose-envify "^1.1.0" prop-types "^15.5.10" -react-router-scroll@^0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/react-router-scroll/-/react-router-scroll-0.4.2.tgz#4b90e8707edf96eba7f066d94c5b4338bd6848b7" +react-router-dom@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.1.1.tgz#3021ade1f2c160af97cf94e25594c5f294583025" dependencies: - prop-types "^15.5.6" - scroll-behavior "^0.9.3" + history "^4.5.1" + loose-envify "^1.3.1" + prop-types "^15.5.4" + react-router "^4.1.1" + +react-router-scroll@ytase/react-router-scroll#build: + version "0.4.1" + resolved "https://codeload.github.com/ytase/react-router-scroll/tar.gz/991ecddb08885e1fb80ec1e9dbf3a35844b7d4cd" + dependencies: + scroll-behavior "^0.9.1" warning "^3.0.0" -react-router@^3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-3.0.5.tgz#c3b7873758045a8bbc9562aef4ff4bc8cce7c136" +react-router@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.1.1.tgz#d448f3b7c1b429a6fbb03395099949c606b1fe95" dependencies: - create-react-class "^15.5.1" - history "^3.0.0" + history "^4.6.0" hoist-non-react-statics "^1.2.0" - invariant "^2.2.1" - loose-envify "^1.2.0" - prop-types "^15.5.6" + invariant "^2.2.2" + loose-envify "^1.3.1" + path-to-regexp "^1.5.3" + prop-types "^15.5.4" warning "^3.0.0" react-simple-di@^1.2.0: @@ -6085,9 +6094,13 @@ resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" +resolve-pathname@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.1.0.tgz#e8358801b86b83b17560d4e3c382d7aef2100944" + resolve-url-loader@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-2.0.2.tgz#c465e97ea0a4791f3961f766cea775ff2e3ceb8c" + version "2.0.3" + resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-2.0.3.tgz#f54cd1b040e8f0ab72b2cb32c9fbb8544152d9e9" dependencies: adjust-sourcemap-loader "^1.1.0" camelcase "^4.0.0" @@ -6201,7 +6214,7 @@ schema-utils@^0.3.0, schema-utils@^0.x: dependencies: ajv "^5.0.0" -scroll-behavior@^0.9.3: +scroll-behavior@^0.9.1: version "0.9.3" resolved "https://registry.yarnpkg.com/scroll-behavior/-/scroll-behavior-0.9.3.tgz#e48bcc8af364f3f07176e8dbca3968bd5e71557b" dependencies: @@ -6977,6 +6990,10 @@ validate-npm-package-license@^3.0.1: spdx-correct "~1.0.0" spdx-expression-parse "~1.0.0" +value-equal@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.2.1.tgz#c220a304361fce6994dbbedaa3c7e1a1b895871d" + vary@~1.1.0, vary@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"