[Glitch] Upgrade to react-router v5

Port 1b70d7ed7c to glitch-soc

Co-authored-by: Claire <claire.github-309c@sitedethib.com>
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
main
Renaud Chaput 2023-10-19 19:44:55 +02:00 committed by Claire
parent 245513d630
commit d6eacb79c6
51 changed files with 413 additions and 385 deletions

View File

@ -4,26 +4,25 @@ import { createPortal } from 'react-dom';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { Icon } from 'flavours/glitch/components/icon'; import { withRouter } from 'react-router-dom';
import { Icon } from 'flavours/glitch/components/icon';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
export default class ColumnBackButton extends PureComponent { class ColumnBackButton extends PureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
multiColumn: PropTypes.bool, multiColumn: PropTypes.bool,
...WithRouterPropTypes,
}; };
handleClick = () => { handleClick = () => {
const { router } = this.context; const { history } = this.props;
if (router.history.location?.state?.fromMastodon) { if (history.location?.state?.fromMastodon) {
router.history.goBack(); history.goBack();
} else { } else {
router.history.push('/'); history.push('/');
} }
}; };
@ -57,3 +56,5 @@ export default class ColumnBackButton extends PureComponent {
} }
} }
export default withRouter(ColumnBackButton);

View File

@ -1,25 +1,27 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react'; import { PureComponent } from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { withRouter } from 'react-router-dom';
import { Icon } from 'flavours/glitch/components/icon'; import { Icon } from 'flavours/glitch/components/icon';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
export default class ColumnBackButtonSlim extends PureComponent { class ColumnBackButtonSlim extends PureComponent {
static contextTypes = { static propTypes = {
router: PropTypes.object, ...WithRouterPropTypes,
}; };
handleClick = () => { handleClick = () => {
const { router } = this.context; const { location, history } = this.props;
// Check if there is a previous page in the app to go back to per https://stackoverflow.com/a/70532858/9703201 // Check if there is a previous page in the app to go back to per https://stackoverflow.com/a/70532858/9703201
// When upgrading to V6, check `location.key !== 'default'` instead per https://github.com/remix-run/history/blob/main/docs/api-reference.md#location // When upgrading to V6, check `location.key !== 'default'` instead per https://github.com/remix-run/history/blob/main/docs/api-reference.md#location
if (router.route.location.key) { if (location.key) {
router.history.goBack(); history.goBack();
} else { } else {
router.history.push('/'); history.push('/');
} }
}; };
@ -35,3 +37,5 @@ export default class ColumnBackButtonSlim extends PureComponent {
} }
} }
export default withRouter(ColumnBackButtonSlim);

View File

