-
+
{name ? <>#{name}> : }
-
+
{description ? (
{description}
@@ -104,6 +107,7 @@ const Hashtag = ({ name, to, people, uses, history, className, description, with
Hashtag.propTypes = {
name: PropTypes.string,
+ href: PropTypes.string,
to: PropTypes.string,
people: PropTypes.number,
description: PropTypes.node,
diff --git a/app/javascript/mastodon/components/permalink.jsx b/app/javascript/mastodon/components/permalink.jsx
new file mode 100644
index 00000000000000..7bd0f61e4cca6a
--- /dev/null
+++ b/app/javascript/mastodon/components/permalink.jsx
@@ -0,0 +1,40 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+
+export default class Permalink extends React.PureComponent {
+
+ static contextTypes = {
+ router: PropTypes.object,
+ };
+
+ static propTypes = {
+ className: PropTypes.string,
+ href: PropTypes.string.isRequired,
+ to: PropTypes.string.isRequired,
+ children: PropTypes.node,
+ onInterceptClick: PropTypes.func,
+ };
+
+ handleClick = e => {
+ if (this.props.onInterceptClick && this.props.onInterceptClick()) {
+ e.preventDefault();
+ return;
+ }
+
+ if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
+ e.preventDefault();
+ this.context.router.history.push(this.props.to);
+ }
+ }
+
+ render () {
+ const { href, children, className, onInterceptClick, ...other } = this.props;
+
+ return (
+
+ {children}
+
+ );
+ }
+
+}
diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx
index 4a5ad54a1c99bc..dd4f37ee4b879f 100644
--- a/app/javascript/mastodon/components/status.jsx
+++ b/app/javascript/mastodon/components/status.jsx
@@ -417,7 +417,7 @@ class Status extends ImmutablePureComponent {
prepend = (
);
@@ -438,7 +438,7 @@ class Status extends ImmutablePureComponent {
prepend = (
);
}
@@ -558,12 +558,12 @@ class Status extends ImmutablePureComponent {
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
-
+
{status.get('edited_at') && *}
-
+
{statusAvatar}
diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx
index d3bbc1ba023e3f..659e086ff141f7 100644
--- a/app/javascript/mastodon/components/status_content.jsx
+++ b/app/javascript/mastodon/components/status_content.jsx
@@ -4,7 +4,7 @@ import { PureComponent } from 'react';
import { FormattedMessage, injectIntl } from 'react-intl';
import classnames from 'classnames';
-import { Link } from 'react-router-dom';
+
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
@@ -13,6 +13,8 @@ import { Icon } from 'mastodon/components/icon';
import PollContainer from 'mastodon/containers/poll_container';
import { autoPlayGif, languages as preloadedLanguages } from 'mastodon/initial_state';
+import Permalink from './permalink';
+
const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
/**
@@ -270,9 +272,9 @@ class StatusContent extends PureComponent {
let mentionsPlaceholder = '';
const mentionLinks = status.get('mentions').map(item => (
-
+
@{item.get('username')}
-
+
)).reduce((aggregate, item) => [...aggregate, item, ' '], []);
const toggleText = hidden ? : ;
diff --git a/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx b/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx
index 2c996ff769d4d0..44e4485e347206 100644
--- a/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx
+++ b/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx
@@ -1,12 +1,12 @@
import { FormattedMessage } from 'react-intl';
-import { Link } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { AvatarOverlay } from '../../../components/avatar_overlay';
import { DisplayName } from '../../../components/display_name';
+import Permalink from '../../../components/permalink';
export default class MovedNote extends ImmutablePureComponent {
@@ -25,12 +25,12 @@ export default class MovedNote extends ImmutablePureComponent {
);
diff --git a/app/javascript/mastodon/features/compose/components/navigation_bar.jsx b/app/javascript/mastodon/features/compose/components/navigation_bar.jsx
index 5af38da43cf4f0..6241f96ca36cd4 100644
--- a/app/javascript/mastodon/features/compose/components/navigation_bar.jsx
+++ b/app/javascript/mastodon/features/compose/components/navigation_bar.jsx
@@ -2,12 +2,12 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
-import { Link } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { Avatar } from '../../../components/avatar';
+import Permalink from '../../../components/permalink';
import ActionBar from './action_bar';
@@ -23,16 +23,16 @@ export default class NavigationBar extends ImmutablePureComponent {
const username = this.props.account.get('acct')
return (
-
+
{username}
-
+
-
+
@{username}
-
+
diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
index bf0a9da95aad91..4233cc8daa83f8 100644
--- a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
+++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames';
-import { Link } from 'react-router-dom';
+
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
@@ -13,6 +13,7 @@ import { HotKeys } from 'react-hotkeys';
import AttachmentList from 'mastodon/components/attachment_list';
import AvatarComposite from 'mastodon/components/avatar_composite';
import { IconButton } from 'mastodon/components/icon_button';
+import Permalink from 'mastodon/components/permalink';
import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
import StatusContent from 'mastodon/components/status_content';
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
@@ -136,7 +137,7 @@ class Conversation extends ImmutablePureComponent {
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDelete });
- const names = accounts.map(a => ).reduce((prev, cur) => [prev, ', ', cur]);
+ const names = accounts.map(a => ).reduce((prev, cur) => [prev, ', ', cur]);
const handlers = {
reply: this.handleReply,
diff --git a/app/javascript/mastodon/features/directory/components/account_card.jsx b/app/javascript/mastodon/features/directory/components/account_card.jsx
index 0306b63d322077..b0520ca3369e5e 100644
--- a/app/javascript/mastodon/features/directory/components/account_card.jsx
+++ b/app/javascript/mastodon/features/directory/components/account_card.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
import classNames from 'classnames';
-import { Link } from 'react-router-dom';
+
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
@@ -19,6 +19,7 @@ import { openModal } from 'mastodon/actions/modal';
import { Avatar } from 'mastodon/components/avatar';
import Button from 'mastodon/components/button';
import { DisplayName } from 'mastodon/components/display_name';
+import Permalink from 'mastodon/components/permalink';
import { ShortNumber } from 'mastodon/components/short_number';
import { autoPlayGif, me, unfollowModal } from 'mastodon/initial_state';
import { makeGetAccount } from 'mastodon/selectors';
@@ -174,7 +175,7 @@ class AccountCard extends ImmutablePureComponent {
return (
-
+
{account.get('note').length > 0 && (
-
+
-
+
diff --git a/app/javascript/mastodon/features/notifications/components/notification.jsx b/app/javascript/mastodon/features/notifications/components/notification.jsx
index 43c5e85cef8618..509e48b80cdcd7 100644
--- a/app/javascript/mastodon/features/notifications/components/notification.jsx
+++ b/app/javascript/mastodon/features/notifications/components/notification.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { injectIntl, FormattedMessage, defineMessages } from 'react-intl';
import classNames from 'classnames';
-import { Link } from 'react-router-dom';
+
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
@@ -11,6 +11,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { HotKeys } from 'react-hotkeys';
import { Icon } from 'mastodon/components/icon';
+import Permalink from 'mastodon/components/permalink';
import AccountContainer from 'mastodon/containers/account_container';
import StatusContainer from 'mastodon/containers/status_container';
import { me } from 'mastodon/initial_state';
@@ -398,7 +399,7 @@ class Notification extends ImmutablePureComponent {
const targetAccount = report.get('target_account');
const targetDisplayNameHtml = { __html: targetAccount.get('display_name_html') };
- const targetLink =
;
+ const targetLink =
;
return (
@@ -423,7 +424,7 @@ class Notification extends ImmutablePureComponent {
const { notification } = this.props;
const account = notification.get('account');
const displayNameHtml = { __html: account.get('display_name_html') };
- const link = ;
+ const link = ;
switch(notification.get('type')) {
case 'follow':
diff --git a/app/javascript/mastodon/features/ui/components/header.jsx b/app/javascript/mastodon/features/ui/components/header.jsx
index 68484b59ab0f5e..3a6b7e30c76b0a 100644
--- a/app/javascript/mastodon/features/ui/components/header.jsx
+++ b/app/javascript/mastodon/features/ui/components/header.jsx
@@ -5,6 +5,7 @@ import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import { Link, withRouter } from 'react-router-dom';
+
import { connect } from 'react-redux';
import { openModal } from 'mastodon/actions/modal';
@@ -12,14 +13,15 @@ import { fetchServer } from 'mastodon/actions/server';
import { Avatar } from 'mastodon/components/avatar';
import { Icon } from 'mastodon/components/icon';
import { WordmarkLogo, SymbolLogo } from 'mastodon/components/logo';
+import Permalink from 'mastodon/components/permalink';
import { registrationsOpen, me, sso_redirect } from 'mastodon/initial_state';
const Account = connect(state => ({
account: state.getIn(['accounts', me]),
}))(({ account }) => (
-
+
-
+
));
const messages = defineMessages({