@ -5,8 +5,10 @@ import { createPortal } from 'react-dom';
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl'; import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import { Icon } from 'flavours/glitch/components/icon'; import { Icon } from 'flavours/glitch/components/icon';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
const messages = defineMessages({ const messages = defineMessages({
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' }, show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
@ -18,7 +20,6 @@ const messages = defineMessages({
class ColumnHeader extends PureComponent { class ColumnHeader extends PureComponent {
static contextTypes = { static contextTypes = {
router: PropTypes.object,
identity: PropTypes.object, identity: PropTypes.object,
}; };
@ -38,6 +39,7 @@ class ColumnHeader extends PureComponent {
onClick: PropTypes.func, onClick: PropTypes.func,
appendContent: PropTypes.node, appendContent: PropTypes.node,
collapseIssues: PropTypes.bool, collapseIssues: PropTypes.bool,
...WithRouterPropTypes,
}; };
state = { state = {
@ -63,12 +65,12 @@ class ColumnHeader extends PureComponent {
}; };
handleBackClick = () => { handleBackClick = () => {
const { router } = this.context; const { history } = this.props;
if (router.history.location?.state?.fromMastodon) { if (history.location?.state?.fromMastodon) {
router.history.goBack(); history.goBack();
} else { } else {
router.history.push('/'); history.push('/');
} }
}; };
@ -78,15 +80,14 @@ class ColumnHeader extends PureComponent {
handlePin = () => { handlePin = () => {
if (!this.props.pinned) { if (!this.props.pinned) {
this.context.router.history.replace('/'); this.props.history.replace('/');
} }
this.props.onPin(); this.props.onPin();
}; };
render () { render () {
const { router } = this.context; const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues, history } = this.props;
const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props;
const { collapsed, animating } = this.state; const { collapsed, animating } = this.state;
const wrapperClassName = classNames('column-header__wrapper', { const wrapperClassName = classNames('column-header__wrapper', {
@ -129,7 +130,7 @@ class ColumnHeader extends PureComponent {
pinButton = <button key='pin-button' className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='plus' /> <FormattedMessage id='column_header.pin' defaultMessage='Pin' /></button>; pinButton = <button key='pin-button' className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='plus' /> <FormattedMessage id='column_header.pin' defaultMessage='Pin' /></button>;
} }
if (!pinned && ((multiColumn && router.history.location?.state?.fromMastodon) || showBackButton)) { if (!pinned && ((multiColumn && history.location?.state?.fromMastodon) || showBackButton)) {
backButton = ( backButton = (
<button onClick={this.handleBackClick} className='column-header__back-button'> <button onClick={this.handleBackClick} className='column-header__back-button'>
<Icon id='chevron-left' className='column-back-button__icon' fixedWidth /> <Icon id='chevron-left' className='column-back-button__icon' fixedWidth />
@ -215,4 +216,4 @@ class ColumnHeader extends PureComponent {
} }
export default injectIntl(ColumnHeader); export default injectIntl(withRouter(ColumnHeader));

View File

@ -2,13 +2,16 @@ import PropTypes from 'prop-types';
import { PureComponent, cloneElement, Children } from 'react'; import { PureComponent, cloneElement, Children } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { supportsPassiveEvents } from 'detect-passive-events'; import { supportsPassiveEvents } from 'detect-passive-events';
import Overlay from 'react-overlays/Overlay'; import Overlay from 'react-overlays/Overlay';
import { CircularProgress } from "./circular_progress"; import { CircularProgress } from 'flavours/glitch/components/circular_progress';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import { IconButton } from './icon_button'; import { IconButton } from './icon_button';
const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true; const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
@ -16,10 +19,6 @@ let id = 0;
class DropdownMenu extends PureComponent { class DropdownMenu extends PureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
items: PropTypes.oneOfType([PropTypes.array, ImmutablePropTypes.list]).isRequired, items: PropTypes.oneOfType([PropTypes.array, ImmutablePropTypes.list]).isRequired,
loading: PropTypes.bool, loading: PropTypes.bool,
@ -159,11 +158,7 @@ class DropdownMenu extends PureComponent {
} }
export default class Dropdown extends PureComponent { class Dropdown extends PureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
children: PropTypes.node, children: PropTypes.node,
@ -183,6 +178,7 @@ export default class Dropdown extends PureComponent {
renderItem: PropTypes.func, renderItem: PropTypes.func,
renderHeader: PropTypes.func, renderHeader: PropTypes.func,
onItemClick: PropTypes.func, onItemClick: PropTypes.func,
...WithRouterPropTypes
}; };
static defaultProps = { static defaultProps = {
@ -250,7 +246,7 @@ export default class Dropdown extends PureComponent {
item.action(); item.action();
} else if (item && item.to) { } else if (item && item.to) {
e.preventDefault(); e.preventDefault();
this.context.router.history.push(item.to); this.props.history.push(item.to);
} }
}; };
@ -338,3 +334,5 @@ export default class Dropdown extends PureComponent {
} }
} }
export default withRouter(Dropdown);

View File

@ -2,14 +2,13 @@ import PropTypes from 'prop-types';
import { PureComponent } from 'react'; import { PureComponent } from 'react';
import 'wicg-inert'; import 'wicg-inert';
import { multiply } from 'color-blend'; import { multiply } from 'color-blend';
import { createBrowserHistory } from 'history'; import { createBrowserHistory } from 'history';
export default class ModalRoot extends PureComponent { import { WithOptionalRouterPropTypes, withOptionalRouter } from 'flavours/glitch/utils/react_router';
static contextTypes = { class ModalRoot extends PureComponent {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
children: PropTypes.node, children: PropTypes.node,
@ -21,6 +20,7 @@ export default class ModalRoot extends PureComponent {
}), }),
noEsc: PropTypes.bool, noEsc: PropTypes.bool,
ignoreFocus: PropTypes.bool, ignoreFocus: PropTypes.bool,
...WithOptionalRouterPropTypes,
}; };
activeElement = this.props.children ? document.activeElement : null; activeElement = this.props.children ? document.activeElement : null;
@ -56,7 +56,7 @@ export default class ModalRoot extends PureComponent {
componentDidMount () { componentDidMount () {
window.addEventListener('keyup', this.handleKeyUp, false); window.addEventListener('keyup', this.handleKeyUp, false);
window.addEventListener('keydown', this.handleKeyDown, false); window.addEventListener('keydown', this.handleKeyDown, false);
this.history = this.context.router ? this.context.router.history : createBrowserHistory(); this.history = this.props.history || createBrowserHistory();
if (this.props.children) { if (this.props.children) {
this._handleModalOpen(); this._handleModalOpen();
@ -160,3 +160,5 @@ export default class ModalRoot extends PureComponent {
} }
} }
export default withOptionalRouter(ModalRoot);

View File

@ -1,36 +0,0 @@
import { PureComponent } from 'react';
import { Switch, Route, withRouter } from 'react-router-dom';
import AccountNavigation from 'flavours/glitch/features/account/navigation';
import Trends from 'flavours/glitch/features/getting_started/containers/trends_container';
import { showTrends } from 'flavours/glitch/initial_state';
const DefaultNavigation = () => (
showTrends ? (
<>
<div className='flex-spacer' />
<Trends />
</>
) : null
);
class NavigationPortal extends PureComponent {
render () {
return (
<Switch>
<Route path='/@:acct' exact component={AccountNavigation} />
<Route path='/@:acct/tagged/:tagged?' exact component={AccountNavigation} />
<Route path='/@:acct/with_replies' exact component={AccountNavigation} />
<Route path='/@:acct/followers' exact component={AccountNavigation} />
<Route path='/@:acct/following' exact component={AccountNavigation} />
<Route path='/@:acct/media' exact component={AccountNavigation} />
<Route component={DefaultNavigation} />
</Switch>
);
}
}
export default withRouter(NavigationPortal);

View File

@ -0,0 +1,25 @@
import { Switch, Route } from 'react-router-dom';
import AccountNavigation from 'flavours/glitch/features/account/navigation';
import Trends from 'flavours/glitch/features/getting_started/containers/trends_container';
import { showTrends } from 'flavours/glitch/initial_state';
const DefaultNavigation: React.FC = () =>
showTrends ? (
<>
<div className='flex-spacer' />
<Trends />
</>
) : null;
export const NavigationPortal: React.FC = () => (
<Switch>
<Route path='/@:acct' exact component={AccountNavigation} />
<Route path='/@:acct/tagged/:tagged?' exact component={AccountNavigation} />
<Route path='/@:acct/with_replies' exact component={AccountNavigation} />
<Route path='/@:acct/followers' exact component={AccountNavigation} />
<Route path='/@:acct/following' exact component={AccountNavigation} />
<Route path='/@:acct/media' exact component={AccountNavigation} />
<Route component={DefaultNavigation} />
</Switch>
);

View File

@ -1,11 +1,9 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { PureComponent } from 'react'; import { PureComponent } from 'react';
export default class Permalink extends PureComponent { import { withOptionalRouter, WithOptionalRouterPropTypes } from 'flavours/glitch/utils/react_router';
static contextTypes = { class Permalink extends PureComponent {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
className: PropTypes.string, className: PropTypes.string,
@ -13,6 +11,7 @@ export default class Permalink extends PureComponent {
to: PropTypes.string.isRequired, to: PropTypes.string.isRequired,
children: PropTypes.node, children: PropTypes.node,
onInterceptClick: PropTypes.func, onInterceptClick: PropTypes.func,
...WithOptionalRouterPropTypes,
}; };
handleClick = (e) => { handleClick = (e) => {
@ -22,9 +21,9 @@ export default class Permalink extends PureComponent {
return; return;
} }
if (this.context.router) { if (this.props.history) {
e.preventDefault(); e.preventDefault();
this.context.router.history.push(this.props.to); this.props.history.push(this.props.to);
} }
} }
}; };
@ -47,3 +46,5 @@ export default class Permalink extends PureComponent {
} }
} }
export default withOptionalRouter(Permalink);

View File

@ -1,15 +1,18 @@
import type { PropsWithChildren } from 'react'; import type { PropsWithChildren } from 'react';
import React from 'react'; import React from 'react';
import { createBrowserHistory } from 'history';
import { Router as OriginalRouter } from 'react-router'; import { Router as OriginalRouter } from 'react-router';
import type { LocationDescriptor, Path } from 'history';
import { createBrowserHistory } from 'history';
import { layoutFromWindow } from 'flavours/glitch/is_mobile'; import { layoutFromWindow } from 'flavours/glitch/is_mobile';
interface MastodonLocationState { interface MastodonLocationState {
fromMastodon?: boolean; fromMastodon?: boolean;
mastodonModalKey?: string; mastodonModalKey?: string;
} }
type HistoryPath = Path | LocationDescriptor<MastodonLocationState>;
const browserHistory = createBrowserHistory< const browserHistory = createBrowserHistory<
MastodonLocationState | undefined MastodonLocationState | undefined
@ -17,25 +20,36 @@ const browserHistory = createBrowserHistory<
const originalPush = browserHistory.push.bind(browserHistory); const originalPush = browserHistory.push.bind(browserHistory);
const originalReplace = browserHistory.replace.bind(browserHistory); const originalReplace = browserHistory.replace.bind(browserHistory);
browserHistory.push = (path: string, state?: MastodonLocationState) => { function extractRealPath(path: HistoryPath) {
if (typeof path === 'string') return path;
else return path.pathname;
}
browserHistory.push = (path: HistoryPath, state?: MastodonLocationState) => {
state = state ?? {}; state = state ?? {};
state.fromMastodon = true; state.fromMastodon = true;
if (layoutFromWindow() === 'multi-column' && !path.startsWith('/deck')) { const realPath = extractRealPath(path);
originalPush(`/deck${path}`, state); if (!realPath) return;
if (layoutFromWindow() === 'multi-column' && !realPath.startsWith('/deck')) {
originalPush(`/deck${realPath}`, state);
} else { } else {
originalPush(path, state); originalPush(path, state);
} }
}; };
browserHistory.replace = (path: string, state?: MastodonLocationState) => { browserHistory.replace = (path: HistoryPath, state?: MastodonLocationState) => {
if (browserHistory.location.state?.fromMastodon) { if (browserHistory.location.state?.fromMastodon) {
state = state ?? {}; state = state ?? {};
state.fromMastodon = true; state.fromMastodon = true;
} }
if (layoutFromWindow() === 'multi-column' && !path.startsWith('/deck')) { const realPath = extractRealPath(path);
originalReplace(`/deck${path}`, state); if (!realPath) return;
if (layoutFromWindow() === 'multi-column' && !realPath.startsWith('/deck')) {
originalReplace(`/deck${realPath}`, state);
} else { } else {
originalReplace(path, state); originalReplace(path, state);
} }

View File

@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import { Children, cloneElement, PureComponent } from 'react'; import { Children, cloneElement, PureComponent } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { useLocation } from 'react-router-dom';
import { List as ImmutableList } from 'immutable'; import { List as ImmutableList } from 'immutable';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -34,11 +35,32 @@ const mapStateToProps = (state, { scrollKey }) => {
}; };
}; };
class ScrollableList extends PureComponent { // This component only exists to be able to call useLocation()
const IOArticleContainerWrapper = ({id, index, listLength, intersectionObserverWrapper, trackScroll, scrollKey, children}) => {
const location = useLocation();
static contextTypes = { return (<IntersectionObserverArticleContainer
router: PropTypes.object, id={id}
}; index={index}
listLength={listLength}
intersectionObserverWrapper={intersectionObserverWrapper}
saveHeightKey={trackScroll ? `${location.key}:${scrollKey}` : null}
>
{children}
</IntersectionObserverArticleContainer>);
};
IOArticleContainerWrapper.propTypes = {
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
index: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
listLength: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
scrollKey: PropTypes.string.isRequired,
intersectionObserverWrapper: PropTypes.object.isRequired,
trackScroll: PropTypes.bool.isRequired,
children: PropTypes.node,
};
class ScrollableList extends PureComponent {
static propTypes = { static propTypes = {
scrollKey: PropTypes.string.isRequired, scrollKey: PropTypes.string.isRequired,
@ -331,13 +353,14 @@ class ScrollableList extends PureComponent {
{loadPending} {loadPending}
{Children.map(this.props.children, (child, index) => ( {Children.map(this.props.children, (child, index) => (
<IntersectionObserverArticleContainer <IOArticleContainerWrapper
key={child.key} key={child.key}
id={child.key} id={child.key}
index={index} index={index}
listLength={childrenCount} listLength={childrenCount}
intersectionObserverWrapper={this.intersectionObserverWrapper} intersectionObserverWrapper={this.intersectionObserverWrapper}
saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null} trackScroll={trackScroll}
scrollKey={scrollKey}
> >
{cloneElement(child, { {cloneElement(child, {
getScrollPosition: this.getScrollPosition, getScrollPosition: this.getScrollPosition,
@ -345,7 +368,7 @@ class ScrollableList extends PureComponent {
cachedMediaWidth: this.state.cachedMediaWidth, cachedMediaWidth: this.state.cachedMediaWidth,
cacheMediaWidth: this.cacheMediaWidth, cacheMediaWidth: this.cacheMediaWidth,
})} })}
</IntersectionObserverArticleContainer> </IOArticleContainerWrapper>
))} ))}
{loadMore} {loadMore}

View File

@ -14,6 +14,7 @@ import PollContainer from 'flavours/glitch/containers/poll_container';
import NotificationOverlayContainer from 'flavours/glitch/features/notifications/containers/overlay_container'; import NotificationOverlayContainer from 'flavours/glitch/features/notifications/containers/overlay_container';
import { displayMedia } from 'flavours/glitch/initial_state'; import { displayMedia } from 'flavours/glitch/initial_state';
import { autoUnfoldCW } from 'flavours/glitch/utils/content_warning'; import { autoUnfoldCW } from 'flavours/glitch/utils/content_warning';
import { withOptionalRouter, WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import Card from '../features/status/components/card'; import Card from '../features/status/components/card';
import Bundle from '../features/ui/components/bundle'; import Bundle from '../features/ui/components/bundle';
@ -67,10 +68,6 @@ export const defaultMediaVisibility = (status, settings) => {
class Status extends ImmutablePureComponent { class Status extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
containerId: PropTypes.string, containerId: PropTypes.string,
id: PropTypes.string, id: PropTypes.string,
@ -117,6 +114,7 @@ class Status extends ImmutablePureComponent {
inUse: PropTypes.bool, inUse: PropTypes.bool,
available: PropTypes.bool, available: PropTypes.bool,
}), }),
...WithRouterPropTypes,
}; };
state = { state = {
@ -356,10 +354,9 @@ class Status extends ImmutablePureComponent {
// Otherwise, we open the url handed to us in `destination`, if // Otherwise, we open the url handed to us in `destination`, if
// applicable. // applicable.
parseClick = (e, destination) => { parseClick = (e, destination) => {
const { router } = this.context; const { status, history } = this.props;
const { status } = this.props;
const { isCollapsed } = this.state; const { isCollapsed } = this.state;
if (!router) return; if (!history) return;
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey)) { if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey)) {
if (isCollapsed) this.setCollapsed(false); if (isCollapsed) this.setCollapsed(false);
@ -377,7 +374,7 @@ class Status extends ImmutablePureComponent {
status.getIn(['reblog', 'id'], status.get('id')) status.getIn(['reblog', 'id'], status.get('id'))
}`; }`;
} }
router.history.push(destination); history.push(destination);
} }
e.preventDefault(); e.preventDefault();
} }
@ -431,7 +428,7 @@ class Status extends ImmutablePureComponent {
handleHotkeyReply = e => { handleHotkeyReply = e => {
e.preventDefault(); e.preventDefault();
this.props.onReply(this.props.status, this.context.router.history); this.props.onReply(this.props.status, this.props.history);
}; };
handleHotkeyFavourite = (e) => { handleHotkeyFavourite = (e) => {
@ -448,16 +445,16 @@ class Status extends ImmutablePureComponent {
handleHotkeyMention = e => { handleHotkeyMention = e => {
e.preventDefault(); e.preventDefault();
this.props.onMention(this.props.status.get('account'), this.context.router.history); this.props.onMention(this.props.status.get('account'), this.props.history);
}; };
handleHotkeyOpen = () => { handleHotkeyOpen = () => {
const status = this.props.status; const status = this.props.status;
this.context.router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`); this.props.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
}; };
handleHotkeyOpenProfile = () => { handleHotkeyOpenProfile = () => {
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`); this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
}; };
handleHotkeyMoveUp = e => { handleHotkeyMoveUp = e => {
@ -514,7 +511,6 @@ class Status extends ImmutablePureComponent {
parseClick, parseClick,
setCollapsed, setCollapsed,
} = this; } = this;
const { router } = this.context;
const { const {
intl, intl,
status, status,
@ -533,6 +529,7 @@ class Status extends ImmutablePureComponent {
previousId, previousId,
nextInReplyToId, nextInReplyToId,
rootId, rootId,
history,
...other ...other
} = this.props; } = this.props;
const { isCollapsed } = this.state; const { isCollapsed } = this.state;
@ -828,7 +825,7 @@ class Status extends ImmutablePureComponent {
onExpandedToggle={this.handleExpandedToggle} onExpandedToggle={this.handleExpandedToggle}
onTranslate={this.handleTranslate} onTranslate={this.handleTranslate}
parseClick={parseClick} parseClick={parseClick}
disabled={!router} disabled={!history}
tagLinks={settings.get('tag_misleading_links')} tagLinks={settings.get('tag_misleading_links')}
rewriteMentions={settings.get('rewrite_mentions')} rewriteMentions={settings.get('rewrite_mentions')}
/> />
@ -854,4 +851,4 @@ class Status extends ImmutablePureComponent {
} }
export default injectIntl(Status); export default withOptionalRouter(injectIntl(Status));

View File

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
@ -11,6 +12,7 @@ import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_cont
import { me } from 'flavours/glitch/initial_state'; import { me } from 'flavours/glitch/initial_state';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions'; import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions';
import { accountAdminLink, statusAdminLink } from 'flavours/glitch/utils/backend_links'; import { accountAdminLink, statusAdminLink } from 'flavours/glitch/utils/backend_links';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import { IconButton } from './icon_button'; import { IconButton } from './icon_button';
import { RelativeTimestamp } from './relative_timestamp'; import { RelativeTimestamp } from './relative_timestamp';
@ -53,7 +55,6 @@ const messages = defineMessages({
class StatusActionBar extends ImmutablePureComponent { class StatusActionBar extends ImmutablePureComponent {
static contextTypes = { static contextTypes = {
router: PropTypes.object,
identity: PropTypes.object, identity: PropTypes.object,
}; };
@ -80,6 +81,7 @@ class StatusActionBar extends ImmutablePureComponent {
showReplyCount: PropTypes.bool, showReplyCount: PropTypes.bool,
scrollKey: PropTypes.string, scrollKey: PropTypes.string,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
...WithRouterPropTypes,
}; };
// Avoid checking props that are functions (and whose equality will always // Avoid checking props that are functions (and whose equality will always
@ -95,7 +97,7 @@ class StatusActionBar extends ImmutablePureComponent {
const { signedIn } = this.context.identity; const { signedIn } = this.context.identity;
if (signedIn) { if (signedIn) {
this.props.onReply(this.props.status, this.context.router.history); this.props.onReply(this.props.status, this.props.history);
} else { } else {
this.props.onInteractionModal('reply', this.props.status); this.props.onInteractionModal('reply', this.props.status);
} }
@ -132,15 +134,15 @@ class StatusActionBar extends ImmutablePureComponent {
}; };
handleDeleteClick = () => { handleDeleteClick = () => {
this.props.onDelete(this.props.status, this.context.router.history); this.props.onDelete(this.props.status, this.props.history);
}; };
handleRedraftClick = () => { handleRedraftClick = () => {
this.props.onDelete(this.props.status, this.context.router.history, true); this.props.onDelete(this.props.status, this.props.history, true);
}; };
handleEditClick = () => { handleEditClick = () => {
this.props.onEdit(this.props.status, this.context.router.history); this.props.onEdit(this.props.status, this.props.history);
}; };
handlePinClick = () => { handlePinClick = () => {
@ -148,11 +150,11 @@ class StatusActionBar extends ImmutablePureComponent {
}; };
handleMentionClick = () => { handleMentionClick = () => {
this.props.onMention(this.props.status.get('account'), this.context.router.history); this.props.onMention(this.props.status.get('account'), this.props.history);
}; };
handleDirectClick = () => { handleDirectClick = () => {
this.props.onDirect(this.props.status.get('account'), this.context.router.history); this.props.onDirect(this.props.status.get('account'), this.props.history);
}; };
handleMuteClick = () => { handleMuteClick = () => {
@ -164,12 +166,7 @@ class StatusActionBar extends ImmutablePureComponent {
}; };
handleOpen = () => { handleOpen = () => {
let state = { ...this.context.router.history.location.state }; this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`);
if (state.mastodonModalKey) {
this.context.router.history.replace(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`);
} else {
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`);
}
}; };
handleEmbed = () => { handleEmbed = () => {
@ -340,4 +337,4 @@ class StatusActionBar extends ImmutablePureComponent {
} }
export default injectIntl(StatusActionBar); export default withRouter(injectIntl(StatusActionBar));

View File

@ -4,6 +4,7 @@ import { PureComponent } from 'react';
import { FormattedMessage, injectIntl } from 'react-intl'; import { FormattedMessage, injectIntl } from 'react-intl';
import classnames from 'classnames'; import classnames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -131,6 +132,10 @@ class StatusContent extends PureComponent {
rewriteMentions: PropTypes.string, rewriteMentions: PropTypes.string,
languages: ImmutablePropTypes.map, languages: ImmutablePropTypes.map,
intl: PropTypes.object, intl: PropTypes.object,
// from react-router
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
}; };
static defaultProps = { static defaultProps = {
@ -472,4 +477,4 @@ class StatusContent extends PureComponent {
} }
export default connect(mapStateToProps)(injectIntl(StatusContent)); export default withRouter(connect(mapStateToProps)(injectIntl(StatusContent)));

View File

@ -14,10 +14,6 @@ const messages = defineMessages({
class FeaturedTags extends ImmutablePureComponent { class FeaturedTags extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
account: ImmutablePropTypes.map, account: ImmutablePropTypes.map,
featuredTags: ImmutablePropTypes.list, featuredTags: ImmutablePropTypes.list,

View File

@ -4,6 +4,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
@ -16,6 +17,7 @@ import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_cont
import { autoPlayGif, me, domain } from 'flavours/glitch/initial_state'; import { autoPlayGif, me, domain } from 'flavours/glitch/initial_state';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions'; import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions';
import { preferencesLink, profileLink, accountAdminLink } from 'flavours/glitch/utils/backend_links'; import { preferencesLink, profileLink, accountAdminLink } from 'flavours/glitch/utils/backend_links';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import AccountNoteContainer from '../containers/account_note_container'; import AccountNoteContainer from '../containers/account_note_container';
import FollowRequestNoteContainer from '../containers/follow_request_note_container'; import FollowRequestNoteContainer from '../containers/follow_request_note_container';
@ -81,10 +83,6 @@ const dateFormatOptions = {
class Header extends ImmutablePureComponent { class Header extends ImmutablePureComponent {
static contextTypes = {
identity: PropTypes.object,
};
static propTypes = { static propTypes = {
account: ImmutablePropTypes.map, account: ImmutablePropTypes.map,
identity_props: ImmutablePropTypes.list, identity_props: ImmutablePropTypes.list,
@ -107,6 +105,11 @@ class Header extends ImmutablePureComponent {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
domain: PropTypes.string.isRequired, domain: PropTypes.string.isRequired,
hidden: PropTypes.bool, hidden: PropTypes.bool,
...WithRouterPropTypes,
};
static contextTypes = {
identity: PropTypes.object,
}; };
openEditProfile = () => { openEditProfile = () => {
@ -406,4 +409,4 @@ class Header extends ImmutablePureComponent {
} }
export default injectIntl(Header); export default withRouter(injectIntl(Header));

View File

@ -2,18 +2,19 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { NavLink } from 'react-router-dom'; import { NavLink, withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import ActionBar from 'flavours/glitch/features/account/components/action_bar'; import ActionBar from 'flavours/glitch/features/account/components/action_bar';
import InnerHeader from 'flavours/glitch/features/account/components/header'; import InnerHeader from 'flavours/glitch/features/account/components/header';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import MemorialNote from './memorial_note'; import MemorialNote from './memorial_note';
import MovedNote from './moved_note'; import MovedNote from './moved_note';
export default class Header extends ImmutablePureComponent { class Header extends ImmutablePureComponent {
static propTypes = { static propTypes = {
account: ImmutablePropTypes.map, account: ImmutablePropTypes.map,
@ -34,10 +35,7 @@ export default class Header extends ImmutablePureComponent {
hideTabs: PropTypes.bool, hideTabs: PropTypes.bool,
domain: PropTypes.string.isRequired, domain: PropTypes.string.isRequired,
hidden: PropTypes.bool, hidden: PropTypes.bool,
}; ...WithRouterPropTypes,
static contextTypes = {
router: PropTypes.object,
}; };
handleFollow = () => { handleFollow = () => {
@ -49,11 +47,11 @@ export default class Header extends ImmutablePureComponent {
}; };
handleMention = () => { handleMention = () => {
this.props.onMention(this.props.account, this.context.router.history); this.props.onMention(this.props.account, this.props.history);
}; };
handleDirect = () => { handleDirect = () => {
this.props.onDirect(this.props.account, this.context.router.history); this.props.onDirect(this.props.account, this.props.history);
}; };
handleReport = () => { handleReport = () => {
@ -162,3 +160,5 @@ export default class Header extends ImmutablePureComponent {
} }
} }
export default withRouter(Header);

View File

@ -1,30 +1,28 @@
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { Icon } from 'flavours/glitch/components/icon'; import { Icon } from 'flavours/glitch/components/icon';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import AvatarOverlay from '../../../components/avatar_overlay'; import AvatarOverlay from '../../../components/avatar_overlay';
import { DisplayName } from '../../../components/display_name'; import { DisplayName } from '../../../components/display_name';
export default class MovedNote extends ImmutablePureComponent { class MovedNote extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
from: ImmutablePropTypes.map.isRequired, from: ImmutablePropTypes.map.isRequired,
to: ImmutablePropTypes.map.isRequired, to: ImmutablePropTypes.map.isRequired,
...WithRouterPropTypes,
}; };
handleAccountClick = e => { handleAccountClick = e => {
if (e.button === 0) { if (e.button === 0) {
e.preventDefault(); e.preventDefault();
this.context.router.history.push(`/@${this.props.to.get('acct')}`); this.props.history.push(`/@${this.props.to.get('acct')}`);
} }
e.stopPropagation(); e.stopPropagation();
@ -50,3 +48,5 @@ export default class MovedNote extends ImmutablePureComponent {
} }
} }
export default withRouter(MovedNote);

View File

@ -44,7 +44,6 @@ class CommunityTimeline extends PureComponent {
}; };
static contextTypes = { static contextTypes = {
router: PropTypes.object,
identity: PropTypes.object, identity: PropTypes.object,
}; };

View File

@ -9,6 +9,7 @@ import { length } from 'stringz';
import { maxChars } from 'flavours/glitch/initial_state'; import { maxChars } from 'flavours/glitch/initial_state';
import { isMobile } from 'flavours/glitch/is_mobile'; import { isMobile } from 'flavours/glitch/is_mobile';
import { WithOptionalRouterPropTypes, withOptionalRouter } from 'flavours/glitch/utils/react_router';
import AutosuggestInput from '../../../components/autosuggest_input'; import AutosuggestInput from '../../../components/autosuggest_input';
import AutosuggestTextarea from '../../../components/autosuggest_textarea'; import AutosuggestTextarea from '../../../components/autosuggest_textarea';
@ -38,11 +39,6 @@ const messages = defineMessages({
}); });
class ComposeForm extends ImmutablePureComponent { class ComposeForm extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
text: PropTypes.string, text: PropTypes.string,
@ -70,7 +66,6 @@ class ComposeForm extends ImmutablePureComponent {
isInReply: PropTypes.bool, isInReply: PropTypes.bool,
singleColumn: PropTypes.bool, singleColumn: PropTypes.bool,
lang: PropTypes.string, lang: PropTypes.string,
advancedOptions: ImmutablePropTypes.map, advancedOptions: ImmutablePropTypes.map,
layout: PropTypes.string, layout: PropTypes.string,
media: ImmutablePropTypes.list, media: ImmutablePropTypes.list,
@ -82,6 +77,7 @@ class ComposeForm extends ImmutablePureComponent {
onChangeSpoilerness: PropTypes.func, onChangeSpoilerness: PropTypes.func,
onChangeVisibility: PropTypes.func, onChangeVisibility: PropTypes.func,
onMediaDescriptionConfirm: PropTypes.func, onMediaDescriptionConfirm: PropTypes.func,
...WithOptionalRouterPropTypes
}; };
static defaultProps = { static defaultProps = {
@ -129,12 +125,12 @@ class ComposeForm extends ImmutablePureComponent {
// Submit unless there are media with missing descriptions // Submit unless there are media with missing descriptions
if (mediaDescriptionConfirmation && onMediaDescriptionConfirm && media && media.some(item => !item.get('description'))) { if (mediaDescriptionConfirmation && onMediaDescriptionConfirm && media && media.some(item => !item.get('description'))) {
const firstWithoutDescription = media.find(item => !item.get('description')); const firstWithoutDescription = media.find(item => !item.get('description'));
onMediaDescriptionConfirm(this.context.router ? this.context.router.history : null, firstWithoutDescription.get('id'), overriddenVisibility); onMediaDescriptionConfirm(this.props.history || null, firstWithoutDescription.get('id'), overriddenVisibility);
} else if (onSubmit) { } else if (onSubmit) {
if (onChangeVisibility && overriddenVisibility) { if (onChangeVisibility && overriddenVisibility) {
onChangeVisibility(overriddenVisibility); onChangeVisibility(overriddenVisibility);
} }
onSubmit(this.context.router ? this.context.router.history : null); onSubmit(this.props.history || null);
} }
}; };
@ -390,4 +386,4 @@ class ComposeForm extends ImmutablePureComponent {
} }
export default injectIntl(ComposeForm); export default withOptionalRouter(injectIntl(ComposeForm));

View File

@ -1,4 +1,3 @@
// Package imports.
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
@ -6,18 +5,13 @@ import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
// Components.
import AttachmentList from 'flavours/glitch/components/attachment_list'; import AttachmentList from 'flavours/glitch/components/attachment_list';
import { IconButton } from 'flavours/glitch/components/icon_button'; import { IconButton } from 'flavours/glitch/components/icon_button';
import AccountContainer from 'flavours/glitch/containers/account_container'; import AccountContainer from 'flavours/glitch/containers/account_container';
// Messages.
const messages = defineMessages({
cancel: {
defaultMessage: 'Cancel',
id: 'reply_indicator.cancel',
},
});
const messages = defineMessages({
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
});
class ReplyIndicator extends ImmutablePureComponent { class ReplyIndicator extends ImmutablePureComponent {

View File

@ -4,14 +4,14 @@ import { PureComponent } from 'react';
import { defineMessages, injectIntl, FormattedMessage, FormattedList } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage, FormattedList } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { Icon } from 'flavours/glitch/components/icon';
import { Icon } from 'flavours/glitch/components/icon';
import { domain, searchEnabled } from 'flavours/glitch/initial_state'; import { domain, searchEnabled } from 'flavours/glitch/initial_state';
import { focusRoot } from 'flavours/glitch/utils/dom_helpers';
import { HASHTAG_REGEX } from 'flavours/glitch/utils/hashtags'; import { HASHTAG_REGEX } from 'flavours/glitch/utils/hashtags';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
const messages = defineMessages({ const messages = defineMessages({
placeholder: { id: 'search.placeholder', defaultMessage: 'Search' }, placeholder: { id: 'search.placeholder', defaultMessage: 'Search' },
@ -32,7 +32,6 @@ const labelForRecentSearch = search => {
class Search extends PureComponent { class Search extends PureComponent {
static contextTypes = { static contextTypes = {
router: PropTypes.object.isRequired,
identity: PropTypes.object.isRequired, identity: PropTypes.object.isRequired,
}; };
@ -50,6 +49,7 @@ class Search extends PureComponent {
openInRoute: PropTypes.bool, openInRoute: PropTypes.bool,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
singleColumn: PropTypes.bool, singleColumn: PropTypes.bool,
...WithRouterPropTypes,
}; };
state = { state = {
@ -122,8 +122,7 @@ class Search extends PureComponent {
switch(e.key) { switch(e.key) {
case 'Escape': case 'Escape':
e.preventDefault(); e.preventDefault();
this._unfocus();
focusRoot();
break; break;
case 'ArrowDown': case 'ArrowDown':
@ -170,32 +169,29 @@ class Search extends PureComponent {
}; };
handleHashtagClick = () => { handleHashtagClick = () => {
const { router } = this.context; const { value, onClickSearchResult, history } = this.props;
const { value, onClickSearchResult } = this.props;
const query = value.trim().replace(/^#/, ''); const query = value.trim().replace(/^#/, '');
router.history.push(`/tags/${query}`); history.push(`/tags/${query}`);
onClickSearchResult(query, 'hashtag'); onClickSearchResult(query, 'hashtag');
this._unfocus(); this._unfocus();
}; };
handleAccountClick = () => { handleAccountClick = () => {
const { router } = this.context; const { value, onClickSearchResult, history } = this.props;
const { value, onClickSearchResult } = this.props;
const query = value.trim().replace(/^@/, ''); const query = value.trim().replace(/^@/, '');
router.history.push(`/@${query}`); history.push(`/@${query}`);
onClickSearchResult(query, 'account'); onClickSearchResult(query, 'account');
this._unfocus(); this._unfocus();
}; };
handleURLClick = () => { handleURLClick = () => {
const { router } = this.context; const { onOpenURL, history } = this.props;
const { onOpenURL } = this.props;
onOpenURL(router.history); onOpenURL(history);
this._unfocus(); this._unfocus();
}; };
@ -208,13 +204,12 @@ class Search extends PureComponent {
}; };
handleRecentSearchClick = search => { handleRecentSearchClick = search => {
const { onChange } = this.props; const { onChange, history } = this.props;
const { router } = this.context;
if (search.get('type') === 'account') { if (search.get('type') === 'account') {
router.history.push(`/@${search.get('q')}`); history.push(`/@${search.get('q')}`);
} else if (search.get('type') === 'hashtag') { } else if (search.get('type') === 'hashtag') {
router.history.push(`/tags/${search.get('q')}`); history.push(`/tags/${search.get('q')}`);
} else { } else {
onChange(search.get('q')); onChange(search.get('q'));
this._submit(search.get('type')); this._submit(search.get('type'));
@ -246,8 +241,7 @@ class Search extends PureComponent {
} }
_submit (type) { _submit (type) {
const { onSubmit, openInRoute, value, onClickSearchResult } = this.props; const { onSubmit, openInRoute, value, onClickSearchResult, history } = this.props;
const { router } = this.context;
onSubmit(type); onSubmit(type);
@ -256,7 +250,7 @@ class Search extends PureComponent {
} }
if (openInRoute) { if (openInRoute) {
router.history.push('/search'); history.push('/search');
} }
this._unfocus(); this._unfocus();
@ -403,4 +397,4 @@ class Search extends PureComponent {
} }
export default injectIntl(Search); export default withRouter(injectIntl(Search));

View File

@ -13,10 +13,6 @@ import Motion from '../../ui/util/optional_motion';
export default class Upload extends ImmutablePureComponent { export default class Upload extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
media: ImmutablePropTypes.map.isRequired, media: ImmutablePropTypes.map.isRequired,
onUndo: PropTypes.func.isRequired, onUndo: PropTypes.func.isRequired,

View File

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
@ -17,6 +18,7 @@ import { RelativeTimestamp } from 'flavours/glitch/components/relative_timestamp
import StatusContent from 'flavours/glitch/components/status_content'; import StatusContent from 'flavours/glitch/components/status_content';
import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container';
import { autoPlayGif } from 'flavours/glitch/initial_state'; import { autoPlayGif } from 'flavours/glitch/initial_state';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
const messages = defineMessages({ const messages = defineMessages({
more: { id: 'status.more', defaultMessage: 'More' }, more: { id: 'status.more', defaultMessage: 'More' },
@ -30,10 +32,6 @@ const messages = defineMessages({
class Conversation extends ImmutablePureComponent { class Conversation extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
conversationId: PropTypes.string.isRequired, conversationId: PropTypes.string.isRequired,
accounts: ImmutablePropTypes.list.isRequired, accounts: ImmutablePropTypes.list.isRequired,
@ -45,6 +43,7 @@ class Conversation extends ImmutablePureComponent {
markRead: PropTypes.func.isRequired, markRead: PropTypes.func.isRequired,
delete: PropTypes.func.isRequired, delete: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
...WithRouterPropTypes,
}; };
state = { state = {
@ -52,9 +51,8 @@ class Conversation extends ImmutablePureComponent {
}; };
parseClick = (e, destination) => { parseClick = (e, destination) => {
const { router } = this.context; const { history, lastStatus, unread, markRead } = this.props;
const { lastStatus, unread, markRead } = this.props; if (!history) return;
if (!router) return;
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey)) { if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey)) {
if (destination === undefined) { if (destination === undefined) {
@ -63,7 +61,7 @@ class Conversation extends ImmutablePureComponent {
} }
destination = `/statuses/${lastStatus.get('id')}`; destination = `/statuses/${lastStatus.get('id')}`;
} }
router.history.push(destination); history.push(destination);
e.preventDefault(); e.preventDefault();
} }
}; };
@ -95,7 +93,7 @@ class Conversation extends ImmutablePureComponent {
}; };
handleClick = () => { handleClick = () => {
if (!this.context.router) { if (!this.props.history) {
return; return;
} }
@ -105,7 +103,7 @@ class Conversation extends ImmutablePureComponent {
markRead(); markRead();
} }
this.context.router.history.push(`/@${lastStatus.getIn(['account', 'acct'])}/${lastStatus.get('id')}`); this.props.history.push(`/@${lastStatus.getIn(['account', 'acct'])}/${lastStatus.get('id')}`);
}; };
handleMarkAsRead = () => { handleMarkAsRead = () => {
@ -113,7 +111,7 @@ class Conversation extends ImmutablePureComponent {
}; };
handleReply = () => { handleReply = () => {
this.props.reply(this.props.lastStatus, this.context.router.history); this.props.reply(this.props.lastStatus, this.props.history);
}; };
handleDelete = () => { handleDelete = () => {
@ -232,4 +230,4 @@ class Conversation extends ImmutablePureComponent {
} }
export default injectIntl(Conversation); export default withRouter(injectIntl(Conversation));

View File

@ -36,10 +36,6 @@ const mapStateToProps = state => ({
class Directory extends PureComponent { class Directory extends PureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
isLoading: PropTypes.bool, isLoading: PropTypes.bool,
accountIds: ImmutablePropTypes.list.isRequired, accountIds: ImmutablePropTypes.list.isRequired,

View File

@ -34,7 +34,6 @@ const mapStateToProps = state => ({
class Explore extends PureComponent { class Explore extends PureComponent {
static contextTypes = { static contextTypes = {
router: PropTypes.object,
identity: PropTypes.object, identity: PropTypes.object,
}; };

View File

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
@ -14,6 +15,7 @@ import { fetchSuggestions } from 'flavours/glitch/actions/suggestions';
import { markAsPartial } from 'flavours/glitch/actions/timelines'; import { markAsPartial } from 'flavours/glitch/actions/timelines';
import Button from 'flavours/glitch/components/button'; import Button from 'flavours/glitch/components/button';
import Column from 'flavours/glitch/features/ui/components/column'; import Column from 'flavours/glitch/features/ui/components/column';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import imageGreeting from 'mastodon/../images/elephant_ui_greeting.svg'; import imageGreeting from 'mastodon/../images/elephant_ui_greeting.svg';
import Account from './components/account'; import Account from './components/account';
@ -25,14 +27,11 @@ const mapStateToProps = state => ({
class FollowRecommendations extends ImmutablePureComponent { class FollowRecommendations extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object.isRequired,
};
static propTypes = { static propTypes = {
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
suggestions: ImmutablePropTypes.list, suggestions: ImmutablePropTypes.list,
isLoading: PropTypes.bool, isLoading: PropTypes.bool,
...WithRouterPropTypes,
}; };
componentDidMount () { componentDidMount () {
@ -56,8 +55,7 @@ class FollowRecommendations extends ImmutablePureComponent {
} }
handleDone = () => { handleDone = () => {
const { dispatch } = this.props; const { history, dispatch } = this.props;
const { router } = this.context;
dispatch(requestBrowserPermission((permission) => { dispatch(requestBrowserPermission((permission) => {
if (permission === 'granted') { if (permission === 'granted') {
@ -71,7 +69,7 @@ class FollowRecommendations extends ImmutablePureComponent {
} }
})); }));
router.history.push('/home'); history.push('/home');
}; };
render () { render () {
@ -118,4 +116,4 @@ class FollowRecommendations extends ImmutablePureComponent {
} }
export default connect(mapStateToProps)(FollowRecommendations); export default withRouter(connect(mapStateToProps)(FollowRecommendations));

View File

@ -4,6 +4,7 @@ import { PureComponent } from 'react';
import { defineMessages, injectIntl, FormattedMessage, FormattedDate } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage, FormattedDate } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
@ -19,24 +20,19 @@ import EmojiPickerDropdown from 'flavours/glitch/features/compose/containers/emo
import unicodeMapping from 'flavours/glitch/features/emoji/emoji_unicode_mapping_light'; import unicodeMapping from 'flavours/glitch/features/emoji/emoji_unicode_mapping_light';
import { autoPlayGif, reduceMotion, disableSwiping, mascot } from 'flavours/glitch/initial_state'; import { autoPlayGif, reduceMotion, disableSwiping, mascot } from 'flavours/glitch/initial_state';
import { assetHost } from 'flavours/glitch/utils/config'; import { assetHost } from 'flavours/glitch/utils/config';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import elephantUIPlane from 'mastodon/../images/elephant_ui_plane.svg'; import elephantUIPlane from 'mastodon/../images/elephant_ui_plane.svg';
const messages = defineMessages({ const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' }, close: { id: 'lightbox.close', defaultMessage: 'Close' },
previous: { id: 'lightbox.previous', defaultMessage: 'Previous' }, previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },
next: { id: 'lightbox.next', defaultMessage: 'Next' }, next: { id: 'lightbox.next', defaultMessage: 'Next' },
}); });
class Content extends ImmutablePureComponent { class ContentWithRouter extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
announcement: ImmutablePropTypes.map.isRequired, announcement: ImmutablePropTypes.map.isRequired,
...WithRouterPropTypes,
}; };
setRef = c => { setRef = c => {
@ -91,25 +87,25 @@ class Content extends ImmutablePureComponent {
} }
onMentionClick = (mention, e) => { onMentionClick = (mention, e) => {
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) { if (this.props.history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault(); e.preventDefault();
this.context.router.history.push(`/@${mention.get('acct')}`); this.props.history.push(`/@${mention.get('acct')}`);
} }
}; };
onHashtagClick = (hashtag, e) => { onHashtagClick = (hashtag, e) => {
hashtag = hashtag.replace(/^#/, ''); hashtag = hashtag.replace(/^#/, '');
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) { if (this.props.history&& e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault(); e.preventDefault();
this.context.router.history.push(`/tags/${hashtag}`); this.props.history.push(`/tags/${hashtag}`);
} }
}; };
onStatusClick = (status, e) => { onStatusClick = (status, e) => {
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) { if (this.props.history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault(); e.preventDefault();
this.context.router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`); this.props.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
} }
}; };
@ -155,6 +151,8 @@ class Content extends ImmutablePureComponent {
} }
const Content = withRouter(ContentWithRouter);
class Emoji extends PureComponent { class Emoji extends PureComponent {
static propTypes = { static propTypes = {

View File

@ -88,7 +88,6 @@ const badgeDisplay = (number, limit) => {
class GettingStarted extends ImmutablePureComponent { class GettingStarted extends ImmutablePureComponent {
static contextTypes = { static contextTypes = {
router: PropTypes.object.isRequired,
identity: PropTypes.object, identity: PropTypes.object,
}; };

View File

@ -28,7 +28,6 @@ const messages = defineMessages({
class GettingStartedMisc extends ImmutablePureComponent { class GettingStartedMisc extends ImmutablePureComponent {
static contextTypes = { static contextTypes = {
router: PropTypes.object.isRequired,
identity: PropTypes.object, identity: PropTypes.object,
}; };

View File

@ -4,6 +4,7 @@ import { PureComponent } from 'react';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -22,6 +23,7 @@ import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
import { RadioButton } from 'flavours/glitch/components/radio_button'; import { RadioButton } from 'flavours/glitch/components/radio_button';
import BundleColumnError from 'flavours/glitch/features/ui/components/bundle_column_error'; import BundleColumnError from 'flavours/glitch/features/ui/components/bundle_column_error';
import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container'; import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
const messages = defineMessages({ const messages = defineMessages({
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' }, deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
@ -38,10 +40,6 @@ const mapStateToProps = (state, props) => ({
class ListTimeline extends PureComponent { class ListTimeline extends PureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
params: PropTypes.object.isRequired, params: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
@ -50,6 +48,7 @@ class ListTimeline extends PureComponent {
multiColumn: PropTypes.bool, multiColumn: PropTypes.bool,
list: PropTypes.oneOfType([ImmutablePropTypes.map, PropTypes.bool]), list: PropTypes.oneOfType([ImmutablePropTypes.map, PropTypes.bool]),
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
...WithRouterPropTypes,
}; };
handlePin = () => { handlePin = () => {
@ -59,7 +58,7 @@ class ListTimeline extends PureComponent {
dispatch(removeColumn(columnId)); dispatch(removeColumn(columnId));
} else { } else {
dispatch(addColumn('LIST', { id: this.props.params.id })); dispatch(addColumn('LIST', { id: this.props.params.id }));
this.context.router.history.push('/'); this.props.history.push('/');
} }
}; };
@ -137,7 +136,7 @@ class ListTimeline extends PureComponent {
if (columnId) { if (columnId) {
dispatch(removeColumn(columnId)); dispatch(removeColumn(columnId));
} else { } else {
this.context.router.history.push('/lists'); this.props.history.push('/lists');
} }
}, },
}, },
@ -242,4 +241,4 @@ class ListTimeline extends PureComponent {
} }
export default connect(mapStateToProps)(injectIntl(ListTimeline)); export default withRouter(connect(mapStateToProps)(injectIntl(ListTimeline)));

View File

@ -1,25 +1,24 @@
// Package imports.
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { HotKeys } from 'react-hotkeys'; import { HotKeys } from 'react-hotkeys';
// Our imports.
import { Icon } from 'flavours/glitch/components/icon'; import { Icon } from 'flavours/glitch/components/icon';
import Permalink from 'flavours/glitch/components/permalink'; import Permalink from 'flavours/glitch/components/permalink';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import NotificationOverlayContainer from '../containers/overlay_container'; import NotificationOverlayContainer from '../containers/overlay_container';
import Report from './report'; import Report from './report';
export default class AdminReport extends ImmutablePureComponent { class AdminReport extends ImmutablePureComponent {
static propTypes = { static propTypes = {
hidden: PropTypes.bool, hidden: PropTypes.bool,
@ -28,6 +27,7 @@ export default class AdminReport extends ImmutablePureComponent {
notification: ImmutablePropTypes.map.isRequired, notification: ImmutablePropTypes.map.isRequired,
unread: PropTypes.bool, unread: PropTypes.bool,
report: ImmutablePropTypes.map.isRequired, report: ImmutablePropTypes.map.isRequired,
...WithRouterPropTypes,
}; };
handleMoveUp = () => { handleMoveUp = () => {
@ -45,15 +45,15 @@ export default class AdminReport extends ImmutablePureComponent {
}; };
handleOpenProfile = () => { handleOpenProfile = () => {
const { notification } = this.props; const { history, notification } = this.props;
this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`); history.push(`/@${notification.getIn(['account', 'acct'])}`);
}; };
handleMention = e => { handleMention = e => {
e.preventDefault(); e.preventDefault();
const { notification, onMention } = this.props; const { history, notification, onMention } = this.props;
onMention(notification.get('account'), this.context.router.history); onMention(notification.get('account'), history);
}; };
getHandlers () { getHandlers () {
@ -111,3 +111,5 @@ export default class AdminReport extends ImmutablePureComponent {
} }
} }
export default withRouter(AdminReport);

View File

@ -1,24 +1,23 @@
// Package imports.
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { HotKeys } from 'react-hotkeys'; import { HotKeys } from 'react-hotkeys';
// Our imports.
import { Icon } from 'flavours/glitch/components/icon'; import { Icon } from 'flavours/glitch/components/icon';
import Permalink from 'flavours/glitch/components/permalink'; import Permalink from 'flavours/glitch/components/permalink';
import AccountContainer from 'flavours/glitch/containers/account_container'; import AccountContainer from 'flavours/glitch/containers/account_container';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import NotificationOverlayContainer from '../containers/overlay_container'; import NotificationOverlayContainer from '../containers/overlay_container';
export default class NotificationFollow extends ImmutablePureComponent { class NotificationAdminSignup extends ImmutablePureComponent {
static propTypes = { static propTypes = {
hidden: PropTypes.bool, hidden: PropTypes.bool,
@ -26,6 +25,7 @@ export default class NotificationFollow extends ImmutablePureComponent {
account: ImmutablePropTypes.map.isRequired, account: ImmutablePropTypes.map.isRequired,
notification: ImmutablePropTypes.map.isRequired, notification: ImmutablePropTypes.map.isRequired,
unread: PropTypes.bool, unread: PropTypes.bool,
...WithRouterPropTypes,
}; };
handleMoveUp = () => { handleMoveUp = () => {
@ -43,15 +43,15 @@ export default class NotificationFollow extends ImmutablePureComponent {
}; };
handleOpenProfile = () => { handleOpenProfile = () => {
const { notification } = this.props; const { history, notification } = this.props;
this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`); history.push(`/@${notification.getIn(['account', 'acct'])}`);
}; };
handleMention = e => { handleMention = e => {
e.preventDefault(); e.preventDefault();
const { notification, onMention } = this.props; const { history, notification, onMention } = this.props;
onMention(notification.get('account'), this.context.router.history); onMention(notification.get('account'), history);
}; };
getHandlers () { getHandlers () {
@ -104,3 +104,5 @@ export default class NotificationFollow extends ImmutablePureComponent {
} }
} }
export default withRouter(NotificationAdminSignup);

View File

@ -1,24 +1,23 @@
// Package imports.
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { HotKeys } from 'react-hotkeys'; import { HotKeys } from 'react-hotkeys';
// Our imports.
import { Icon } from 'flavours/glitch/components/icon'; import { Icon } from 'flavours/glitch/components/icon';
import Permalink from 'flavours/glitch/components/permalink'; import Permalink from 'flavours/glitch/components/permalink';
import AccountContainer from 'flavours/glitch/containers/account_container'; import AccountContainer from 'flavours/glitch/containers/account_container';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import NotificationOverlayContainer from '../containers/overlay_container'; import NotificationOverlayContainer from '../containers/overlay_container';
export default class NotificationFollow extends ImmutablePureComponent { class NotificationFollow extends ImmutablePureComponent {
static propTypes = { static propTypes = {
hidden: PropTypes.bool, hidden: PropTypes.bool,
@ -26,6 +25,7 @@ export default class NotificationFollow extends ImmutablePureComponent {
account: ImmutablePropTypes.map.isRequired, account: ImmutablePropTypes.map.isRequired,
notification: ImmutablePropTypes.map.isRequired, notification: ImmutablePropTypes.map.isRequired,
unread: PropTypes.bool, unread: PropTypes.bool,
...WithRouterPropTypes,
}; };
handleMoveUp = () => { handleMoveUp = () => {
@ -43,15 +43,15 @@ export default class NotificationFollow extends ImmutablePureComponent {
}; };
handleOpenProfile = () => { handleOpenProfile = () => {
const { notification } = this.props; const { history, notification } = this.props;
this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`); history.push(`/@${notification.getIn(['account', 'acct'])}`);
}; };
handleMention = e => { handleMention = e => {
e.preventDefault(); e.preventDefault();
const { notification, onMention } = this.props; const { history, notification, onMention } = this.props;
onMention(notification.get('account'), this.context.router.history); onMention(notification.get('account'), history);
}; };
getHandlers () { getHandlers () {
@ -104,3 +104,5 @@ export default class NotificationFollow extends ImmutablePureComponent {
} }
} }
export default withRouter(NotificationFollow);

View File

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
@ -14,6 +15,7 @@ import { DisplayName } from 'flavours/glitch/components/display_name';
import { Icon } from 'flavours/glitch/components/icon'; import { Icon } from 'flavours/glitch/components/icon';
import { IconButton } from 'flavours/glitch/components/icon_button'; import { IconButton } from 'flavours/glitch/components/icon_button';
import Permalink from 'flavours/glitch/components/permalink'; import Permalink from 'flavours/glitch/components/permalink';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import NotificationOverlayContainer from '../containers/overlay_container'; import NotificationOverlayContainer from '../containers/overlay_container';
@ -31,6 +33,7 @@ class FollowRequest extends ImmutablePureComponent {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
notification: ImmutablePropTypes.map.isRequired, notification: ImmutablePropTypes.map.isRequired,
unread: PropTypes.bool, unread: PropTypes.bool,
...WithRouterPropTypes,
}; };
handleMoveUp = () => { handleMoveUp = () => {
@ -48,15 +51,15 @@ class FollowRequest extends ImmutablePureComponent {
}; };
handleOpenProfile = () => { handleOpenProfile = () => {
const { notification } = this.props; const { history, notification } = this.props;
this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`); history.push(`/@${notification.getIn(['account', 'acct'])}`);
}; };
handleMention = e => { handleMention = e => {
e.preventDefault(); e.preventDefault();
const { notification, onMention } = this.props; const { history, notification, onMention } = this.props;
onMention(notification.get('account'), this.context.router.history); onMention(notification.get('account'), history);
}; };
getHandlers () { getHandlers () {
@ -135,4 +138,4 @@ class FollowRequest extends ImmutablePureComponent {
} }
export default injectIntl(FollowRequest); export default withRouter(injectIntl(FollowRequest));

View File

@ -1,7 +1,5 @@
// Package imports.
import { connect } from 'react-redux'; import { connect } from 'react-redux';
// Our imports.
import { mentionCompose } from 'flavours/glitch/actions/compose'; import { mentionCompose } from 'flavours/glitch/actions/compose';
import { makeGetNotification } from 'flavours/glitch/selectors'; import { makeGetNotification } from 'flavours/glitch/selectors';
@ -19,8 +17,8 @@ const makeMapStateToProps = () => {
}; };
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
onMention: (account, router) => { onMention: (account, history) => {
dispatch(mentionCompose(account, router)); dispatch(mentionCompose(account, history));
}, },
}); });

View File

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
@ -15,6 +16,7 @@ import { openModal } from 'flavours/glitch/actions/modal';
import { IconButton } from 'flavours/glitch/components/icon_button'; import { IconButton } from 'flavours/glitch/components/icon_button';
import { me, boostModal } from 'flavours/glitch/initial_state'; import { me, boostModal } from 'flavours/glitch/initial_state';
import { makeGetStatus } from 'flavours/glitch/selectors'; import { makeGetStatus } from 'flavours/glitch/selectors';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
const messages = defineMessages({ const messages = defineMessages({
reply: { id: 'status.reply', defaultMessage: 'Reply' }, reply: { id: 'status.reply', defaultMessage: 'Reply' },
@ -44,7 +46,6 @@ const makeMapStateToProps = () => {
class Footer extends ImmutablePureComponent { class Footer extends ImmutablePureComponent {
static contextTypes = { static contextTypes = {
router: PropTypes.object,
identity: PropTypes.object, identity: PropTypes.object,
}; };
@ -57,17 +58,17 @@ class Footer extends ImmutablePureComponent {
showReplyCount: PropTypes.bool, showReplyCount: PropTypes.bool,
withOpenButton: PropTypes.bool, withOpenButton: PropTypes.bool,
onClose: PropTypes.func, onClose: PropTypes.func,
...WithRouterPropTypes,
}; };
_performReply = () => { _performReply = () => {
const { dispatch, status, onClose } = this.props; const { dispatch, status, onClose, history } = this.props;
const { router } = this.context;
if (onClose) { if (onClose) {
onClose(true); onClose(true);
} }
dispatch(replyCompose(status, router.history)); dispatch(replyCompose(status, history));
}; };
handleReplyClick = () => { handleReplyClick = () => {
@ -151,9 +152,7 @@ class Footer extends ImmutablePureComponent {
}; };
handleOpenClick = e => { handleOpenClick = e => {
const { router } = this.context; if (e.button !== 0 || !history) {
if (e.button !== 0 || !router) {
return; return;
} }
@ -163,7 +162,7 @@ class Footer extends ImmutablePureComponent {
onClose(); onClose();
} }
router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`); history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
}; };
render () { render () {
@ -229,4 +228,4 @@ class Footer extends ImmutablePureComponent {
} }
export default connect(makeMapStateToProps)(injectIntl(Footer)); export default withRouter(connect(makeMapStateToProps)(injectIntl(Footer)));

View File

@ -48,7 +48,6 @@ class PublicTimeline extends PureComponent {
}; };
static contextTypes = { static contextTypes = {
router: PropTypes.object,
identity: PropTypes.object, identity: PropTypes.object,
}; };

View File

@ -4,6 +4,7 @@ import { PureComponent } from 'react';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
@ -12,6 +13,7 @@ import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_cont
import { me } from 'flavours/glitch/initial_state'; import { me } from 'flavours/glitch/initial_state';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions'; import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'flavours/glitch/permissions';
import { accountAdminLink, statusAdminLink } from 'flavours/glitch/utils/backend_links'; import { accountAdminLink, statusAdminLink } from 'flavours/glitch/utils/backend_links';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
const messages = defineMessages({ const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' }, delete: { id: 'status.delete', defaultMessage: 'Delete' },
@ -46,7 +48,6 @@ const messages = defineMessages({
class ActionBar extends PureComponent { class ActionBar extends PureComponent {
static contextTypes = { static contextTypes = {
router: PropTypes.object,
identity: PropTypes.object, identity: PropTypes.object,
}; };
@ -67,6 +68,7 @@ class ActionBar extends PureComponent {
onPin: PropTypes.func, onPin: PropTypes.func,
onEmbed: PropTypes.func, onEmbed: PropTypes.func,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
...WithRouterPropTypes,
}; };
handleReplyClick = () => { handleReplyClick = () => {
@ -86,23 +88,23 @@ class ActionBar extends PureComponent {
}; };
handleDeleteClick = () => { handleDeleteClick = () => {
this.props.onDelete(this.props.status, this.context.router.history); this.props.onDelete(this.props.status, this.props.history);
}; };
handleRedraftClick = () => { handleRedraftClick = () => {
this.props.onDelete(this.props.status, this.context.router.history, true); this.props.onDelete(this.props.status, this.props.history, true);
}; };
handleEditClick = () => { handleEditClick = () => {
this.props.onEdit(this.props.status, this.context.router.history); this.props.onEdit(this.props.status, this.props.history);
}; };
handleDirectClick = () => { handleDirectClick = () => {
this.props.onDirect(this.props.status.get('account'), this.context.router.history); this.props.onDirect(this.props.status.get('account'), this.props.history);
}; };
handleMentionClick = () => { handleMentionClick = () => {
this.props.onMention(this.props.status.get('account'), this.context.router.history); this.props.onMention(this.props.status.get('account'), this.props.history);
}; };
handleMuteClick = () => { handleMuteClick = () => {
@ -234,4 +236,4 @@ class ActionBar extends PureComponent {
} }
export default injectIntl(ActionBar); export default withRouter(injectIntl(ActionBar));

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { injectIntl, FormattedDate } from 'react-intl'; import { injectIntl, FormattedDate } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { Link } from 'react-router-dom'; import { Link, withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
@ -21,20 +21,14 @@ import VisibilityIcon from 'flavours/glitch/components/status_visibility_icon';
import PollContainer from 'flavours/glitch/containers/poll_container'; import PollContainer from 'flavours/glitch/containers/poll_container';
import Audio from 'flavours/glitch/features/audio'; import Audio from 'flavours/glitch/features/audio';
import Video from 'flavours/glitch/features/video'; import Video from 'flavours/glitch/features/video';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import scheduleIdleTask from '../../ui/util/schedule_idle_task'; import scheduleIdleTask from '../../ui/util/schedule_idle_task';
import Card from './card'; import Card from './card';
class DetailedStatus extends ImmutablePureComponent { class DetailedStatus extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
status: ImmutablePropTypes.map, status: ImmutablePropTypes.map,
settings: ImmutablePropTypes.map.isRequired, settings: ImmutablePropTypes.map.isRequired,
@ -54,6 +48,7 @@ class DetailedStatus extends ImmutablePureComponent {
}), }),
onToggleMediaVisibility: PropTypes.func, onToggleMediaVisibility: PropTypes.func,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
...WithRouterPropTypes,
}; };
state = { state = {
@ -61,18 +56,18 @@ class DetailedStatus extends ImmutablePureComponent {
}; };
handleAccountClick = (e) => { handleAccountClick = (e) => {
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey) && this.context.router) { if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey) && this.props.history) {
e.preventDefault(); e.preventDefault();
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`); this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
} }
e.stopPropagation(); e.stopPropagation();
}; };
parseClick = (e, destination) => { parseClick = (e, destination) => {
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey) && this.context.router) { if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey) && this.props.history) {
e.preventDefault(); e.preventDefault();
this.context.router.history.push(destination); this.props.history.push(destination);
} }
e.stopPropagation(); e.stopPropagation();
@ -253,7 +248,7 @@ class DetailedStatus extends ImmutablePureComponent {
if (!['unlisted', 'public'].includes(status.get('visibility'))) { if (!['unlisted', 'public'].includes(status.get('visibility'))) {
reblogLink = null; reblogLink = null;
} else if (this.context.router) { } else if (this.props.history) {
reblogLink = ( reblogLink = (
<> <>
{' · '} {' · '}
@ -279,7 +274,7 @@ class DetailedStatus extends ImmutablePureComponent {
); );
} }
if (this.context.router) { if (this.props.history) {
favouriteLink = ( favouriteLink = (
<Link to={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}/favourites`} className='detailed-status__link'> <Link to={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}/favourites`} className='detailed-status__link'>
<Icon id='star' /> <Icon id='star' />
@ -344,4 +339,4 @@ class DetailedStatus extends ImmutablePureComponent {
} }
export default injectIntl(DetailedStatus); export default withRouter(injectIntl(DetailedStatus));

View File

@ -4,6 +4,7 @@ import { defineMessages, injectIntl } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { withRouter } from 'react-router-dom';
import Immutable from 'immutable'; import Immutable from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
@ -55,6 +56,7 @@ import Column from 'flavours/glitch/features/ui/components/column';
import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/initial_state'; import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/initial_state';
import { makeGetStatus, makeGetPictureInPicture } from 'flavours/glitch/selectors'; import { makeGetStatus, makeGetPictureInPicture } from 'flavours/glitch/selectors';
import { autoUnfoldCW } from 'flavours/glitch/utils/content_warning'; import { autoUnfoldCW } from 'flavours/glitch/utils/content_warning';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import ColumnHeader from '../../components/column_header'; import ColumnHeader from '../../components/column_header';
import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen'; import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen';
@ -62,6 +64,7 @@ import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from
import ActionBar from './components/action_bar'; import ActionBar from './components/action_bar';
import DetailedStatus from './components/detailed_status'; import DetailedStatus from './components/detailed_status';
const messages = defineMessages({ const messages = defineMessages({
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' }, deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
@ -182,7 +185,6 @@ const titleFromStatus = (intl, status) => {
class Status extends ImmutablePureComponent { class Status extends ImmutablePureComponent {
static contextTypes = { static contextTypes = {
router: PropTypes.object,
identity: PropTypes.object, identity: PropTypes.object,
}; };
@ -202,6 +204,7 @@ class Status extends ImmutablePureComponent {
inUse: PropTypes.bool, inUse: PropTypes.bool,
available: PropTypes.bool, available: PropTypes.bool,
}), }),
...WithRouterPropTypes
}; };
state = { state = {
@ -322,11 +325,11 @@ class Status extends ImmutablePureComponent {
message: intl.formatMessage(messages.replyMessage), message: intl.formatMessage(messages.replyMessage),
confirm: intl.formatMessage(messages.replyConfirm), confirm: intl.formatMessage(messages.replyConfirm),
onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_before_clearing_draft'], false)), onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_before_clearing_draft'], false)),
onConfirm: () => dispatch(replyCompose(status, this.context.router.history)), onConfirm: () => dispatch(replyCompose(status, this.props.history)),
}, },
})); }));
} else { } else {
dispatch(replyCompose(status, this.context.router.history)); dispatch(replyCompose(status, this.props.history));
} }
} else { } else {
dispatch(openModal({ dispatch(openModal({
@ -403,12 +406,12 @@ class Status extends ImmutablePureComponent {
this.props.dispatch(editStatus(status.get('id'), history)); this.props.dispatch(editStatus(status.get('id'), history));
}; };
handleDirectClick = (account, router) => { handleDirectClick = (account, history) => {
this.props.dispatch(directCompose(account, router)); this.props.dispatch(directCompose(account, history));
}; };
handleMentionClick = (account, router) => { handleMentionClick = (account, history) => {
this.props.dispatch(mentionCompose(account, router)); this.props.dispatch(mentionCompose(account, history));
}; };
handleOpenMedia = (media, index, lang) => { handleOpenMedia = (media, index, lang) => {
@ -530,7 +533,7 @@ class Status extends ImmutablePureComponent {
}; };
handleHotkeyOpenProfile = () => { handleHotkeyOpenProfile = () => {
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`); this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
}; };
handleMoveUp = id => { handleMoveUp = id => {
@ -783,4 +786,4 @@ class Status extends ImmutablePureComponent {
} }
export default injectIntl(connect(makeMapStateToProps)(Status)); export default withRouter(injectIntl(connect(makeMapStateToProps)(Status)));

View File

@ -26,10 +26,6 @@ class AudioModal extends ImmutablePureComponent {
onChangeBackgroundColor: PropTypes.func.isRequired, onChangeBackgroundColor: PropTypes.func.isRequired,
}; };
static contextTypes = {
router: PropTypes.object,
};
render () { render () {
const { media, status, accountStaticAvatar, onClose } = this.props; const { media, status, accountStaticAvatar, onClose } = this.props;
const options = this.props.options || {}; const options = this.props.options || {};

View File

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
@ -18,6 +19,7 @@ import { RelativeTimestamp } from 'flavours/glitch/components/relative_timestamp
import StatusContent from 'flavours/glitch/components/status_content'; import StatusContent from 'flavours/glitch/components/status_content';
import VisibilityIcon from 'flavours/glitch/components/status_visibility_icon'; import VisibilityIcon from 'flavours/glitch/components/status_visibility_icon';
import PrivacyDropdown from 'flavours/glitch/features/compose/components/privacy_dropdown'; import PrivacyDropdown from 'flavours/glitch/features/compose/components/privacy_dropdown';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
const messages = defineMessages({ const messages = defineMessages({
cancel_reblog: { id: 'status.cancel_reblog_private', defaultMessage: 'Unboost' }, cancel_reblog: { id: 'status.cancel_reblog_private', defaultMessage: 'Unboost' },
@ -39,17 +41,13 @@ const mapDispatchToProps = dispatch => {
}; };
class BoostModal extends ImmutablePureComponent { class BoostModal extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
status: ImmutablePropTypes.map.isRequired, status: ImmutablePropTypes.map.isRequired,
onReblog: PropTypes.func.isRequired, onReblog: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
missingMediaDescription: PropTypes.bool, missingMediaDescription: PropTypes.bool,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
...WithRouterPropTypes,
}; };
componentDidMount() { componentDidMount() {
@ -65,7 +63,7 @@ class BoostModal extends ImmutablePureComponent {
if (e.button === 0) { if (e.button === 0) {
e.preventDefault(); e.preventDefault();
this.props.onClose(); this.props.onClose();
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`); this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
} }
}; };
@ -137,4 +135,4 @@ class BoostModal extends ImmutablePureComponent {
} }
export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(BoostModal)); export default withRouter(connect(mapStateToProps, mapDispatchToProps)(injectIntl(BoostModal)));

View File

@ -45,11 +45,6 @@ const componentMap = {
}; };
export default class ColumnsArea extends ImmutablePureComponent { export default class ColumnsArea extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object.isRequired,
};
static propTypes = { static propTypes = {
columns: ImmutablePropTypes.list.isRequired, columns: ImmutablePropTypes.list.isRequired,
singleColumn: PropTypes.bool, singleColumn: PropTypes.bool,

View File

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
@ -15,6 +16,7 @@ import { Icon } from 'flavours/glitch/components/icon';
import { RelativeTimestamp } from 'flavours/glitch/components/relative_timestamp'; import { RelativeTimestamp } from 'flavours/glitch/components/relative_timestamp';
import StatusContent from 'flavours/glitch/components/status_content'; import StatusContent from 'flavours/glitch/components/status_content';
import VisibilityIcon from 'flavours/glitch/components/status_visibility_icon'; import VisibilityIcon from 'flavours/glitch/components/status_visibility_icon';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
const messages = defineMessages({ const messages = defineMessages({
favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }, favourite: { id: 'status.favourite', defaultMessage: 'Favourite' },
@ -22,15 +24,12 @@ const messages = defineMessages({
class FavouriteModal extends ImmutablePureComponent { class FavouriteModal extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
status: ImmutablePropTypes.map.isRequired, status: ImmutablePropTypes.map.isRequired,
onFavourite: PropTypes.func.isRequired, onFavourite: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
...WithRouterPropTypes,
}; };
componentDidMount() { componentDidMount() {
@ -46,7 +45,7 @@ class FavouriteModal extends ImmutablePureComponent {
if (e.button === 0) { if (e.button === 0) {
e.preventDefault(); e.preventDefault();
this.props.onClose(); this.props.onClose();
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`); this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
} }
}; };
@ -100,4 +99,4 @@ class FavouriteModal extends ImmutablePureComponent {
} }
export default injectIntl(FavouriteModal); export default withRouter(injectIntl(FavouriteModal));

View File

@ -1,7 +1,5 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -55,4 +53,4 @@ class ListPanel extends ImmutablePureComponent {
} }
export default withRouter(connect(mapStateToProps)(ListPanel)); export default connect(mapStateToProps)(ListPanel);

View File

@ -27,10 +27,6 @@ const messages = defineMessages({
class MediaModal extends ImmutablePureComponent { class MediaModal extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
media: ImmutablePropTypes.list.isRequired, media: ImmutablePropTypes.list.isRequired,
statusId: PropTypes.string, statusId: PropTypes.string,

View File

@ -3,7 +3,7 @@ import { Component } from 'react';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import NavigationPortal from 'flavours/glitch/components/navigation_portal'; import { NavigationPortal } from 'flavours/glitch/components/navigation_portal';
import { timelinePreview, trendsEnabled } from 'flavours/glitch/initial_state'; import { timelinePreview, trendsEnabled } from 'flavours/glitch/initial_state';
import { transientSingleColumn } from 'flavours/glitch/is_mobile'; import { transientSingleColumn } from 'flavours/glitch/is_mobile';
import { preferencesLink } from 'flavours/glitch/utils/backend_links'; import { preferencesLink } from 'flavours/glitch/utils/backend_links';
@ -36,7 +36,6 @@ const messages = defineMessages({
class NavigationPanel extends Component { class NavigationPanel extends Component {
static contextTypes = { static contextTypes = {
router: PropTypes.object.isRequired,
identity: PropTypes.object.isRequired, identity: PropTypes.object.isRequired,
}; };

View File

@ -22,6 +22,7 @@ import { expandHomeTimeline } from 'flavours/glitch/actions/timelines';
import PermaLink from 'flavours/glitch/components/permalink'; import PermaLink from 'flavours/glitch/components/permalink';
import PictureInPicture from 'flavours/glitch/features/picture_in_picture'; import PictureInPicture from 'flavours/glitch/features/picture_in_picture';
import { layoutFromWindow } from 'flavours/glitch/is_mobile'; import { layoutFromWindow } from 'flavours/glitch/is_mobile';
import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding } from '../../initial_state'; import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding } from '../../initial_state';
@ -269,8 +270,6 @@ class UI extends Component {
hasMediaAttachments: PropTypes.bool, hasMediaAttachments: PropTypes.bool,
canUploadMore: PropTypes.bool, canUploadMore: PropTypes.bool,
match: PropTypes.object.isRequired, match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
dropdownMenuIsOpen: PropTypes.bool, dropdownMenuIsOpen: PropTypes.bool,
unreadNotifications: PropTypes.number, unreadNotifications: PropTypes.number,
@ -280,6 +279,7 @@ class UI extends Component {
layout: PropTypes.string.isRequired, layout: PropTypes.string.isRequired,
firstLaunch: PropTypes.bool, firstLaunch: PropTypes.bool,
username: PropTypes.string, username: PropTypes.string,
...WithRouterPropTypes,
}; };
state = { state = {
@ -416,7 +416,7 @@ class UI extends Component {
// On first launch, redirect to the follow recommendations page // On first launch, redirect to the follow recommendations page
if (signedIn && this.props.firstLaunch) { if (signedIn && this.props.firstLaunch) {
this.context.router.history.replace('/start'); this.props.history.replace('/start');
// TODO: this.props.dispatch(closeOnboarding()); // TODO: this.props.dispatch(closeOnboarding());
} }

View File

@ -1,7 +1,7 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Component, PureComponent, cloneElement, Children } from 'react'; import { Component, cloneElement, Children } from 'react';
import { Switch, Route } from 'react-router-dom'; import { Switch, Route, useLocation } from 'react-router-dom';
import StackTrace from 'stacktrace-js'; import StackTrace from 'stacktrace-js';
@ -10,27 +10,20 @@ import ColumnLoading from 'flavours/glitch/features/ui/components/column_loading
import BundleContainer from 'flavours/glitch/features/ui/containers/bundle_container'; import BundleContainer from 'flavours/glitch/features/ui/containers/bundle_container';
// Small wrapper to pass multiColumn to the route components // Small wrapper to pass multiColumn to the route components
export class WrappedSwitch extends PureComponent { export const WrappedSwitch = ({ multiColumn, children }) => {
static contextTypes = { const location = useLocation();
router: PropTypes.object,
};
render () { const decklessLocation = multiColumn && location.pathname.startsWith('/deck')
const { multiColumn, children } = this.props; ? {...location, pathname: location.pathname.slice(5)}
const { location } = this.context.router.route; : location;
const decklessLocation = multiColumn && location.pathname.startsWith('/deck') return (
? {...location, pathname: location.pathname.slice(5)} <Switch location={decklessLocation}>
: location; {Children.map(children, child => child ? cloneElement(child, { multiColumn }) : null)}
</Switch>
);
};
return (
<Switch location={decklessLocation}>
{Children.map(children, child => child ? cloneElement(child, { multiColumn }) : null)}
</Switch>
);
}
}
WrappedSwitch.propTypes = { WrappedSwitch.propTypes = {
multiColumn: PropTypes.bool, multiColumn: PropTypes.bool,

View File

@ -1,7 +0,0 @@
// Focuses the root element.
export function focusRoot () {
let e;
if (document && (e = document.querySelector('.ui')) && (e = e.parentElement)) {
e.focus();
}
}

View File

@ -0,0 +1,60 @@
import PropTypes from "prop-types";
import { __RouterContext } from "react-router";
import hoistStatics from "hoist-non-react-statics";
export const WithRouterPropTypes = {
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
};
export const WithOptionalRouterPropTypes = {
match: PropTypes.object,
location: PropTypes.object,
history: PropTypes.object,
};
// This is copied from https://github.com/remix-run/react-router/blob/v5.3.4/packages/react-router/modules/withRouter.js
// but does not fail if called outside of a React Router context
export function withOptionalRouter(Component) {
const displayName = `withRouter(${Component.displayName || Component.name})`;
const C = props => {
const { wrappedComponentRef, ...remainingProps } = props;
return (
<__RouterContext.Consumer>
{context => {
if(context)
return (
<Component
{...remainingProps}
{...context}
ref={wrappedComponentRef}
/>
);
else
return (
<Component
{...remainingProps}
ref={wrappedComponentRef}
/>
);
}}
</__RouterContext.Consumer>
);
};
C.displayName = displayName;
C.WrappedComponent = Component;
C.propTypes = {
wrappedComponentRef: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
PropTypes.object
])
};
return hoistStatics(C, Component);
}