Merge pull request #159 from kmycode/upstream-20231021
Upstream 20231021
This commit is contained in:
commit
551a9e8216
133 changed files with 1159 additions and 817 deletions
|
@ -236,7 +236,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
// Common React utilities
|
// Common React utilities
|
||||||
{
|
{
|
||||||
pattern: '{classnames,react-helmet,react-router-dom}',
|
pattern: '{classnames,react-helmet,react-router,react-router-dom}',
|
||||||
group: 'external',
|
group: 'external',
|
||||||
position: 'before',
|
position: 'before',
|
||||||
},
|
},
|
||||||
|
|
1
.github/workflows/test-ruby.yml
vendored
1
.github/workflows/test-ruby.yml
vendored
|
@ -114,6 +114,7 @@ jobs:
|
||||||
BUNDLE_WITH: 'pam_authentication test'
|
BUNDLE_WITH: 'pam_authentication test'
|
||||||
CI_JOBS: ${{ matrix.ci_job }}/4
|
CI_JOBS: ${{ matrix.ci_job }}/4
|
||||||
ES_ENABLED: false
|
ES_ENABLED: false
|
||||||
|
GITHUB_RSPEC: ${{ matrix.ruby-version == '.ruby-version' && github.event.pull_request && 'true' }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
|
@ -48,27 +48,6 @@ Lint/UnusedBlockArgument:
|
||||||
- 'config/initializers/paperclip.rb'
|
- 'config/initializers/paperclip.rb'
|
||||||
- 'config/initializers/simple_form.rb'
|
- 'config/initializers/simple_form.rb'
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
||||||
Lint/UselessAssignment:
|
|
||||||
Exclude:
|
|
||||||
- 'app/services/activitypub/process_status_update_service.rb'
|
|
||||||
- 'config/initializers/3_omniauth.rb'
|
|
||||||
- 'db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb'
|
|
||||||
- 'db/post_migrate/20190511152737_remove_suspended_silenced_account_fields.rb'
|
|
||||||
- 'spec/controllers/api/v1/favourites_controller_spec.rb'
|
|
||||||
- 'spec/controllers/concerns/account_controller_concern_spec.rb'
|
|
||||||
- 'spec/helpers/jsonld_helper_spec.rb'
|
|
||||||
- 'spec/models/account_spec.rb'
|
|
||||||
- 'spec/models/domain_block_spec.rb'
|
|
||||||
- 'spec/models/status_spec.rb'
|
|
||||||
- 'spec/models/user_spec.rb'
|
|
||||||
- 'spec/models/webauthn_credentials_spec.rb'
|
|
||||||
- 'spec/services/account_search_service_spec.rb'
|
|
||||||
- 'spec/services/post_status_service_spec.rb'
|
|
||||||
- 'spec/services/precompute_feed_service_spec.rb'
|
|
||||||
- 'spec/services/resolve_url_service_spec.rb'
|
|
||||||
- 'spec/views/statuses/show.html.haml_spec.rb'
|
|
||||||
|
|
||||||
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
Max: 144
|
Max: 144
|
||||||
|
@ -86,26 +65,6 @@ Metrics/CyclomaticComplexity:
|
||||||
Metrics/PerceivedComplexity:
|
Metrics/PerceivedComplexity:
|
||||||
Max: 27
|
Max: 27
|
||||||
|
|
||||||
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
|
|
||||||
# SupportedStyles: snake_case, normalcase, non_integer
|
|
||||||
# AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
|
|
||||||
Naming/VariableNumber:
|
|
||||||
Exclude:
|
|
||||||
- 'db/migrate/20180106000232_add_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb'
|
|
||||||
- 'db/migrate/20180514140000_revert_index_change_on_statuses_for_api_v1_accounts_account_id_statuses.rb'
|
|
||||||
- 'db/migrate/20190820003045_update_statuses_index.rb'
|
|
||||||
- 'db/migrate/20190823221802_add_local_index_to_statuses.rb'
|
|
||||||
- 'db/migrate/20200119112504_add_public_index_to_statuses.rb'
|
|
||||||
- 'spec/models/account_spec.rb'
|
|
||||||
- 'spec/models/domain_block_spec.rb'
|
|
||||||
- 'spec/models/user_spec.rb'
|
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
||||||
# Configuration parameters: SafeMultiline.
|
|
||||||
Performance/DeletePrefix:
|
|
||||||
Exclude:
|
|
||||||
- 'app/models/featured_tag.rb'
|
|
||||||
|
|
||||||
Performance/MapMethodChain:
|
Performance/MapMethodChain:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/feed.rb'
|
- 'app/models/feed.rb'
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Apps::CredentialsController < Api::BaseController
|
class Api::V1::Apps::CredentialsController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :read }
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer, fields: %i(name website vapid_key)
|
return doorkeeper_render_error unless valid_doorkeeper_token?
|
||||||
|
|
||||||
|
render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer, fields: %i(name website vapid_key client_id scopes)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
19
app/helpers/admin/disputes_helper.rb
Normal file
19
app/helpers/admin/disputes_helper.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Admin
|
||||||
|
module DisputesHelper
|
||||||
|
def strike_action_label(appeal)
|
||||||
|
t(key_for_action(appeal),
|
||||||
|
scope: 'admin.strikes.actions',
|
||||||
|
name: content_tag(:span, appeal.strike.account.username, class: 'username'),
|
||||||
|
target: content_tag(:span, appeal.account.username, class: 'target'))
|
||||||
|
.html_safe
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def key_for_action(appeal)
|
||||||
|
AccountWarning.actions.slice(appeal.strike.action).keys.first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,6 +9,10 @@ module FormattingHelper
|
||||||
TextFormatter.new(text, options).to_s
|
TextFormatter.new(text, options).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def url_for_preview_card(preview_card)
|
||||||
|
preview_card.url
|
||||||
|
end
|
||||||
|
|
||||||
def extract_status_plain_text(status)
|
def extract_status_plain_text(status)
|
||||||
PlainTextFormatter.new(status.text, status.local?).to_s
|
PlainTextFormatter.new(status.text, status.local?).to_s
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { render, fireEvent, screen } from '@testing-library/react';
|
import { render, fireEvent, screen } from '@testing-library/react';
|
||||||
import renderer from 'react-test-renderer';
|
import renderer from 'react-test-renderer';
|
||||||
|
|
||||||
import Button from '../button';
|
import { Button } from '../button';
|
||||||
|
|
||||||
describe('<Button />', () => {
|
describe('<Button />', () => {
|
||||||
it('renders a button element', () => {
|
it('renders a button element', () => {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { VerifiedBadge } from 'mastodon/components/verified_badge';
|
||||||
import { me } from '../initial_state';
|
import { me } from '../initial_state';
|
||||||
|
|
||||||
import { Avatar } from './avatar';
|
import { Avatar } from './avatar';
|
||||||
import Button from './button';
|
import { Button } from './button';
|
||||||
import { FollowersCounter } from './counters';
|
import { FollowersCounter } from './counters';
|
||||||
import { DisplayName } from './display_name';
|
import { DisplayName } from './display_name';
|
||||||
import { IconButton } from './icon_button';
|
import { IconButton } from './icon_button';
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { PureComponent } from 'react';
|
|
||||||
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
export default class Button extends PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
text: PropTypes.node,
|
|
||||||
type: PropTypes.string,
|
|
||||||
onClick: PropTypes.func,
|
|
||||||
disabled: PropTypes.bool,
|
|
||||||
block: PropTypes.bool,
|
|
||||||
secondary: PropTypes.bool,
|
|
||||||
className: PropTypes.string,
|
|
||||||
title: PropTypes.string,
|
|
||||||
children: PropTypes.node,
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
type: 'button',
|
|
||||||
};
|
|
||||||
|
|
||||||
handleClick = (e) => {
|
|
||||||
if (!this.props.disabled && this.props.onClick) {
|
|
||||||
this.props.onClick(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
setRef = (c) => {
|
|
||||||
this.node = c;
|
|
||||||
};
|
|
||||||
|
|
||||||
focus() {
|
|
||||||
this.node.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const className = classNames('button', this.props.className, {
|
|
||||||
'button-secondary': this.props.secondary,
|
|
||||||
'button--block': this.props.block,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
className={className}
|
|
||||||
disabled={this.props.disabled}
|
|
||||||
onClick={this.handleClick}
|
|
||||||
ref={this.setRef}
|
|
||||||
title={this.props.title}
|
|
||||||
type={this.props.type}
|
|
||||||
>
|
|
||||||
{this.props.text || this.props.children}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
58
app/javascript/mastodon/components/button.tsx
Normal file
58
app/javascript/mastodon/components/button.tsx
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
interface BaseProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
|
block?: boolean;
|
||||||
|
secondary?: boolean;
|
||||||
|
text?: JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PropsWithChildren extends BaseProps {
|
||||||
|
text?: never;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PropsWithText extends BaseProps {
|
||||||
|
text: JSX.Element;
|
||||||
|
children: never;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = PropsWithText | PropsWithChildren;
|
||||||
|
|
||||||
|
export const Button: React.FC<Props> = ({
|
||||||
|
text,
|
||||||
|
type = 'button',
|
||||||
|
onClick,
|
||||||
|
disabled,
|
||||||
|
block,
|
||||||
|
secondary,
|
||||||
|
className,
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
const handleClick = useCallback<React.MouseEventHandler<HTMLButtonElement>>(
|
||||||
|
(e) => {
|
||||||
|
if (!disabled && onClick) {
|
||||||
|
onClick(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[disabled, onClick],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={classNames('button', className, {
|
||||||
|
'button-secondary': secondary,
|
||||||
|
'button--block': block,
|
||||||
|
})}
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={handleClick}
|
||||||
|
title={title}
|
||||||
|
type={type}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{text ?? children}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
|
@ -4,29 +4,28 @@ import { createPortal } from 'react-dom';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/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,
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
const { router } = this.context;
|
const { onClick, history } = this.props;
|
||||||
const { onClick } = this.props;
|
|
||||||
|
|
||||||
if (onClick) {
|
if (onClick) {
|
||||||
onClick();
|
onClick();
|
||||||
} else if (router.history.location?.state?.fromMastodon) {
|
} else if (history.location?.state?.fromMastodon) {
|
||||||
router.history.goBack();
|
history.goBack();
|
||||||
} else {
|
} else {
|
||||||
router.history.push('/');
|
history.push('/');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -60,3 +59,5 @@ export default class ColumnBackButton extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withRouter(ColumnBackButton);
|
||||||
|
|
|
@ -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 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/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));
|
||||||
|
|
|
@ -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 'mastodon/components/circular_progress';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/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);
|
||||||
|
|
|
@ -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 'mastodon/utils/react_router';
|
||||||
|
|
||||||
static contextTypes = {
|
class ModalRoot extends PureComponent {
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
|
@ -20,6 +19,7 @@ export default class ModalRoot extends PureComponent {
|
||||||
b: PropTypes.number,
|
b: PropTypes.number,
|
||||||
}),
|
}),
|
||||||
ignoreFocus: PropTypes.bool,
|
ignoreFocus: PropTypes.bool,
|
||||||
|
...WithOptionalRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
activeElement = this.props.children ? document.activeElement : null;
|
activeElement = this.props.children ? document.activeElement : null;
|
||||||
|
@ -55,7 +55,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||||
|
@ -156,3 +156,5 @@ export default class ModalRoot extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withOptionalRouter(ModalRoot);
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
import { PureComponent } from 'react';
|
|
||||||
|
|
||||||
import { Switch, Route, withRouter } from 'react-router-dom';
|
|
||||||
|
|
||||||
import AccountNavigation from 'mastodon/features/account/navigation';
|
|
||||||
import Trends from 'mastodon/features/getting_started/containers/trends_container';
|
|
||||||
import { showTrends } from 'mastodon/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);
|
|
25
app/javascript/mastodon/components/navigation_portal.tsx
Normal file
25
app/javascript/mastodon/components/navigation_portal.tsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { Switch, Route } from 'react-router-dom';
|
||||||
|
|
||||||
|
import AccountNavigation from 'mastodon/features/account/navigation';
|
||||||
|
import Trends from 'mastodon/features/getting_started/containers/trends_container';
|
||||||
|
import { showTrends } from 'mastodon/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>
|
||||||
|
);
|
|
@ -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 'mastodon/is_mobile';
|
import { layoutFromWindow } from 'mastodon/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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,12 +35,33 @@ 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,
|
||||||
onLoadMore: PropTypes.func,
|
onLoadMore: PropTypes.func,
|
||||||
|
@ -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, child.type.name === 'ColumnLink' ? {} : {
|
{cloneElement(child, child.type.name === 'ColumnLink' ? {} : {
|
||||||
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}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { HotKeys } from 'react-hotkeys';
|
||||||
import AttachmentList from 'mastodon/components/attachment_list';
|
import AttachmentList from 'mastodon/components/attachment_list';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
|
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
|
||||||
|
import { withOptionalRouter, WithOptionalRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
import CompactedStatusContainer from '../containers/compacted_status_container';
|
import CompactedStatusContainer from '../containers/compacted_status_container';
|
||||||
import Card from '../features/status/components/card';
|
import Card from '../features/status/components/card';
|
||||||
|
@ -81,10 +82,6 @@ const messages = defineMessages({
|
||||||
|
|
||||||
class Status extends ImmutablePureComponent {
|
class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
status: ImmutablePropTypes.map,
|
status: ImmutablePropTypes.map,
|
||||||
account: ImmutablePropTypes.map,
|
account: ImmutablePropTypes.map,
|
||||||
|
@ -130,6 +127,7 @@ class Status extends ImmutablePureComponent {
|
||||||
available: PropTypes.bool,
|
available: PropTypes.bool,
|
||||||
}),
|
}),
|
||||||
withoutEmojiReactions: PropTypes.bool,
|
withoutEmojiReactions: PropTypes.bool,
|
||||||
|
...WithOptionalRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Avoid checking props that are functions (and whose equality will always
|
// Avoid checking props that are functions (and whose equality will always
|
||||||
|
@ -272,7 +270,7 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
handleHotkeyReply = e => {
|
handleHotkeyReply = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.onReply(this._properStatus(), this.context.router.history);
|
this.props.onReply(this._properStatus(), this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyFavourite = () => {
|
handleHotkeyFavourite = () => {
|
||||||
|
@ -285,7 +283,7 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
handleHotkeyMention = e => {
|
handleHotkeyMention = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.onMention(this._properStatus().get('account'), this.context.router.history);
|
this.props.onMention(this._properStatus().get('account'), this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyOpen = () => {
|
handleHotkeyOpen = () => {
|
||||||
|
@ -294,14 +292,14 @@ class Status extends ImmutablePureComponent {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { router } = this.context;
|
const { history } = this.props;
|
||||||
const status = this._properStatus();
|
const status = this._properStatus();
|
||||||
|
|
||||||
if (!router) {
|
if (!history) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
|
history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyOpenProfile = () => {
|
handleHotkeyOpenProfile = () => {
|
||||||
|
@ -309,14 +307,14 @@ class Status extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
_openProfile = (proper = true) => {
|
_openProfile = (proper = true) => {
|
||||||
const { router } = this.context;
|
const { history } = this.props;
|
||||||
const status = proper ? this._properStatus() : this.props.status;
|
const status = proper ? this._properStatus() : this.props.status;
|
||||||
|
|
||||||
if (!router) {
|
if (!history) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
router.history.push(`/@${status.getIn(['account', 'acct'])}`);
|
history.push(`/@${status.getIn(['account', 'acct'])}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyMoveUp = e => {
|
handleHotkeyMoveUp = e => {
|
||||||
|
@ -686,4 +684,4 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(Status);
|
export default withOptionalRouter(injectIntl(Status));
|
||||||
|
|
|
@ -3,12 +3,14 @@ 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';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
|
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
|
|
||||||
import DropdownMenuContainer from '../containers/dropdown_menu_container';
|
import DropdownMenuContainer from '../containers/dropdown_menu_container';
|
||||||
|
@ -70,7 +72,6 @@ const mapStateToProps = (state, { status }) => ({
|
||||||
class StatusActionBar extends ImmutablePureComponent {
|
class StatusActionBar extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,6 +107,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
withCounters: PropTypes.bool,
|
withCounters: 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
|
||||||
|
@ -120,7 +122,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);
|
||||||
}
|
}
|
||||||
|
@ -187,15 +189,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 = () => {
|
||||||
|
@ -203,11 +205,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 = () => {
|
||||||
|
@ -247,7 +249,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleOpen = () => {
|
handleOpen = () => {
|
||||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`);
|
this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleOpenMentions = () => {
|
handleOpenMentions = () => {
|
||||||
|
@ -477,4 +479,4 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(injectIntl(StatusActionBar));
|
export default withRouter(connect(mapStateToProps)(injectIntl(StatusActionBar)));
|
||||||
|
|
|
@ -4,7 +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 { 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 { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -68,7 +68,6 @@ const mapStateToProps = state => ({
|
||||||
class StatusContent extends PureComponent {
|
class StatusContent extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,6 +82,10 @@ class StatusContent extends PureComponent {
|
||||||
onCollapsedToggle: PropTypes.func,
|
onCollapsedToggle: PropTypes.func,
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -173,18 +176,18 @@ class StatusContent extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
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}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -252,7 +255,7 @@ class StatusContent extends PureComponent {
|
||||||
const spoilerContent = { __html: status.getIn(['translation', 'spoilerHtml']) || status.get('spoilerHtml') };
|
const spoilerContent = { __html: status.getIn(['translation', 'spoilerHtml']) || status.get('spoilerHtml') };
|
||||||
const language = status.getIn(['translation', 'language']) || status.get('language');
|
const language = status.getIn(['translation', 'language']) || status.get('language');
|
||||||
const classNames = classnames('status__content', {
|
const classNames = classnames('status__content', {
|
||||||
'status__content--with-action': this.props.onClick && this.context.router,
|
'status__content--with-action': this.props.onClick && this.props.history,
|
||||||
'status__content--with-spoiler': status.get('spoiler_text').length > 0,
|
'status__content--with-spoiler': status.get('spoiler_text').length > 0,
|
||||||
'status__content--collapsed': renderReadMore,
|
'status__content--collapsed': renderReadMore,
|
||||||
});
|
});
|
||||||
|
@ -329,4 +332,4 @@ class StatusContent extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(injectIntl(StatusContent));
|
export default withRouter(connect(mapStateToProps)(injectIntl(StatusContent)));
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -4,14 +4,14 @@ 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 { 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 { Avatar } from 'mastodon/components/avatar';
|
import { Avatar } from 'mastodon/components/avatar';
|
||||||
import { Badge, AutomatedBadge, GroupBadge } from 'mastodon/components/badge';
|
import { Badge, AutomatedBadge, GroupBadge } from 'mastodon/components/badge';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { FollowersCounter, FollowingCounter, StatusesCounter } from 'mastodon/components/counters';
|
import { FollowersCounter, FollowingCounter, StatusesCounter } from 'mastodon/components/counters';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { IconButton } from 'mastodon/components/icon_button';
|
import { IconButton } from 'mastodon/components/icon_button';
|
||||||
|
@ -19,6 +19,7 @@ import { ShortNumber } from 'mastodon/components/short_number';
|
||||||
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
||||||
import { autoPlayGif, me, domain } from 'mastodon/initial_state';
|
import { autoPlayGif, me, domain } from 'mastodon/initial_state';
|
||||||
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
|
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/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';
|
||||||
|
@ -86,11 +87,6 @@ const dateFormatOptions = {
|
||||||
|
|
||||||
class Header extends ImmutablePureComponent {
|
class Header extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
identity: PropTypes.object,
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
account: ImmutablePropTypes.map,
|
account: ImmutablePropTypes.map,
|
||||||
identity_props: ImmutablePropTypes.list,
|
identity_props: ImmutablePropTypes.list,
|
||||||
|
@ -117,6 +113,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,
|
||||||
};
|
};
|
||||||
|
|
||||||
setRef = c => {
|
setRef = c => {
|
||||||
|
@ -179,25 +180,24 @@ class Header extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHashtagClick = e => {
|
handleHashtagClick = e => {
|
||||||
const { router } = this.context;
|
const { history } = this.props;
|
||||||
const value = e.currentTarget.textContent.replace(/^#/, '');
|
const value = e.currentTarget.textContent.replace(/^#/, '');
|
||||||
|
|
||||||
if (router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
if (history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
router.history.push(`/tags/${value}`);
|
history.push(`/tags/${value}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMentionClick = e => {
|
handleMentionClick = e => {
|
||||||
const { router } = this.context;
|
const { history, onOpenURL } = this.props;
|
||||||
const { onOpenURL } = this.props;
|
|
||||||
|
|
||||||
if (router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
if (history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const link = e.currentTarget;
|
const link = e.currentTarget;
|
||||||
|
|
||||||
onOpenURL(link.href, router.history, () => {
|
onOpenURL(link.href, history, () => {
|
||||||
window.location = link.href;
|
window.location = link.href;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -506,4 +506,4 @@ class Header extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(Header);
|
export default withRouter(injectIntl(Header));
|
||||||
|
|
|
@ -2,17 +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 { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
import InnerHeader from '../../account/components/header';
|
import InnerHeader from '../../account/components/header';
|
||||||
|
|
||||||
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,
|
||||||
|
@ -37,10 +39,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 = () => {
|
||||||
|
@ -52,11 +51,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 = () => {
|
||||||
|
@ -177,3 +176,5 @@ export default class Header extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default withRouter(Header);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { FormattedMessage } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { revealAccount } from 'mastodon/actions/accounts';
|
import { revealAccount } from 'mastodon/actions/accounts';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { domain } from 'mastodon/initial_state';
|
import { domain } from 'mastodon/initial_state';
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch, { accountId }) => ({
|
const mapDispatchToProps = (dispatch, { accountId }) => ({
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { injectIntl } from 'react-intl';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { IconButton } from 'mastodon/components/icon_button';
|
import { IconButton } from 'mastodon/components/icon_button';
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ import {
|
||||||
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
|
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
|
||||||
import { fetchLists } from 'mastodon/actions/lists';
|
import { fetchLists } from 'mastodon/actions/lists';
|
||||||
import { openModal } from 'mastodon/actions/modal';
|
import { openModal } from 'mastodon/actions/modal';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import Column from 'mastodon/components/column';
|
import Column from 'mastodon/components/column';
|
||||||
import ColumnHeader from 'mastodon/components/column_header';
|
import ColumnHeader from 'mastodon/components/column_header';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { changeAntennaEditorTitle, submitAntennaEditor } from 'mastodon/actions/antennas';
|
import { changeAntennaEditorTitle, submitAntennaEditor } from 'mastodon/actions/antennas';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
label: { id: 'antennas.new.title_placeholder', defaultMessage: 'New antenna title' },
|
label: { id: 'antennas.new.title_placeholder', defaultMessage: 'New antenna title' },
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { changeBookmarkCategoryEditorTitle, submitBookmarkCategoryEditor } from 'mastodon/actions/bookmark_categories';
|
import { changeBookmarkCategoryEditorTitle, submitBookmarkCategoryEditor } from 'mastodon/actions/bookmark_categories';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
label: { id: 'bookmark_categories.new.title_placeholder', defaultMessage: 'New category title' },
|
label: { id: 'bookmark_categories.new.title_placeholder', defaultMessage: 'New category title' },
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { changeCircleEditorTitle, submitCircleEditor } from 'mastodon/actions/circles';
|
import { changeCircleEditorTitle, submitCircleEditor } from 'mastodon/actions/circles';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
label: { id: 'circles.new.title_placeholder', defaultMessage: 'New circle title' },
|
label: { id: 'circles.new.title_placeholder', defaultMessage: 'New circle title' },
|
||||||
|
|
|
@ -39,7 +39,6 @@ const mapStateToProps = (state, { columnId }) => {
|
||||||
class CommunityTimeline extends PureComponent {
|
class CommunityTimeline extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,11 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { length } from 'stringz';
|
import { length } from 'stringz';
|
||||||
|
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
|
import { WithOptionalRouterPropTypes, withOptionalRouter } from 'mastodon/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';
|
||||||
import Button from '../../../components/button';
|
import { Button } from '../../../components/button';
|
||||||
import CircleSelectContainer from '../containers/circle_select_container';
|
import CircleSelectContainer from '../containers/circle_select_container';
|
||||||
import EmojiPickerDropdown from '../containers/emoji_picker_dropdown_container';
|
import EmojiPickerDropdown from '../containers/emoji_picker_dropdown_container';
|
||||||
import ExpirationDropdownContainer from '../containers/expiration_dropdown_container';
|
import ExpirationDropdownContainer from '../containers/expiration_dropdown_container';
|
||||||
|
@ -43,11 +44,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.isRequired,
|
text: PropTypes.string.isRequired,
|
||||||
|
@ -78,6 +74,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
singleColumn: PropTypes.bool,
|
singleColumn: PropTypes.bool,
|
||||||
lang: PropTypes.string,
|
lang: PropTypes.string,
|
||||||
circleId: PropTypes.string,
|
circleId: PropTypes.string,
|
||||||
|
...WithOptionalRouterPropTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -121,7 +118,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.onSubmit(this.context.router ? this.context.router.history : null);
|
this.props.onSubmit(this.props.history || null);
|
||||||
|
|
||||||
if (e) {
|
if (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -337,4 +334,4 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(ComposeForm);
|
export default withOptionalRouter(injectIntl(ComposeForm));
|
||||||
|
|
|
@ -6,6 +6,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import AttachmentList from 'mastodon/components/attachment_list';
|
import AttachmentList from 'mastodon/components/attachment_list';
|
||||||
|
import { WithOptionalRouterPropTypes, withOptionalRouter } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
import { Avatar } from '../../../components/avatar';
|
import { Avatar } from '../../../components/avatar';
|
||||||
import { DisplayName } from '../../../components/display_name';
|
import { DisplayName } from '../../../components/display_name';
|
||||||
|
@ -17,14 +18,11 @@ const messages = defineMessages({
|
||||||
|
|
||||||
class ReplyIndicator extends ImmutablePureComponent {
|
class ReplyIndicator extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
status: ImmutablePropTypes.map,
|
status: ImmutablePropTypes.map,
|
||||||
onCancel: PropTypes.func.isRequired,
|
onCancel: PropTypes.func.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
|
...WithOptionalRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
|
@ -34,7 +32,7 @@ class ReplyIndicator extends ImmutablePureComponent {
|
||||||
handleAccountClick = (e) => {
|
handleAccountClick = (e) => {
|
||||||
if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||||
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'])}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,4 +70,4 @@ class ReplyIndicator extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(ReplyIndicator);
|
export default withOptionalRouter(injectIntl(ReplyIndicator));
|
||||||
|
|
|
@ -4,12 +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 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { domain, searchEnabled } from 'mastodon/initial_state';
|
import { domain, searchEnabled } from 'mastodon/initial_state';
|
||||||
import { HASHTAG_REGEX } from 'mastodon/utils/hashtags';
|
import { HASHTAG_REGEX } from 'mastodon/utils/hashtags';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
placeholder: { id: 'search.placeholder', defaultMessage: 'Search' },
|
placeholder: { id: 'search.placeholder', defaultMessage: 'Search' },
|
||||||
|
@ -30,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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,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 = {
|
||||||
|
@ -163,32 +165,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 { value, onOpenURL, history } = this.props;
|
||||||
const { value, onOpenURL } = this.props;
|
|
||||||
|
|
||||||
onOpenURL(value, router.history);
|
onOpenURL(value, history);
|
||||||
this._unfocus();
|
this._unfocus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -201,13 +200,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'));
|
||||||
|
@ -239,8 +237,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);
|
||||||
|
|
||||||
|
@ -249,7 +246,7 @@ class Search extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openInRoute) {
|
if (openInRoute) {
|
||||||
router.history.push('/search');
|
history.push('/search');
|
||||||
}
|
}
|
||||||
|
|
||||||
this._unfocus();
|
this._unfocus();
|
||||||
|
@ -398,4 +395,4 @@ class Search extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(Search);
|
export default withRouter(injectIntl(Search));
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -3,7 +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 { 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';
|
||||||
|
@ -17,6 +17,7 @@ import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
|
||||||
import StatusContent from 'mastodon/components/status_content';
|
import StatusContent from 'mastodon/components/status_content';
|
||||||
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
||||||
import { autoPlayGif } from 'mastodon/initial_state';
|
import { autoPlayGif } from 'mastodon/initial_state';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
more: { id: 'status.more', defaultMessage: 'More' },
|
more: { id: 'status.more', defaultMessage: 'More' },
|
||||||
|
@ -30,10 +31,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 +42,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,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMouseEnter = ({ currentTarget }) => {
|
handleMouseEnter = ({ currentTarget }) => {
|
||||||
|
@ -74,7 +72,7 @@ class Conversation extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
if (!this.context.router) {
|
if (!this.props.history) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +82,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 = () => {
|
||||||
|
@ -92,7 +90,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 = () => {
|
||||||
|
@ -202,4 +200,4 @@ class Conversation extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(Conversation);
|
export default withRouter(injectIntl(Conversation));
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {
|
||||||
} from 'mastodon/actions/accounts';
|
} from 'mastodon/actions/accounts';
|
||||||
import { openModal } from 'mastodon/actions/modal';
|
import { openModal } from 'mastodon/actions/modal';
|
||||||
import { Avatar } from 'mastodon/components/avatar';
|
import { Avatar } from 'mastodon/components/avatar';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { DisplayName } from 'mastodon/components/display_name';
|
import { DisplayName } from 'mastodon/components/display_name';
|
||||||
import { ShortNumber } from 'mastodon/components/short_number';
|
import { ShortNumber } from 'mastodon/components/short_number';
|
||||||
import { autoPlayGif, me, unfollowModal } from 'mastodon/initial_state';
|
import { autoPlayGif, me, unfollowModal } from 'mastodon/initial_state';
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -32,7 +32,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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -45,13 +45,10 @@ class Statuses extends PureComponent {
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.explore_statuses' defaultMessage='Nothing is trending right now. Check back later!' />;
|
const emptyMessage = <FormattedMessage id='empty_column.explore_statuses' defaultMessage='Nothing is trending right now. Check back later!' />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<DismissableBanner id='explore/statuses'>
|
|
||||||
<FormattedMessage id='dismissable_banner.explore_statuses' defaultMessage='These are posts from across the social web that are gaining traction today. Newer posts with more boosts and favorites are ranked higher.' />
|
|
||||||
</DismissableBanner>
|
|
||||||
|
|
||||||
<StatusList
|
<StatusList
|
||||||
trackScroll
|
trackScroll
|
||||||
|
prepend={<DismissableBanner id='explore/statuses'><FormattedMessage id='dismissable_banner.explore_statuses' defaultMessage='These are posts from across the social web that are gaining traction today. Newer posts with more boosts and favorites are ranked higher.' /></DismissableBanner>}
|
||||||
|
alwaysPrepend
|
||||||
timelineId='explore'
|
timelineId='explore'
|
||||||
statusIds={statusIds}
|
statusIds={statusIds}
|
||||||
scrollKey='explore-statuses'
|
scrollKey='explore-statuses'
|
||||||
|
@ -62,7 +59,6 @@ class Statuses extends PureComponent {
|
||||||
bindToDocument={!multiColumn}
|
bindToDocument={!multiColumn}
|
||||||
withCounters
|
withCounters
|
||||||
/>
|
/>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { FormattedMessage } from 'react-intl';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { toServerSideType } from 'mastodon/utils/filters';
|
import { toServerSideType } from 'mastodon/utils/filters';
|
||||||
|
|
||||||
const mapStateToProps = (state, { filterId }) => ({
|
const mapStateToProps = (state, { filterId }) => ({
|
||||||
|
|
|
@ -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';
|
||||||
|
@ -20,6 +21,7 @@ import EmojiPickerDropdown from 'mastodon/features/compose/containers/emoji_pick
|
||||||
import unicodeMapping from 'mastodon/features/emoji/emoji_unicode_mapping_light';
|
import unicodeMapping from 'mastodon/features/emoji/emoji_unicode_mapping_light';
|
||||||
import { autoPlayGif, reduceMotion, disableSwiping, mascot } from 'mastodon/initial_state';
|
import { autoPlayGif, reduceMotion, disableSwiping, mascot } from 'mastodon/initial_state';
|
||||||
import { assetHost } from 'mastodon/utils/config';
|
import { assetHost } from 'mastodon/utils/config';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||||
|
@ -27,14 +29,10 @@ const messages = defineMessages({
|
||||||
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 => {
|
||||||
|
@ -89,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')}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -153,6 +151,8 @@ class Content extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Content = withRouter(ContentWithRouter);
|
||||||
|
|
||||||
class Emoji extends PureComponent {
|
class Emoji extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -68,7 +68,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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { ShortNumber } from 'mastodon/components/short_number';
|
import { ShortNumber } from 'mastodon/components/short_number';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
|
|
@ -37,7 +37,7 @@ const getHomeFeedSpeed = createSelector([
|
||||||
state => state.getIn(['timelines', 'home', 'pendingItems'], ImmutableList()),
|
state => state.getIn(['timelines', 'home', 'pendingItems'], ImmutableList()),
|
||||||
state => state.get('statuses'),
|
state => state.get('statuses'),
|
||||||
], (statusIds, pendingStatusIds, statusMap) => {
|
], (statusIds, pendingStatusIds, statusMap) => {
|
||||||
const recentStatusIds = pendingStatusIds.size > 0 ? pendingStatusIds : statusIds;
|
const recentStatusIds = pendingStatusIds.concat(statusIds);
|
||||||
const statuses = recentStatusIds.filter(id => id !== null).map(id => statusMap.get(id)).filter(status => status?.get('account') !== me).take(20);
|
const statuses = recentStatusIds.filter(id => id !== null).map(id => statusMap.get(id)).filter(status => status?.get('account') !== me).take(20);
|
||||||
|
|
||||||
if (statuses.isEmpty()) {
|
if (statuses.isEmpty()) {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { throttle, escapeRegExp } from 'lodash';
|
||||||
|
|
||||||
import { openModal, closeModal } from 'mastodon/actions/modal';
|
import { openModal, closeModal } from 'mastodon/actions/modal';
|
||||||
import api from 'mastodon/api';
|
import api from 'mastodon/api';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { registrationsOpen, sso_redirect } from 'mastodon/initial_state';
|
import { registrationsOpen, sso_redirect } from 'mastodon/initial_state';
|
||||||
|
|
||||||
|
|
|
@ -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 'mastodon/components/loading_indicator';
|
||||||
import { RadioButton } from 'mastodon/components/radio_button';
|
import { RadioButton } from 'mastodon/components/radio_button';
|
||||||
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
|
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
|
||||||
import StatusListContainer from 'mastodon/features/ui/containers/status_list_container';
|
import StatusListContainer from 'mastodon/features/ui/containers/status_list_container';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/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');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -263,4 +262,4 @@ class ListTimeline extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(injectIntl(ListTimeline));
|
export default withRouter(connect(mapStateToProps)(injectIntl(ListTimeline)));
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { changeListEditorTitle, submitListEditor } from 'mastodon/actions/lists';
|
import { changeListEditorTitle, submitListEditor } from 'mastodon/actions/lists';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
label: { id: 'lists.new.title_placeholder', defaultMessage: 'New list title' },
|
label: { id: 'lists.new.title_placeholder', defaultMessage: 'New list title' },
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import { injectIntl, FormattedMessage, defineMessages } from 'react-intl';
|
import { injectIntl, FormattedMessage, defineMessages } 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';
|
||||||
|
@ -15,6 +15,7 @@ import { Icon } from 'mastodon/components/icon';
|
||||||
import AccountContainer from 'mastodon/containers/account_container';
|
import AccountContainer from 'mastodon/containers/account_container';
|
||||||
import StatusContainer from 'mastodon/containers/status_container';
|
import StatusContainer from 'mastodon/containers/status_container';
|
||||||
import { me } from 'mastodon/initial_state';
|
import { me } from 'mastodon/initial_state';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
import FollowRequestContainer from '../containers/follow_request_container';
|
import FollowRequestContainer from '../containers/follow_request_container';
|
||||||
|
|
||||||
|
@ -44,11 +45,6 @@ const notificationForScreenReader = (intl, message, timestamp) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
class Notification extends ImmutablePureComponent {
|
class Notification extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
notification: ImmutablePropTypes.map.isRequired,
|
notification: ImmutablePropTypes.map.isRequired,
|
||||||
hidden: PropTypes.bool,
|
hidden: PropTypes.bool,
|
||||||
|
@ -65,6 +61,7 @@ class Notification extends ImmutablePureComponent {
|
||||||
cacheMediaWidth: PropTypes.func,
|
cacheMediaWidth: PropTypes.func,
|
||||||
cachedMediaWidth: PropTypes.number,
|
cachedMediaWidth: PropTypes.number,
|
||||||
unread: PropTypes.bool,
|
unread: PropTypes.bool,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMoveUp = () => {
|
handleMoveUp = () => {
|
||||||
|
@ -81,7 +78,7 @@ class Notification extends ImmutablePureComponent {
|
||||||
const { notification } = this.props;
|
const { notification } = this.props;
|
||||||
|
|
||||||
if (notification.get('status')) {
|
if (notification.get('status')) {
|
||||||
this.context.router.history.push(`/@${notification.getIn(['status', 'account', 'acct'])}/${notification.get('status')}`);
|
this.props.history.push(`/@${notification.getIn(['status', 'account', 'acct'])}/${notification.get('status')}`);
|
||||||
} else {
|
} else {
|
||||||
this.handleOpenProfile();
|
this.handleOpenProfile();
|
||||||
}
|
}
|
||||||
|
@ -89,14 +86,14 @@ class Notification extends ImmutablePureComponent {
|
||||||
|
|
||||||
handleOpenProfile = () => {
|
handleOpenProfile = () => {
|
||||||
const { notification } = this.props;
|
const { notification } = this.props;
|
||||||
this.context.router.history.push(`/@${notification.getIn(['account', 'acct'])}`);
|
this.props.history.push(`/@${notification.getIn(['account', 'acct'])}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMention = e => {
|
handleMention = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const { notification, onMention } = this.props;
|
const { notification, onMention } = this.props;
|
||||||
onMention(notification.get('account'), this.context.router.history);
|
onMention(notification.get('account'), this.props.history);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyFavourite = () => {
|
handleHotkeyFavourite = () => {
|
||||||
|
@ -560,4 +557,4 @@ class Notification extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(Notification);
|
export default withRouter(injectIntl(Notification));
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { requestBrowserPermission } from 'mastodon/actions/notifications';
|
import { requestBrowserPermission } from 'mastodon/actions/notifications';
|
||||||
import { changeSetting } from 'mastodon/actions/settings';
|
import { changeSetting } from 'mastodon/actions/settings';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { IconButton } from 'mastodon/components/icon_button';
|
import { IconButton } from 'mastodon/components/icon_button';
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
||||||
|
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
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';
|
||||||
|
@ -19,6 +19,7 @@ import Column from 'mastodon/features/ui/components/column';
|
||||||
import { me } from 'mastodon/initial_state';
|
import { me } from 'mastodon/initial_state';
|
||||||
import { makeGetAccount } from 'mastodon/selectors';
|
import { makeGetAccount } from 'mastodon/selectors';
|
||||||
import { assetHost } from 'mastodon/utils/config';
|
import { assetHost } from 'mastodon/utils/config';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
import ArrowSmallRight from './components/arrow_small_right';
|
import ArrowSmallRight from './components/arrow_small_right';
|
||||||
import Step from './components/step';
|
import Step from './components/step';
|
||||||
|
@ -38,15 +39,11 @@ const mapStateToProps = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
class Onboarding extends ImmutablePureComponent {
|
class Onboarding extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
account: ImmutablePropTypes.map,
|
account: ImmutablePropTypes.map,
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -56,11 +53,10 @@ class Onboarding extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClose = () => {
|
handleClose = () => {
|
||||||
const { dispatch } = this.props;
|
const { dispatch, history } = this.props;
|
||||||
const { router } = this.context;
|
|
||||||
|
|
||||||
dispatch(closeOnboarding());
|
dispatch(closeOnboarding());
|
||||||
router.history.push('/home');
|
history.push('/home');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleProfileClick = () => {
|
handleProfileClick = () => {
|
||||||
|
@ -72,10 +68,9 @@ class Onboarding extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleComposeClick = () => {
|
handleComposeClick = () => {
|
||||||
const { dispatch, intl } = this.props;
|
const { dispatch, intl, history } = this.props;
|
||||||
const { router } = this.context;
|
|
||||||
|
|
||||||
dispatch(focusCompose(router.history, intl.formatMessage(messages.template)));
|
dispatch(focusCompose(history, intl.formatMessage(messages.template)));
|
||||||
};
|
};
|
||||||
|
|
||||||
handleShareClick = () => {
|
handleShareClick = () => {
|
||||||
|
@ -153,4 +148,4 @@ class Onboarding extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(injectIntl(Onboarding));
|
export default withRouter(connect(mapStateToProps)(injectIntl(Onboarding)));
|
||||||
|
|
|
@ -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 'mastodon/actions/modal';
|
||||||
import { IconButton } from 'mastodon/components/icon_button';
|
import { IconButton } from 'mastodon/components/icon_button';
|
||||||
import { me, boostModal } from 'mastodon/initial_state';
|
import { me, boostModal } from 'mastodon/initial_state';
|
||||||
import { makeGetStatus } from 'mastodon/selectors';
|
import { makeGetStatus } from 'mastodon/selectors';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
reply: { id: 'status.reply', defaultMessage: 'Reply' },
|
reply: { id: 'status.reply', defaultMessage: 'Reply' },
|
||||||
|
@ -43,7 +45,6 @@ const makeMapStateToProps = () => {
|
||||||
class Footer extends ImmutablePureComponent {
|
class Footer extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,17 +56,17 @@ class Footer extends ImmutablePureComponent {
|
||||||
askReplyConfirmation: PropTypes.bool,
|
askReplyConfirmation: 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 = () => {
|
||||||
|
@ -149,9 +150,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +160,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 () {
|
||||||
|
@ -204,4 +203,4 @@ class Footer extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(makeMapStateToProps)(injectIntl(Footer));
|
export default withRouter(connect(makeMapStateToProps)(injectIntl(Footer)));
|
||||||
|
|
|
@ -41,7 +41,6 @@ const mapStateToProps = (state, { columnId }) => {
|
||||||
class PublicTimeline extends PureComponent {
|
class PublicTimeline extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ 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';
|
||||||
|
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import EmojiPickerDropdownContainer from 'mastodon/features/compose/containers/emoji_picker_dropdown_container';
|
import EmojiPickerDropdownContainer from 'mastodon/features/compose/containers/emoji_picker_dropdown_container';
|
||||||
import emojify from 'mastodon/features/emoji/emoji';
|
import emojify from 'mastodon/features/emoji/emoji';
|
||||||
import { autoPlayGif } from 'mastodon/initial_state';
|
import { autoPlayGif } from 'mastodon/initial_state';
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { createSelector } from 'reselect';
|
||||||
import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd';
|
import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd';
|
||||||
|
|
||||||
import { updateReactionDeck } from 'mastodon/actions/reaction_deck';
|
import { updateReactionDeck } from 'mastodon/actions/reaction_deck';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import ColumnHeader from 'mastodon/components/column_header';
|
import ColumnHeader from 'mastodon/components/column_header';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { List as ImmutableList } from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
|
|
||||||
import Option from './components/option';
|
import Option from './components/option';
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { createSelector } from 'reselect';
|
||||||
import Toggle from 'react-toggle';
|
import Toggle from 'react-toggle';
|
||||||
|
|
||||||
import { fetchAccount } from 'mastodon/actions/accounts';
|
import { fetchAccount } from 'mastodon/actions/accounts';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { FormattedMessage } from 'react-intl';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
|
|
||||||
import Option from './components/option';
|
import Option from './components/option';
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { OrderedSet } from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
||||||
import StatusCheckBox from 'mastodon/features/report/containers/status_check_box_container';
|
import StatusCheckBox from 'mastodon/features/report/containers/status_check_box_container';
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
muteAccount,
|
muteAccount,
|
||||||
blockAccount,
|
blockAccount,
|
||||||
} from 'mastodon/actions/accounts';
|
} from 'mastodon/actions/accounts';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
|
|
||||||
const mapStateToProps = () => ({});
|
const mapStateToProps = () => ({});
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,13 @@ 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';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
|
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
|
|
||||||
import { IconButton } from '../../../components/icon_button';
|
import { IconButton } from '../../../components/icon_button';
|
||||||
|
@ -63,7 +65,6 @@ const mapStateToProps = (state, { status }) => ({
|
||||||
class ActionBar extends PureComponent {
|
class ActionBar extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
|
||||||
identity: PropTypes.object,
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -94,6 +95,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,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleOpenMentions = () => {
|
handleOpenMentions = () => {
|
||||||
|
@ -129,23 +131,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 = () => {
|
||||||
|
@ -373,4 +375,4 @@ class ActionBar extends PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(injectIntl(ActionBar));
|
export default withRouter(connect(mapStateToProps)(injectIntl(ActionBar)));
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import { injectIntl, defineMessages, FormattedDate, FormattedMessage } from 'react-intl';
|
import { injectIntl, defineMessages, FormattedDate, FormattedMessage } 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';
|
||||||
|
@ -14,6 +14,7 @@ import { getHashtagBarForStatus } from 'mastodon/components/hashtag_bar';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
|
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
|
||||||
import { enableEmojiReaction } from 'mastodon/initial_state';
|
import { enableEmojiReaction } from 'mastodon/initial_state';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
import { Avatar } from '../../../components/avatar';
|
import { Avatar } from '../../../components/avatar';
|
||||||
import { DisplayName } from '../../../components/display_name';
|
import { DisplayName } from '../../../components/display_name';
|
||||||
|
@ -46,10 +47,6 @@ const messages = defineMessages({
|
||||||
|
|
||||||
class DetailedStatus extends ImmutablePureComponent {
|
class DetailedStatus extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
status: ImmutablePropTypes.map,
|
status: ImmutablePropTypes.map,
|
||||||
onOpenMedia: PropTypes.func.isRequired,
|
onOpenMedia: PropTypes.func.isRequired,
|
||||||
|
@ -68,6 +65,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||||
onToggleMediaVisibility: PropTypes.func,
|
onToggleMediaVisibility: PropTypes.func,
|
||||||
onEmojiReact: PropTypes.func,
|
onEmojiReact: PropTypes.func,
|
||||||
onUnEmojiReact: PropTypes.func,
|
onUnEmojiReact: PropTypes.func,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -75,9 +73,9 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleAccountClick = (e) => {
|
handleAccountClick = (e) => {
|
||||||
if (e.button === 0 && !(e.ctrlKey || e.metaKey) && this.context.router) {
|
if (e.button === 0 && !(e.ctrlKey || e.metaKey) && this.props.history) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
|
this.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
@ -282,7 +280,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||||
|
|
||||||
if (['private', 'direct'].includes(status.get('visibility_ex'))) {
|
if (['private', 'direct'].includes(status.get('visibility_ex'))) {
|
||||||
reblogLink = '';
|
reblogLink = '';
|
||||||
} else if (this.context.router) {
|
} else if (this.props.history) {
|
||||||
reblogLink = (
|
reblogLink = (
|
||||||
<>
|
<>
|
||||||
{' · '}
|
{' · '}
|
||||||
|
@ -308,7 +306,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' />
|
||||||
|
@ -420,4 +418,4 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(DetailedStatus);
|
export default withRouter(injectIntl(DetailedStatus));
|
||||||
|
|
|
@ -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 Immutable from 'immutable';
|
import Immutable from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
@ -17,6 +18,7 @@ import { Icon } from 'mastodon/components/icon';
|
||||||
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
||||||
import ScrollContainer from 'mastodon/containers/scroll_container';
|
import ScrollContainer from 'mastodon/containers/scroll_container';
|
||||||
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
|
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
unblockAccount,
|
unblockAccount,
|
||||||
|
@ -71,6 +73,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?' },
|
||||||
|
@ -199,7 +202,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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -219,6 +221,7 @@ class Status extends ImmutablePureComponent {
|
||||||
inUse: PropTypes.bool,
|
inUse: PropTypes.bool,
|
||||||
available: PropTypes.bool,
|
available: PropTypes.bool,
|
||||||
}),
|
}),
|
||||||
|
...WithRouterPropTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -312,11 +315,11 @@ class Status extends ImmutablePureComponent {
|
||||||
modalProps: {
|
modalProps: {
|
||||||
message: intl.formatMessage(messages.replyMessage),
|
message: intl.formatMessage(messages.replyMessage),
|
||||||
confirm: intl.formatMessage(messages.replyConfirm),
|
confirm: intl.formatMessage(messages.replyConfirm),
|
||||||
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({
|
||||||
|
@ -560,7 +563,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'])}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyToggleHidden = () => {
|
handleHotkeyToggleHidden = () => {
|
||||||
|
@ -816,4 +819,4 @@ class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(connect(makeMapStateToProps)(Status));
|
export default withRouter(injectIntl(connect(makeMapStateToProps)(Status)));
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
import { followAccount } from 'mastodon/actions/accounts';
|
import { followAccount } from 'mastodon/actions/accounts';
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { IconButton } from 'mastodon/components/icon_button';
|
import { IconButton } from 'mastodon/components/icon_button';
|
||||||
import Option from 'mastodon/features/report/components/option';
|
import Option from 'mastodon/features/report/components/option';
|
||||||
import { languages as preloadedLanguages } from 'mastodon/initial_state';
|
import { languages as preloadedLanguages } from 'mastodon/initial_state';
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { connect } from 'react-redux';
|
||||||
import { blockAccount } from '../../../actions/accounts';
|
import { blockAccount } from '../../../actions/accounts';
|
||||||
import { closeModal } from '../../../actions/modal';
|
import { closeModal } from '../../../actions/modal';
|
||||||
import { initReport } from '../../../actions/reports';
|
import { initReport } from '../../../actions/reports';
|
||||||
import Button from '../../../components/button';
|
import { Button } from '../../../components/button';
|
||||||
import { makeGetAccount } from '../../../selectors';
|
import { makeGetAccount } from '../../../selectors';
|
||||||
|
|
||||||
const makeMapStateToProps = () => {
|
const makeMapStateToProps = () => {
|
||||||
|
@ -51,10 +51,6 @@ class BlockModal extends PureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.button.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
this.props.onClose();
|
this.props.onClose();
|
||||||
this.props.onConfirm(this.props.account);
|
this.props.onConfirm(this.props.account);
|
||||||
|
@ -69,10 +65,6 @@ class BlockModal extends PureComponent {
|
||||||
this.props.onClose();
|
this.props.onClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
setRef = (c) => {
|
|
||||||
this.button = c;
|
|
||||||
};
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { account } = this.props;
|
const { account } = this.props;
|
||||||
|
|
||||||
|
@ -95,7 +87,7 @@ class BlockModal extends PureComponent {
|
||||||
<Button onClick={this.handleSecondary} className='confirmation-modal__secondary-button'>
|
<Button onClick={this.handleSecondary} className='confirmation-modal__secondary-button'>
|
||||||
<FormattedMessage id='confirmations.block.block_and_report' defaultMessage='Block & Report' />
|
<FormattedMessage id='confirmations.block.block_and_report' defaultMessage='Block & Report' />
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={this.handleClick} ref={this.setRef}>
|
<Button onClick={this.handleClick} autoFocus>
|
||||||
<FormattedMessage id='confirmations.block.confirm' defaultMessage='Block' />
|
<FormattedMessage id='confirmations.block.confirm' defaultMessage='Block' />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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';
|
||||||
|
@ -12,9 +13,10 @@ import { changeBoostPrivacy } from 'mastodon/actions/boosts';
|
||||||
import AttachmentList from 'mastodon/components/attachment_list';
|
import AttachmentList from 'mastodon/components/attachment_list';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import PrivacyDropdown from 'mastodon/features/compose/components/privacy_dropdown';
|
import PrivacyDropdown from 'mastodon/features/compose/components/privacy_dropdown';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
import { Avatar } from '../../../components/avatar';
|
import { Avatar } from '../../../components/avatar';
|
||||||
import Button from '../../../components/button';
|
import { Button } from '../../../components/button';
|
||||||
import { DisplayName } from '../../../components/display_name';
|
import { DisplayName } from '../../../components/display_name';
|
||||||
import { RelativeTimestamp } from '../../../components/relative_timestamp';
|
import { RelativeTimestamp } from '../../../components/relative_timestamp';
|
||||||
import StatusContent from '../../../components/status_content';
|
import StatusContent from '../../../components/status_content';
|
||||||
|
@ -49,11 +51,6 @@ 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,
|
||||||
|
@ -61,12 +58,9 @@ class BoostModal extends ImmutablePureComponent {
|
||||||
onChangeBoostPrivacy: PropTypes.func.isRequired,
|
onChangeBoostPrivacy: PropTypes.func.isRequired,
|
||||||
privacy: PropTypes.string.isRequired,
|
privacy: PropTypes.string.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.button.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleReblog = () => {
|
handleReblog = () => {
|
||||||
this.props.onReblog(this.props.status, this.props.privacy);
|
this.props.onReblog(this.props.status, this.props.privacy);
|
||||||
this.props.onClose();
|
this.props.onClose();
|
||||||
|
@ -76,7 +70,7 @@ class BoostModal extends ImmutablePureComponent {
|
||||||
if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||||
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'])}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,10 +78,6 @@ class BoostModal extends ImmutablePureComponent {
|
||||||
return document.getElementsByClassName('modal-root__container')[0];
|
return document.getElementsByClassName('modal-root__container')[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
setRef = (c) => {
|
|
||||||
this.button = c;
|
|
||||||
};
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { status, privacy, intl } = this.props;
|
const { status, privacy, intl } = this.props;
|
||||||
const buttonText = status.get('reblogged') ? messages.cancel_reblog : messages.reblog;
|
const buttonText = status.get('reblogged') ? messages.cancel_reblog : messages.reblog;
|
||||||
|
@ -147,7 +137,7 @@ class BoostModal extends ImmutablePureComponent {
|
||||||
onChange={this.props.onChangeBoostPrivacy}
|
onChange={this.props.onChangeBoostPrivacy}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Button text={intl.formatMessage(buttonText)} onClick={this.handleReblog} ref={this.setRef} />
|
<Button text={intl.formatMessage(buttonText)} onClick={this.handleReblog} autoFocus />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -155,4 +145,4 @@ class BoostModal extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(BoostModal));
|
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(injectIntl(BoostModal)));
|
||||||
|
|
|
@ -7,7 +7,7 @@ import classNames from 'classnames';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import Column from 'mastodon/components/column';
|
import Column from 'mastodon/components/column';
|
||||||
import { autoPlayGif } from 'mastodon/initial_state';
|
import { autoPlayGif } from 'mastodon/initial_state';
|
||||||
|
|
||||||
|
|
|
@ -54,11 +54,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,
|
||||||
isModalOpen: PropTypes.bool.isRequired,
|
isModalOpen: PropTypes.bool.isRequired,
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { PureComponent } from 'react';
|
||||||
|
|
||||||
import { injectIntl, FormattedMessage } from 'react-intl';
|
import { injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import Button from '../../../components/button';
|
import { Button } from '../../../components/button';
|
||||||
|
|
||||||
class ConfirmationModal extends PureComponent {
|
class ConfirmationModal extends PureComponent {
|
||||||
|
|
||||||
|
@ -22,10 +22,6 @@ class ConfirmationModal extends PureComponent {
|
||||||
closeWhenConfirm: true,
|
closeWhenConfirm: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.button.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
if (this.props.closeWhenConfirm) {
|
if (this.props.closeWhenConfirm) {
|
||||||
this.props.onClose();
|
this.props.onClose();
|
||||||
|
@ -42,10 +38,6 @@ class ConfirmationModal extends PureComponent {
|
||||||
this.props.onClose();
|
this.props.onClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
setRef = (c) => {
|
|
||||||
this.button = c;
|
|
||||||
};
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { message, confirm, secondary } = this.props;
|
const { message, confirm, secondary } = this.props;
|
||||||
|
|
||||||
|
@ -62,7 +54,7 @@ class ConfirmationModal extends PureComponent {
|
||||||
{secondary !== undefined && (
|
{secondary !== undefined && (
|
||||||
<Button text={secondary} onClick={this.handleSecondary} className='confirmation-modal__secondary-button' />
|
<Button text={secondary} onClick={this.handleSecondary} className='confirmation-modal__secondary-button' />
|
||||||
)}
|
)}
|
||||||
<Button text={confirm} onClick={this.handleClick} ref={this.setRef} />
|
<Button text={confirm} onClick={this.handleClick} autoFocus />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,7 +16,7 @@ import tesseractWorkerPath from 'tesseract.js/dist/worker.min.js';
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
import tesseractCorePath from 'tesseract.js-core/tesseract-core.wasm.js';
|
import tesseractCorePath from 'tesseract.js-core/tesseract-core.wasm.js';
|
||||||
|
|
||||||
import Button from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
import { GIFV } from 'mastodon/components/gifv';
|
import { GIFV } from 'mastodon/components/gifv';
|
||||||
import { IconButton } from 'mastodon/components/icon_button';
|
import { IconButton } from 'mastodon/components/icon_button';
|
||||||
import Audio from 'mastodon/features/audio';
|
import Audio from 'mastodon/features/audio';
|
||||||
|
|
|
@ -100,7 +100,7 @@ class LinkFooter extends PureComponent {
|
||||||
{DividingCircle}
|
{DividingCircle}
|
||||||
<a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='footer.source_code' defaultMessage='View source code' /></a>
|
<a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='footer.source_code' defaultMessage='View source code' /></a>
|
||||||
{DividingCircle}
|
{DividingCircle}
|
||||||
<span class='version'>v{version}</span>
|
<span className='version'>v{version}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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';
|
||||||
|
@ -71,4 +69,4 @@ class ListPanel extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withRouter(connect(mapStateToProps)(ListPanel));
|
export default connect(mapStateToProps)(ListPanel);
|
||||||
|
|
|
@ -10,7 +10,7 @@ import Toggle from 'react-toggle';
|
||||||
import { muteAccount } from '../../../actions/accounts';
|
import { muteAccount } from '../../../actions/accounts';
|
||||||
import { closeModal } from '../../../actions/modal';
|
import { closeModal } from '../../../actions/modal';
|
||||||
import { toggleHideNotifications, changeMuteDuration } from '../../../actions/mutes';
|
import { toggleHideNotifications, changeMuteDuration } from '../../../actions/mutes';
|
||||||
import Button from '../../../components/button';
|
import { Button } from '../../../components/button';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
minutes: { id: 'intervals.full.minutes', defaultMessage: '{number, plural, one {# minute} other {# minutes}}' },
|
minutes: { id: 'intervals.full.minutes', defaultMessage: '{number, plural, one {# minute} other {# minutes}}' },
|
||||||
|
@ -63,10 +63,6 @@ class MuteModal extends PureComponent {
|
||||||
onChangeMuteDuration: PropTypes.func.isRequired,
|
onChangeMuteDuration: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.button.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
this.props.onClose();
|
this.props.onClose();
|
||||||
this.props.onConfirm(this.props.account, this.props.notifications, this.props.muteDuration);
|
this.props.onConfirm(this.props.account, this.props.notifications, this.props.muteDuration);
|
||||||
|
@ -76,10 +72,6 @@ class MuteModal extends PureComponent {
|
||||||
this.props.onClose();
|
this.props.onClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
setRef = (c) => {
|
|
||||||
this.button = c;
|
|
||||||
};
|
|
||||||
|
|
||||||
toggleNotifications = () => {
|
toggleNotifications = () => {
|
||||||
this.props.onToggleNotifications();
|
this.props.onToggleNotifications();
|
||||||
};
|
};
|
||||||
|
@ -134,7 +126,7 @@ class MuteModal extends PureComponent {
|
||||||
<Button onClick={this.handleCancel} className='mute-modal__cancel-button'>
|
<Button onClick={this.handleCancel} className='mute-modal__cancel-button'>
|
||||||
<FormattedMessage id='confirmation_modal.cancel' defaultMessage='Cancel' />
|
<FormattedMessage id='confirmation_modal.cancel' defaultMessage='Cancel' />
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={this.handleClick} ref={this.setRef}>
|
<Button onClick={this.handleClick} autoFocus>
|
||||||
<FormattedMessage id='confirmations.mute.confirm' defaultMessage='Mute' />
|
<FormattedMessage id='confirmations.mute.confirm' defaultMessage='Mute' />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { WordmarkLogo } from 'mastodon/components/logo';
|
import { WordmarkLogo } from 'mastodon/components/logo';
|
||||||
import NavigationPortal from 'mastodon/components/navigation_portal';
|
import { NavigationPortal } from 'mastodon/components/navigation_portal';
|
||||||
import { enableDtlMenu, timelinePreview, trendsEnabled, dtlTag } from 'mastodon/initial_state';
|
import { enableDtlMenu, timelinePreview, trendsEnabled, dtlTag } from 'mastodon/initial_state';
|
||||||
import { transientSingleColumn } from 'mastodon/is_mobile';
|
import { transientSingleColumn } from 'mastodon/is_mobile';
|
||||||
|
|
||||||
|
@ -41,7 +41,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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,23 +66,29 @@ class NavigationPanel extends Component {
|
||||||
<ColumnLink transparent to='/search' icon='search' text={intl.formatMessage(messages.search)} />
|
<ColumnLink transparent to='/search' icon='search' text={intl.formatMessage(messages.search)} />
|
||||||
));
|
));
|
||||||
|
|
||||||
|
let banner = undefined;
|
||||||
|
|
||||||
|
if(transientSingleColumn)
|
||||||
|
banner = (<div className='switch-to-advanced'>
|
||||||
|
{intl.formatMessage(messages.openedInClassicInterface)}
|
||||||
|
{" "}
|
||||||
|
<a href={`/deck${location.pathname}`} className='switch-to-advanced__toggle'>
|
||||||
|
{intl.formatMessage(messages.advancedInterface)}
|
||||||
|
</a>
|
||||||
|
</div>);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='navigation-panel'>
|
<div className='navigation-panel'>
|
||||||
<div className='navigation-panel__logo'>
|
<div className='navigation-panel__logo'>
|
||||||
<Link to='/' className='column-link column-link--logo'><WordmarkLogo /></Link>
|
<Link to='/' className='column-link column-link--logo'><WordmarkLogo /></Link>
|
||||||
|
{!banner && <hr />}
|
||||||
|
</div>
|
||||||
|
|
||||||
{transientSingleColumn ? (
|
{banner &&
|
||||||
<div class='switch-to-advanced'>
|
<div class='navigation-panel__banner'>
|
||||||
{intl.formatMessage(messages.openedInClassicInterface)}
|
{banner}
|
||||||
{" "}
|
|
||||||
<a href={`/deck${location.pathname}`} class='switch-to-advanced__toggle'>
|
|
||||||
{intl.formatMessage(messages.advancedInterface)}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<hr />
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
{signedIn && (
|
{signedIn && (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { synchronouslySubmitMarkers, submitMarkers, fetchMarkers } from 'mastodo
|
||||||
import { INTRODUCTION_VERSION } from 'mastodon/actions/onboarding';
|
import { INTRODUCTION_VERSION } from 'mastodon/actions/onboarding';
|
||||||
import PictureInPicture from 'mastodon/features/picture_in_picture';
|
import PictureInPicture from 'mastodon/features/picture_in_picture';
|
||||||
import { layoutFromWindow } from 'mastodon/is_mobile';
|
import { layoutFromWindow } from 'mastodon/is_mobile';
|
||||||
|
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose';
|
import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose';
|
||||||
import { clearHeight } from '../../actions/height_cache';
|
import { clearHeight } from '../../actions/height_cache';
|
||||||
|
@ -278,7 +279,6 @@ class SwitchingColumnsArea extends PureComponent {
|
||||||
class UI extends PureComponent {
|
class UI extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object.isRequired,
|
|
||||||
identity: PropTypes.object.isRequired,
|
identity: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -289,12 +289,12 @@ class UI extends PureComponent {
|
||||||
hasComposingText: PropTypes.bool,
|
hasComposingText: PropTypes.bool,
|
||||||
hasMediaAttachments: PropTypes.bool,
|
hasMediaAttachments: PropTypes.bool,
|
||||||
canUploadMore: PropTypes.bool,
|
canUploadMore: PropTypes.bool,
|
||||||
location: PropTypes.object,
|
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
dropdownMenuIsOpen: PropTypes.bool,
|
dropdownMenuIsOpen: PropTypes.bool,
|
||||||
layout: PropTypes.string.isRequired,
|
layout: PropTypes.string.isRequired,
|
||||||
firstLaunch: PropTypes.bool,
|
firstLaunch: PropTypes.bool,
|
||||||
username: PropTypes.string,
|
username: PropTypes.string,
|
||||||
|
...WithRouterPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -391,7 +391,7 @@ class UI extends PureComponent {
|
||||||
|
|
||||||
handleServiceWorkerPostMessage = ({ data }) => {
|
handleServiceWorkerPostMessage = ({ data }) => {
|
||||||
if (data.type === 'navigate') {
|
if (data.type === 'navigate') {
|
||||||
this.context.router.history.push(data.path);
|
this.props.history.push(data.path);
|
||||||
} else {
|
} else {
|
||||||
console.warn('Unknown message type:', data.type);
|
console.warn('Unknown message type:', data.type);
|
||||||
}
|
}
|
||||||
|
@ -512,12 +512,12 @@ class UI extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyBack = () => {
|
handleHotkeyBack = () => {
|
||||||
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('/');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -527,38 +527,38 @@ class UI extends PureComponent {
|
||||||
|
|
||||||
handleHotkeyToggleHelp = () => {
|
handleHotkeyToggleHelp = () => {
|
||||||
if (this.props.location.pathname === '/keyboard-shortcuts') {
|
if (this.props.location.pathname === '/keyboard-shortcuts') {
|
||||||
this.context.router.history.goBack();
|
this.props.history.goBack();
|
||||||
} else {
|
} else {
|
||||||
this.context.router.history.push('/keyboard-shortcuts');
|
this.props.history.push('/keyboard-shortcuts');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToHome = () => {
|
handleHotkeyGoToHome = () => {
|
||||||
this.context.router.history.push('/home');
|
this.props.history.push('/home');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToNotifications = () => {
|
handleHotkeyGoToNotifications = () => {
|
||||||
this.context.router.history.push('/notifications');
|
this.props.history.push('/notifications');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToLocal = () => {
|
handleHotkeyGoToLocal = () => {
|
||||||
this.context.router.history.push('/public/local');
|
this.props.history.push('/public/local');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToFederated = () => {
|
handleHotkeyGoToFederated = () => {
|
||||||
this.context.router.history.push('/public');
|
this.props.history.push('/public');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToDirect = () => {
|
handleHotkeyGoToDirect = () => {
|
||||||
this.context.router.history.push('/conversations');
|
this.props.history.push('/conversations');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToStart = () => {
|
handleHotkeyGoToStart = () => {
|
||||||
this.context.router.history.push('/getting-started');
|
this.props.history.push('/getting-started');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToFavourites = () => {
|
handleHotkeyGoToFavourites = () => {
|
||||||
this.context.router.history.push('/favourites');
|
this.props.history.push('/favourites');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToEmojiReactions = () => {
|
handleHotkeyGoToEmojiReactions = () => {
|
||||||
|
@ -566,23 +566,23 @@ class UI extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToPinned = () => {
|
handleHotkeyGoToPinned = () => {
|
||||||
this.context.router.history.push('/pinned');
|
this.props.history.push('/pinned');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToProfile = () => {
|
handleHotkeyGoToProfile = () => {
|
||||||
this.context.router.history.push(`/@${this.props.username}`);
|
this.props.history.push(`/@${this.props.username}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToBlocked = () => {
|
handleHotkeyGoToBlocked = () => {
|
||||||
this.context.router.history.push('/blocks');
|
this.props.history.push('/blocks');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToMuted = () => {
|
handleHotkeyGoToMuted = () => {
|
||||||
this.context.router.history.push('/mutes');
|
this.props.history.push('/mutes');
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyGoToRequests = () => {
|
handleHotkeyGoToRequests = () => {
|
||||||
this.context.router.history.push('/follow_requests');
|
this.props.history.push('/follow_requests');
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
|
|
@ -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,14 +10,8 @@ import ColumnLoading from '../components/column_loading';
|
||||||
import BundleContainer from '../containers/bundle_container';
|
import BundleContainer from '../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 { multiColumn, children } = this.props;
|
|
||||||
const { location } = this.context.router.route;
|
|
||||||
|
|
||||||
const decklessLocation = multiColumn && location.pathname.startsWith('/deck')
|
const decklessLocation = multiColumn && location.pathname.startsWith('/deck')
|
||||||
? {...location, pathname: location.pathname.slice(5)}
|
? {...location, pathname: location.pathname.slice(5)}
|
||||||
|
@ -28,9 +22,8 @@ export class WrappedSwitch extends PureComponent {
|
||||||
{Children.map(children, child => child ? cloneElement(child, { multiColumn }) : null)}
|
{Children.map(children, child => child ? cloneElement(child, { multiColumn }) : null)}
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
WrappedSwitch.propTypes = {
|
WrappedSwitch.propTypes = {
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
|
|
|
@ -71,11 +71,11 @@
|
||||||
"account.unmute_notifications_short": "Poista ilmoitusten mykistys",
|
"account.unmute_notifications_short": "Poista ilmoitusten mykistys",
|
||||||
"account.unmute_short": "Poista mykistys",
|
"account.unmute_short": "Poista mykistys",
|
||||||
"account_note.placeholder": "Lisää muistiinpano napsauttamalla",
|
"account_note.placeholder": "Lisää muistiinpano napsauttamalla",
|
||||||
"admin.dashboard.daily_retention": "Käyttäjän pysyminen rekisteröitymisen jälkeiseen päivään mennessä",
|
"admin.dashboard.daily_retention": "Käyttäjien pysyvyys rekisteröitymisen jälkeen päivittäin",
|
||||||
"admin.dashboard.monthly_retention": "Käyttäjän pysyminen rekisteröitymisen jälkeiseen kuukauteen mennessä",
|
"admin.dashboard.monthly_retention": "Käyttäjien pysyvyys rekisteröitymisen jälkeen kuukausittain",
|
||||||
"admin.dashboard.retention.average": "Keskimäärin",
|
"admin.dashboard.retention.average": "Keskimäärin",
|
||||||
"admin.dashboard.retention.cohort": "Kirjautumiset",
|
"admin.dashboard.retention.cohort": "Rekisteröitymis-kk.",
|
||||||
"admin.dashboard.retention.cohort_size": "Uudet käyttäjät",
|
"admin.dashboard.retention.cohort_size": "Uusia käyttäjiä",
|
||||||
"admin.impact_report.instance_accounts": "Tilien profiilit, jotka tämä poistaisi",
|
"admin.impact_report.instance_accounts": "Tilien profiilit, jotka tämä poistaisi",
|
||||||
"admin.impact_report.instance_followers": "Seuraajat, jotka käyttäjämme menettäisivät",
|
"admin.impact_report.instance_followers": "Seuraajat, jotka käyttäjämme menettäisivät",
|
||||||
"admin.impact_report.instance_follows": "Seuraajat, jotka heidän käyttäjänsä menettäisivät",
|
"admin.impact_report.instance_follows": "Seuraajat, jotka heidän käyttäjänsä menettäisivät",
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
"column.directory": "Selaa profiileja",
|
"column.directory": "Selaa profiileja",
|
||||||
"column.domain_blocks": "Estetyt verkkotunnukset",
|
"column.domain_blocks": "Estetyt verkkotunnukset",
|
||||||
"column.favourites": "Suosikit",
|
"column.favourites": "Suosikit",
|
||||||
"column.firehose": "Live-syötteet",
|
"column.firehose": "Livesyötteet",
|
||||||
"column.follow_requests": "Seuraamispyynnöt",
|
"column.follow_requests": "Seuraamispyynnöt",
|
||||||
"column.home": "Koti",
|
"column.home": "Koti",
|
||||||
"column.lists": "Listat",
|
"column.lists": "Listat",
|
||||||
|
@ -135,7 +135,7 @@
|
||||||
"community.column_settings.remote_only": "Vain etätilit",
|
"community.column_settings.remote_only": "Vain etätilit",
|
||||||
"compose.language.change": "Vaihda kieli",
|
"compose.language.change": "Vaihda kieli",
|
||||||
"compose.language.search": "Hae kieliä...",
|
"compose.language.search": "Hae kieliä...",
|
||||||
"compose.published.body": "Julkaisusi julkaistiin.",
|
"compose.published.body": "Julkaisu lähetetty.",
|
||||||
"compose.published.open": "Avaa",
|
"compose.published.open": "Avaa",
|
||||||
"compose.saved.body": "Julkaisu tallennettu.",
|
"compose.saved.body": "Julkaisu tallennettu.",
|
||||||
"compose_form.direct_message_warning_learn_more": "Lisätietoja",
|
"compose_form.direct_message_warning_learn_more": "Lisätietoja",
|
||||||
|
@ -436,10 +436,10 @@
|
||||||
"notifications.clear": "Tyhjennä ilmoitukset",
|
"notifications.clear": "Tyhjennä ilmoitukset",
|
||||||
"notifications.clear_confirmation": "Haluatko varmasti poistaa kaikki ilmoitukset pysyvästi?",
|
"notifications.clear_confirmation": "Haluatko varmasti poistaa kaikki ilmoitukset pysyvästi?",
|
||||||
"notifications.column_settings.admin.report": "Uudet ilmoitukset:",
|
"notifications.column_settings.admin.report": "Uudet ilmoitukset:",
|
||||||
"notifications.column_settings.admin.sign_up": "Uudet kirjautumiset:",
|
"notifications.column_settings.admin.sign_up": "Uudet rekisteröitymiset:",
|
||||||
"notifications.column_settings.alert": "Työpöytäilmoitukset",
|
"notifications.column_settings.alert": "Työpöytäilmoitukset",
|
||||||
"notifications.column_settings.favourite": "Suosikit:",
|
"notifications.column_settings.favourite": "Suosikit:",
|
||||||
"notifications.column_settings.filter_bar.advanced": "Näytä kaikki kategoriat",
|
"notifications.column_settings.filter_bar.advanced": "Näytä kaikki luokat",
|
||||||
"notifications.column_settings.filter_bar.category": "Pikasuodatuspalkki",
|
"notifications.column_settings.filter_bar.category": "Pikasuodatuspalkki",
|
||||||
"notifications.column_settings.filter_bar.show_bar": "Näytä suodatinpalkki",
|
"notifications.column_settings.filter_bar.show_bar": "Näytä suodatinpalkki",
|
||||||
"notifications.column_settings.follow": "Uudet seuraajat:",
|
"notifications.column_settings.follow": "Uudet seuraajat:",
|
||||||
|
@ -517,7 +517,7 @@
|
||||||
"privacy.private.short": "Vain seuraajat",
|
"privacy.private.short": "Vain seuraajat",
|
||||||
"privacy.public.long": "Näkyy kaikille",
|
"privacy.public.long": "Näkyy kaikille",
|
||||||
"privacy.public.short": "Julkinen",
|
"privacy.public.short": "Julkinen",
|
||||||
"privacy.unlisted.long": "Näkyy kaikille, mutta jää pois löytämisominaisuuksista",
|
"privacy.unlisted.long": "Näkyy kaikille mutta jää pois löytämisominaisuuksista",
|
||||||
"privacy.unlisted.short": "Listaamaton",
|
"privacy.unlisted.short": "Listaamaton",
|
||||||
"privacy_policy.last_updated": "Viimeksi päivitetty {date}",
|
"privacy_policy.last_updated": "Viimeksi päivitetty {date}",
|
||||||
"privacy_policy.title": "Tietosuojakäytäntö",
|
"privacy_policy.title": "Tietosuojakäytäntö",
|
||||||
|
@ -589,13 +589,13 @@
|
||||||
"search.quick_action.go_to_hashtag": "Siirry aihetunnisteeseen {x}",
|
"search.quick_action.go_to_hashtag": "Siirry aihetunnisteeseen {x}",
|
||||||
"search.quick_action.open_url": "Avaa URL-osoite Mastodonissa",
|
"search.quick_action.open_url": "Avaa URL-osoite Mastodonissa",
|
||||||
"search.quick_action.status_search": "Julkaisut haulla {x}",
|
"search.quick_action.status_search": "Julkaisut haulla {x}",
|
||||||
"search.search_or_paste": "Hae tai kirjoita URL-osoite",
|
"search.search_or_paste": "Hae tai liitä URL-osoite",
|
||||||
"search_popout.full_text_search_disabled_message": "Ei saatavilla palvelimella {domain}.",
|
"search_popout.full_text_search_disabled_message": "Ei saatavilla palvelimella {domain}.",
|
||||||
"search_popout.language_code": "ISO-kielikoodi",
|
"search_popout.language_code": "ISO-kielikoodi",
|
||||||
"search_popout.options": "Hakuvalinnat",
|
"search_popout.options": "Hakuvalinnat",
|
||||||
"search_popout.quick_actions": "Pikatoiminnot",
|
"search_popout.quick_actions": "Pikatoiminnot",
|
||||||
"search_popout.recent": "Viimeaikaiset haut",
|
"search_popout.recent": "Viimeaikaiset haut",
|
||||||
"search_popout.specific_date": "tietty päivämäärä",
|
"search_popout.specific_date": "tarkka päiväys",
|
||||||
"search_popout.user": "käyttäjä",
|
"search_popout.user": "käyttäjä",
|
||||||
"search_results.accounts": "Profiilit",
|
"search_results.accounts": "Profiilit",
|
||||||
"search_results.all": "Kaikki",
|
"search_results.all": "Kaikki",
|
||||||
|
|
|
@ -163,13 +163,13 @@
|
||||||
"confirmation_modal.cancel": "Annulearje",
|
"confirmation_modal.cancel": "Annulearje",
|
||||||
"confirmations.block.block_and_report": "Blokkearje en rapportearje",
|
"confirmations.block.block_and_report": "Blokkearje en rapportearje",
|
||||||
"confirmations.block.confirm": "Blokkearje",
|
"confirmations.block.confirm": "Blokkearje",
|
||||||
"confirmations.block.message": "Bisto wis datsto {name} blokkearje wolst?",
|
"confirmations.block.message": "Binne jo wis dat jo {name} blokkearje wolle?",
|
||||||
"confirmations.cancel_follow_request.confirm": "Fersyk annulearje",
|
"confirmations.cancel_follow_request.confirm": "Fersyk annulearje",
|
||||||
"confirmations.cancel_follow_request.message": "Binne jo wis dat jo jo fersyk om {name} te folgjen annulearje wolle?",
|
"confirmations.cancel_follow_request.message": "Binne jo wis dat jo jo fersyk om {name} te folgjen annulearje wolle?",
|
||||||
"confirmations.delete.confirm": "Fuortsmite",
|
"confirmations.delete.confirm": "Fuortsmite",
|
||||||
"confirmations.delete.message": "Binne jo wis dat jo dit berjocht fuortsmite wolle?",
|
"confirmations.delete.message": "Binne jo wis dat jo dit berjocht fuortsmite wolle?",
|
||||||
"confirmations.delete_list.confirm": "Fuortsmite",
|
"confirmations.delete_list.confirm": "Fuortsmite",
|
||||||
"confirmations.delete_list.message": "Bisto wis datsto dizze list foar permanint fuortsmite wolst?",
|
"confirmations.delete_list.message": "Binne jo wis dat jo dizze list foar permanint fuortsmite wolle?",
|
||||||
"confirmations.discard_edit_media.confirm": "Fuortsmite",
|
"confirmations.discard_edit_media.confirm": "Fuortsmite",
|
||||||
"confirmations.discard_edit_media.message": "Jo hawwe net-bewarre wizigingen yn de mediabeskriuwing of foarfertoaning, wolle jo dizze dochs fuortsmite?",
|
"confirmations.discard_edit_media.message": "Jo hawwe net-bewarre wizigingen yn de mediabeskriuwing of foarfertoaning, wolle jo dizze dochs fuortsmite?",
|
||||||
"confirmations.domain_block.confirm": "Alles fan dit domein blokkearje",
|
"confirmations.domain_block.confirm": "Alles fan dit domein blokkearje",
|
||||||
|
@ -177,16 +177,16 @@
|
||||||
"confirmations.edit.confirm": "Bewurkje",
|
"confirmations.edit.confirm": "Bewurkje",
|
||||||
"confirmations.edit.message": "Troch no te bewurkjen sil it berjocht dat jo no oan it skriuwen binne oerskreaun wurde. Wolle jo trochgean?",
|
"confirmations.edit.message": "Troch no te bewurkjen sil it berjocht dat jo no oan it skriuwen binne oerskreaun wurde. Wolle jo trochgean?",
|
||||||
"confirmations.logout.confirm": "Ofmelde",
|
"confirmations.logout.confirm": "Ofmelde",
|
||||||
"confirmations.logout.message": "Bisto wis datsto ôfmelde wolst?",
|
"confirmations.logout.message": "Binne jo wis dat jo ôfmelde wolle?",
|
||||||
"confirmations.mute.confirm": "Negearje",
|
"confirmations.mute.confirm": "Negearje",
|
||||||
"confirmations.mute.explanation": "Dit sil berjochten fan harren en berjochten dêr’t se yn fermeld wurde ûnsichtber meitsje, mar se sille berjochten noch hieltyd sjen kinne en jo folgje kinne.",
|
"confirmations.mute.explanation": "Dit sil berjochten fan harren en berjochten dêr’t se yn fermeld wurde ûnsichtber meitsje, mar se sille jo berjochten noch hieltyd sjen kinne en jo folgje kinne.",
|
||||||
"confirmations.mute.message": "Binne jo wis dat jo {name} negearje wolle?",
|
"confirmations.mute.message": "Binne jo wis dat jo {name} negearje wolle?",
|
||||||
"confirmations.redraft.confirm": "Fuortsmite en opnij opstelle",
|
"confirmations.redraft.confirm": "Fuortsmite en opnij opstelle",
|
||||||
"confirmations.redraft.message": "Binne jo wis dat jo dit berjocht fuortsmite en opnij opstelle wolle? Favoriten en boosts geane dan ferlern en reaksjes op it oarspronklike berjocht reitsje jo kwyt.",
|
"confirmations.redraft.message": "Binne jo wis dat jo dit berjocht fuortsmite en opnij opstelle wolle? Favoriten en boosts geane dan ferlern en reaksjes op it oarspronklike berjocht reitsje jo kwyt.",
|
||||||
"confirmations.reply.confirm": "Reagearje",
|
"confirmations.reply.confirm": "Reagearje",
|
||||||
"confirmations.reply.message": "Troch no te reagearjen sil it berjocht dat jo no oan it skriuwen binne oerskreaun wurde. Wolle jo trochgean?",
|
"confirmations.reply.message": "Troch no te reagearjen sil it berjocht dat jo no oan it skriuwen binne oerskreaun wurde. Wolle jo trochgean?",
|
||||||
"confirmations.unfollow.confirm": "Net mear folgje",
|
"confirmations.unfollow.confirm": "Net mear folgje",
|
||||||
"confirmations.unfollow.message": "Bisto wis datsto {name} net mear folgje wolst?",
|
"confirmations.unfollow.message": "Binne jo wis dat jo {name} net mear folgje wolle?",
|
||||||
"conversation.delete": "Petear fuortsmite",
|
"conversation.delete": "Petear fuortsmite",
|
||||||
"conversation.mark_as_read": "As lêzen markearje",
|
"conversation.mark_as_read": "As lêzen markearje",
|
||||||
"conversation.open": "Petear toane",
|
"conversation.open": "Petear toane",
|
||||||
|
@ -351,7 +351,7 @@
|
||||||
"keyboard_shortcuts.local": "to open local timeline",
|
"keyboard_shortcuts.local": "to open local timeline",
|
||||||
"keyboard_shortcuts.mention": "Skriuwer fermelde",
|
"keyboard_shortcuts.mention": "Skriuwer fermelde",
|
||||||
"keyboard_shortcuts.muted": "to open muted users list",
|
"keyboard_shortcuts.muted": "to open muted users list",
|
||||||
"keyboard_shortcuts.my_profile": "Dyn profyl iepenje",
|
"keyboard_shortcuts.my_profile": "Jo profyl iepenje",
|
||||||
"keyboard_shortcuts.notifications": "Meldingen toane",
|
"keyboard_shortcuts.notifications": "Meldingen toane",
|
||||||
"keyboard_shortcuts.open_media": "Media iepenje",
|
"keyboard_shortcuts.open_media": "Media iepenje",
|
||||||
"keyboard_shortcuts.pinned": "Fêstsette berjochten toane",
|
"keyboard_shortcuts.pinned": "Fêstsette berjochten toane",
|
||||||
|
@ -421,20 +421,20 @@
|
||||||
"navigation_bar.public_timeline": "Globale tiidline",
|
"navigation_bar.public_timeline": "Globale tiidline",
|
||||||
"navigation_bar.search": "Sykje",
|
"navigation_bar.search": "Sykje",
|
||||||
"navigation_bar.security": "Befeiliging",
|
"navigation_bar.security": "Befeiliging",
|
||||||
"not_signed_in_indicator.not_signed_in": "Do moatst oanmelde om tagong ta dizze ynformaasje te krijen.",
|
"not_signed_in_indicator.not_signed_in": "Jo moatte oanmelde om tagong ta dizze ynformaasje te krijen.",
|
||||||
"notification.admin.report": "{name} hat {target} rapportearre",
|
"notification.admin.report": "{name} hat {target} rapportearre",
|
||||||
"notification.admin.sign_up": "{name} hat harren registrearre",
|
"notification.admin.sign_up": "{name} hat harren registrearre",
|
||||||
"notification.favourite": "{name} hat jo berjocht as favoryt markearre",
|
"notification.favourite": "{name} hat jo berjocht as favoryt markearre",
|
||||||
"notification.follow": "{name} folget dy",
|
"notification.follow": "{name} folget dy",
|
||||||
"notification.follow_request": "{name} hat dy in folchfersyk stjoerd",
|
"notification.follow_request": "{name} hat dy in folchfersyk stjoerd",
|
||||||
"notification.mention": "{name} hat dy fermeld",
|
"notification.mention": "{name} hat dy fermeld",
|
||||||
"notification.own_poll": "Dyn poll is beëinige",
|
"notification.own_poll": "Jo poll is beëinige",
|
||||||
"notification.poll": "In enkête dêr’t jo yn stimd hawwe is beëinige",
|
"notification.poll": "In enkête dêr’t jo yn stimd hawwe is beëinige",
|
||||||
"notification.reblog": "{name} hat jo berjocht boost",
|
"notification.reblog": "{name} hat jo berjocht boost",
|
||||||
"notification.status": "{name} hat in berjocht pleatst",
|
"notification.status": "{name} hat in berjocht pleatst",
|
||||||
"notification.update": "{name} hat in berjocht bewurke",
|
"notification.update": "{name} hat in berjocht bewurke",
|
||||||
"notifications.clear": "Meldingen wiskje",
|
"notifications.clear": "Meldingen wiskje",
|
||||||
"notifications.clear_confirmation": "Bisto wis datsto al dyn meldingen permanint fuortsmite wolst?",
|
"notifications.clear_confirmation": "Binne jo wis dat jo al jo meldingen permanint fuortsmite wolle?",
|
||||||
"notifications.column_settings.admin.report": "Nije rapportaazjes:",
|
"notifications.column_settings.admin.report": "Nije rapportaazjes:",
|
||||||
"notifications.column_settings.admin.sign_up": "Nije registraasjes:",
|
"notifications.column_settings.admin.sign_up": "Nije registraasjes:",
|
||||||
"notifications.column_settings.alert": "Desktopmeldingen",
|
"notifications.column_settings.alert": "Desktopmeldingen",
|
||||||
|
|
|
@ -209,7 +209,7 @@
|
||||||
"compose.language.search": "言語を検索...",
|
"compose.language.search": "言語を検索...",
|
||||||
"compose.published.body": "投稿されました!",
|
"compose.published.body": "投稿されました!",
|
||||||
"compose.published.open": "開く",
|
"compose.published.open": "開く",
|
||||||
"compose.saved.body": "投稿が保存されました",
|
"compose.saved.body": "変更を保存しました。",
|
||||||
"compose_form.direct_message_warning_learn_more": "もっと詳しく",
|
"compose_form.direct_message_warning_learn_more": "もっと詳しく",
|
||||||
"compose_form.encryption_warning": "Mastodonの投稿はエンドツーエンド暗号化に対応していません。安全に送受信されるべき情報をMastodonで共有しないでください。",
|
"compose_form.encryption_warning": "Mastodonの投稿はエンドツーエンド暗号化に対応していません。安全に送受信されるべき情報をMastodonで共有しないでください。",
|
||||||
"compose_form.hashtag_warning": "この投稿は公開設定ではないのでハッシュタグの一覧に表示されません。公開投稿だけがハッシュタグで検索できます。",
|
"compose_form.hashtag_warning": "この投稿は公開設定ではないのでハッシュタグの一覧に表示されません。公開投稿だけがハッシュタグで検索できます。",
|
||||||
|
|
|
@ -204,7 +204,7 @@
|
||||||
"dismissable_banner.explore_links": "이 소식들은 오늘 소셜 웹에서 가장 많이 공유된 내용들입니다. 새 소식을 더 많은 사람들이 공유할수록 높은 순위가 됩니다.",
|
"dismissable_banner.explore_links": "이 소식들은 오늘 소셜 웹에서 가장 많이 공유된 내용들입니다. 새 소식을 더 많은 사람들이 공유할수록 높은 순위가 됩니다.",
|
||||||
"dismissable_banner.explore_statuses": "이 게시물들은 오늘 소셜 웹에서 호응을 얻고 있는 게시물들입니다. 부스트와 관심을 받는 새로운 글들이 높은 순위가 됩니다.",
|
"dismissable_banner.explore_statuses": "이 게시물들은 오늘 소셜 웹에서 호응을 얻고 있는 게시물들입니다. 부스트와 관심을 받는 새로운 글들이 높은 순위가 됩니다.",
|
||||||
"dismissable_banner.explore_tags": "이 해시태그들은 이 서버와 분산화된 네트워크의 다른 서버에서 사람들의 인기를 끌고 있는 것들입니다.",
|
"dismissable_banner.explore_tags": "이 해시태그들은 이 서버와 분산화된 네트워크의 다른 서버에서 사람들의 인기를 끌고 있는 것들입니다.",
|
||||||
"dismissable_banner.public_timeline": "이것들은 {domain}에 있는 사람들이 팔로우한 사람들의 최신 게시물들입니다.",
|
"dismissable_banner.public_timeline": "{domain} 사람들이 팔로우하는 소셜 웹 사람들의 최신 공개 게시물입니다.",
|
||||||
"embed.instructions": "아래의 코드를 복사하여 대화를 원하는 곳으로 공유하세요.",
|
"embed.instructions": "아래의 코드를 복사하여 대화를 원하는 곳으로 공유하세요.",
|
||||||
"embed.preview": "이렇게 표시됩니다:",
|
"embed.preview": "이렇게 표시됩니다:",
|
||||||
"emoji_button.activity": "활동",
|
"emoji_button.activity": "활동",
|
||||||
|
|
|
@ -153,7 +153,7 @@
|
||||||
"compose_form.publish": "Legg ut",
|
"compose_form.publish": "Legg ut",
|
||||||
"compose_form.publish_form": "Legg ut",
|
"compose_form.publish_form": "Legg ut",
|
||||||
"compose_form.publish_loud": "{publish}!",
|
"compose_form.publish_loud": "{publish}!",
|
||||||
"compose_form.save_changes": "Gøym",
|
"compose_form.save_changes": "Lagre endringar",
|
||||||
"compose_form.sensitive.hide": "{count, plural, one {Marker mediet som ømtolig} other {Marker media som ømtolige}}",
|
"compose_form.sensitive.hide": "{count, plural, one {Marker mediet som ømtolig} other {Marker media som ømtolige}}",
|
||||||
"compose_form.sensitive.marked": "{count, plural, one {Mediet er markert som ømtolig} other {Media er markerte som ømtolige}}",
|
"compose_form.sensitive.marked": "{count, plural, one {Mediet er markert som ømtolig} other {Media er markerte som ømtolige}}",
|
||||||
"compose_form.sensitive.unmarked": "{count, plural, one {Mediet er ikkje markert som ømtolig} other {Media er ikkje markerte som ømtolige}}",
|
"compose_form.sensitive.unmarked": "{count, plural, one {Mediet er ikkje markert som ømtolig} other {Media er ikkje markerte som ømtolige}}",
|
||||||
|
@ -171,7 +171,7 @@
|
||||||
"confirmations.delete_list.confirm": "Slett",
|
"confirmations.delete_list.confirm": "Slett",
|
||||||
"confirmations.delete_list.message": "Er du sikker på at du vil sletta denne lista for alltid?",
|
"confirmations.delete_list.message": "Er du sikker på at du vil sletta denne lista for alltid?",
|
||||||
"confirmations.discard_edit_media.confirm": "Forkast",
|
"confirmations.discard_edit_media.confirm": "Forkast",
|
||||||
"confirmations.discard_edit_media.message": "Du har ulagra endringar i mediaskildringa eller førehandsvisinga. Vil du forkaste dei likevel?",
|
"confirmations.discard_edit_media.message": "Du har ulagra endringar i mediaskildringa eller førehandsvisinga. Vil du forkasta dei likevel?",
|
||||||
"confirmations.domain_block.confirm": "Skjul alt frå domenet",
|
"confirmations.domain_block.confirm": "Skjul alt frå domenet",
|
||||||
"confirmations.domain_block.message": "Er du heilt, heilt sikker på at du vil skjula heile {domain}? I dei fleste tilfelle er det godt nok og føretrekt med nokre få målretta blokkeringar eller målbindingar. Du kjem ikkje til å sjå innhald frå domenet i fødererte tidsliner eller i varsla dine. Fylgjarane dine frå domenet vert fjerna.",
|
"confirmations.domain_block.message": "Er du heilt, heilt sikker på at du vil skjula heile {domain}? I dei fleste tilfelle er det godt nok og føretrekt med nokre få målretta blokkeringar eller målbindingar. Du kjem ikkje til å sjå innhald frå domenet i fødererte tidsliner eller i varsla dine. Fylgjarane dine frå domenet vert fjerna.",
|
||||||
"confirmations.edit.confirm": "Rediger",
|
"confirmations.edit.confirm": "Rediger",
|
||||||
|
@ -285,7 +285,7 @@
|
||||||
"footer.privacy_policy": "Personvernsreglar",
|
"footer.privacy_policy": "Personvernsreglar",
|
||||||
"footer.source_code": "Vis kjeldekode",
|
"footer.source_code": "Vis kjeldekode",
|
||||||
"footer.status": "Status",
|
"footer.status": "Status",
|
||||||
"generic.saved": "Gøymt",
|
"generic.saved": "Lagra",
|
||||||
"getting_started.heading": "Kom i gang",
|
"getting_started.heading": "Kom i gang",
|
||||||
"hashtag.column_header.tag_mode.all": "og {additional}",
|
"hashtag.column_header.tag_mode.all": "og {additional}",
|
||||||
"hashtag.column_header.tag_mode.any": "eller {additional}",
|
"hashtag.column_header.tag_mode.any": "eller {additional}",
|
||||||
|
@ -314,7 +314,7 @@
|
||||||
"home.pending_critical_update.link": "Sjå oppdateringar",
|
"home.pending_critical_update.link": "Sjå oppdateringar",
|
||||||
"home.pending_critical_update.title": "Kritisk sikkerheitsoppdatering er tilgjengeleg!",
|
"home.pending_critical_update.title": "Kritisk sikkerheitsoppdatering er tilgjengeleg!",
|
||||||
"home.show_announcements": "Vis kunngjeringar",
|
"home.show_announcements": "Vis kunngjeringar",
|
||||||
"interaction_modal.description.favourite": "Med ein konto på Mastodon kan du favorittmerkja dette innlegget for å visa forfattaren at du set pris på det, og for å lagra det til seinare.",
|
"interaction_modal.description.favourite": "Med ein konto på Mastodon kan du favorittmerka dette innlegget for å visa forfattaren at du set pris på det, og for å lagra det til seinare.",
|
||||||
"interaction_modal.description.follow": "Med ein konto på Mastodon kan du fylgja {name} for å sjå innlegga deira i din heimestraum.",
|
"interaction_modal.description.follow": "Med ein konto på Mastodon kan du fylgja {name} for å sjå innlegga deira i din heimestraum.",
|
||||||
"interaction_modal.description.reblog": "Med ein konto på Mastodon kan du framheva dette innlegget for å dela det med dine eigne fylgjarar.",
|
"interaction_modal.description.reblog": "Med ein konto på Mastodon kan du framheva dette innlegget for å dela det med dine eigne fylgjarar.",
|
||||||
"interaction_modal.description.reply": "Med ein konto på Mastodon kan du svara på dette innlegget.",
|
"interaction_modal.description.reply": "Med ein konto på Mastodon kan du svara på dette innlegget.",
|
||||||
|
@ -673,7 +673,7 @@
|
||||||
"status.unmute_conversation": "Opphev målbinding av samtalen",
|
"status.unmute_conversation": "Opphev målbinding av samtalen",
|
||||||
"status.unpin": "Løys frå profil",
|
"status.unpin": "Løys frå profil",
|
||||||
"subscribed_languages.lead": "Kun innlegg på valde språk vil bli dukke opp i heimestraumen din og i listene dine etter denne endringa. For å motta innlegg på alle språk, la vere å velje nokon.",
|
"subscribed_languages.lead": "Kun innlegg på valde språk vil bli dukke opp i heimestraumen din og i listene dine etter denne endringa. For å motta innlegg på alle språk, la vere å velje nokon.",
|
||||||
"subscribed_languages.save": "Gøym",
|
"subscribed_languages.save": "Lagre endringar",
|
||||||
"subscribed_languages.target": "Endre abonnerte språk for {target}",
|
"subscribed_languages.target": "Endre abonnerte språk for {target}",
|
||||||
"tabs_bar.home": "Heim",
|
"tabs_bar.home": "Heim",
|
||||||
"tabs_bar.notifications": "Varsel",
|
"tabs_bar.notifications": "Varsel",
|
||||||
|
|
|
@ -303,7 +303,7 @@
|
||||||
"hashtag.unfollow": "Отпрати хеш ознаку",
|
"hashtag.unfollow": "Отпрати хеш ознаку",
|
||||||
"hashtags.and_other": "…и {count, plural, one {још #} few {још #}other {још #}}",
|
"hashtags.and_other": "…и {count, plural, one {још #} few {још #}other {још #}}",
|
||||||
"home.actions.go_to_explore": "Погледате шта је у тренду",
|
"home.actions.go_to_explore": "Погледате шта је у тренду",
|
||||||
"home.actions.go_to_suggestions": "Пронађeте људе које бисте пратили",
|
"home.actions.go_to_suggestions": "Пронађете људе које бисте пратили",
|
||||||
"home.column_settings.basic": "Основна",
|
"home.column_settings.basic": "Основна",
|
||||||
"home.column_settings.show_reblogs": "Прикажи подржавања",
|
"home.column_settings.show_reblogs": "Прикажи подржавања",
|
||||||
"home.column_settings.show_replies": "Прикажи одговоре",
|
"home.column_settings.show_replies": "Прикажи одговоре",
|
||||||
|
|
|
@ -629,7 +629,7 @@
|
||||||
"status.edit": "編輯",
|
"status.edit": "編輯",
|
||||||
"status.edited": "編輯於 {date}",
|
"status.edited": "編輯於 {date}",
|
||||||
"status.edited_x_times": "已編輯 {count, plural, one {{count} 次} other {{count} 次}}",
|
"status.edited_x_times": "已編輯 {count, plural, one {{count} 次} other {{count} 次}}",
|
||||||
"status.embed": "內嵌",
|
"status.embed": "內嵌嘟文",
|
||||||
"status.favourite": "最愛",
|
"status.favourite": "最愛",
|
||||||
"status.filter": "過濾此嘟文",
|
"status.filter": "過濾此嘟文",
|
||||||
"status.filtered": "已過濾",
|
"status.filtered": "已過濾",
|
||||||
|
|
61
app/javascript/mastodon/utils/react_router.jsx
Normal file
61
app/javascript/mastodon/utils/react_router.jsx
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
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 = {
|
||||||
|
...Component.propTypes,
|
||||||
|
wrappedComponentRef: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.func,
|
||||||
|
PropTypes.object
|
||||||
|
])
|
||||||
|
};
|
||||||
|
|
||||||
|
return hoistStatics(C, Component);
|
||||||
|
}
|
|
@ -2536,6 +2536,7 @@ $ui-header-height: 55px;
|
||||||
|
|
||||||
.navigation-panel__sign-in-banner,
|
.navigation-panel__sign-in-banner,
|
||||||
.navigation-panel__logo,
|
.navigation-panel__logo,
|
||||||
|
.navigation-panel__banner,
|
||||||
.getting-started__trends {
|
.getting-started__trends {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ class ActivityPub::LinkedDataSignature
|
||||||
return unless type == 'RsaSignature2017'
|
return unless type == 'RsaSignature2017'
|
||||||
|
|
||||||
creator = ActivityPub::TagManager.instance.uri_to_actor(creator_uri)
|
creator = ActivityPub::TagManager.instance.uri_to_actor(creator_uri)
|
||||||
creator ||= ActivityPub::FetchRemoteKeyService.new.call(creator_uri, id: false)
|
creator = ActivityPub::FetchRemoteKeyService.new.call(creator_uri, id: false) if creator&.public_key.blank?
|
||||||
|
|
||||||
return if creator.nil?
|
return if creator.nil?
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ class ActivityPub::LinkedDataSignature
|
||||||
to_be_verified = options_hash + document_hash
|
to_be_verified = options_hash + document_hash
|
||||||
|
|
||||||
creator if creator.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), Base64.decode64(signature), to_be_verified)
|
creator if creator.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), Base64.decode64(signature), to_be_verified)
|
||||||
|
rescue OpenSSL::PKey::RSAError
|
||||||
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def sign!(creator, sign_with: nil)
|
def sign!(creator, sign_with: nil)
|
||||||
|
|
|
@ -51,7 +51,7 @@ class FeaturedTag < ApplicationRecord
|
||||||
private
|
private
|
||||||
|
|
||||||
def strip_name
|
def strip_name
|
||||||
self.name = name&.strip&.gsub(/\A#/, '')
|
self.name = name&.strip&.delete_prefix('#')
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_tag
|
def set_tag
|
||||||
|
|
|
@ -55,7 +55,7 @@ class PreviewCard < ApplicationRecord
|
||||||
|
|
||||||
has_attached_file :image, processors: [:thumbnail, :blurhash_transcoder], styles: ->(f) { image_styles(f) }, convert_options: { all: '-quality 90 +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' }, validate_media_type: false
|
has_attached_file :image, processors: [:thumbnail, :blurhash_transcoder], styles: ->(f) { image_styles(f) }, convert_options: { all: '-quality 90 +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' }, validate_media_type: false
|
||||||
|
|
||||||
validates :url, presence: true, uniqueness: true
|
validates :url, presence: true, uniqueness: true, url: true
|
||||||
validates_attachment_content_type :image, content_type: IMAGE_MIME_TYPES
|
validates_attachment_content_type :image, content_type: IMAGE_MIME_TYPES
|
||||||
validates_attachment_size :image, less_than: LIMIT
|
validates_attachment_size :image, less_than: LIMIT
|
||||||
remotable_attachment :image, LIMIT
|
remotable_attachment :image, LIMIT
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class REST::ApplicationSerializer < ActiveModel::Serializer
|
class REST::ApplicationSerializer < ActiveModel::Serializer
|
||||||
attributes :id, :name, :website, :redirect_uri,
|
attributes :id, :name, :website, :scopes, :redirect_uri,
|
||||||
:client_id, :client_secret, :vapid_key
|
:client_id, :client_secret, :vapid_key
|
||||||
|
|
||||||
def id
|
def id
|
||||||
|
|
|
@ -107,8 +107,6 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
added_media_attachments = @next_media_attachments - previous_media_attachments
|
|
||||||
|
|
||||||
@status.ordered_media_attachment_ids = @next_media_attachments.map(&:id)
|
@status.ordered_media_attachment_ids = @next_media_attachments.map(&:id)
|
||||||
|
|
||||||
@media_attachments_changed = true if @status.ordered_media_attachment_ids != previous_media_attachments_ids
|
@media_attachments_changed = true if @status.ordered_media_attachment_ids != previous_media_attachments_ids
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
= image_tag appeal.account.avatar.url(:original), alt: '', width: 40, height: 40, class: 'avatar'
|
= image_tag appeal.account.avatar.url(:original), alt: '', width: 40, height: 40, class: 'avatar'
|
||||||
.log-entry__content
|
.log-entry__content
|
||||||
.log-entry__title
|
.log-entry__title
|
||||||
= t(appeal.strike.action, scope: 'admin.strikes.actions', name: content_tag(:span, appeal.strike.account.username, class: 'username'), target: content_tag(:span, appeal.account.username, class: 'target')).html_safe
|
= strike_action_label(appeal)
|
||||||
.log-entry__timestamp
|
.log-entry__timestamp
|
||||||
%time.formatted{ datetime: appeal.strike.created_at.iso8601 }
|
%time.formatted{ datetime: appeal.strike.created_at.iso8601 }
|
||||||
= l(appeal.strike.created_at)
|
= l(appeal.strike.created_at)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
.batch-table__row__content.pending-account
|
.batch-table__row__content.pending-account
|
||||||
.pending-account__header
|
.pending-account__header
|
||||||
= link_to preview_card.title, preview_card.url
|
= link_to preview_card.title, url_for_preview_card(preview_card)
|
||||||
|
|
||||||
%br/
|
%br/
|
||||||
|
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
{
|
|
||||||
"ignored_warnings": [
|
|
||||||
{
|
|
||||||
"warning_type": "Cross-Site Scripting",
|
|
||||||
"warning_code": 2,
|
|
||||||
"fingerprint": "71cf98c8235b5cfa9946b5db8fdc1a2f3a862566abb34e4542be6f3acae78233",
|
|
||||||
"check_name": "CrossSiteScripting",
|
|
||||||
"message": "Unescaped model attribute",
|
|
||||||
"file": "app/views/admin/disputes/appeals/_appeal.html.haml",
|
|
||||||
"line": 7,
|
|
||||||
"link": "https://brakemanscanner.org/docs/warning_types/cross_site_scripting",
|
|
||||||
"code": "t((Unresolved Model).new.strike.action, :scope => \"admin.strikes.actions\", :name => content_tag(:span, (Unresolved Model).new.strike.account.username, :class => \"username\"), :target => content_tag(:span, (Unresolved Model).new.account.username, :class => \"target\"))",
|
|
||||||
"render_path": [
|
|
||||||
{
|
|
||||||
"type": "template",
|
|
||||||
"name": "admin/disputes/appeals/index",
|
|
||||||
"line": 20,
|
|
||||||
"file": "app/views/admin/disputes/appeals/index.html.haml",
|
|
||||||
"rendered": {
|
|
||||||
"name": "admin/disputes/appeals/_appeal",
|
|
||||||
"file": "app/views/admin/disputes/appeals/_appeal.html.haml"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"location": {
|
|
||||||
"type": "template",
|
|
||||||
"template": "admin/disputes/appeals/_appeal"
|
|
||||||
},
|
|
||||||
"user_input": "(Unresolved Model).new.strike",
|
|
||||||
"confidence": "Weak",
|
|
||||||
"cwe_id": [
|
|
||||||
79
|
|
||||||
],
|
|
||||||
"note": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"warning_type": "Cross-Site Scripting",
|
|
||||||
"warning_code": 4,
|
|
||||||
"fingerprint": "cd5cfd7f40037fbfa753e494d7129df16e358bfc43ef0da3febafbf4ee1ed3ac",
|
|
||||||
"check_name": "LinkToHref",
|
|
||||||
"message": "Potentially unsafe model attribute in `link_to` href",
|
|
||||||
"file": "app/views/admin/trends/links/_preview_card.html.haml",
|
|
||||||
"line": 7,
|
|
||||||
"link": "https://brakemanscanner.org/docs/warning_types/link_to_href",
|
|
||||||
"code": "link_to((Unresolved Model).new.title, (Unresolved Model).new.url)",
|
|
||||||
"render_path": [
|
|
||||||
{
|
|
||||||
"type": "template",
|
|
||||||
"name": "admin/trends/links/index",
|
|
||||||
"line": 49,
|
|
||||||
"file": "app/views/admin/trends/links/index.html.haml",
|
|
||||||
"rendered": {
|
|
||||||
"name": "admin/trends/links/_preview_card",
|
|
||||||
"file": "app/views/admin/trends/links/_preview_card.html.haml"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"location": {
|
|
||||||
"type": "template",
|
|
||||||
"template": "admin/trends/links/_preview_card"
|
|
||||||
},
|
|
||||||
"user_input": "(Unresolved Model).new.url",
|
|
||||||
"confidence": "Weak",
|
|
||||||
"cwe_id": [
|
|
||||||
79
|
|
||||||
],
|
|
||||||
"note": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"warning_type": "Mass Assignment",
|
|
||||||
"warning_code": 105,
|
|
||||||
"fingerprint": "d0511f0287aea4ed9511f5a744f880cb15af77a8ec88f81b7365b00b642cf427",
|
|
||||||
"check_name": "PermitAttributes",
|
|
||||||
"message": "Potentially dangerous key allowed for mass assignment",
|
|
||||||
"file": "app/controllers/api/v1/reports_controller.rb",
|
|
||||||
"line": 26,
|
|
||||||
"link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
|
|
||||||
"code": "params.permit(:account_id, :comment, :category, :forward, :forward_to_domains => ([]), :status_ids => ([]), :rule_ids => ([]))",
|
|
||||||
"render_path": null,
|
|
||||||
"location": {
|
|
||||||
"type": "method",
|
|
||||||
"class": "Api::V1::ReportsController",
|
|
||||||
"method": "report_params"
|
|
||||||
},
|
|
||||||
"user_input": ":account_id",
|
|
||||||
"confidence": "High",
|
|
||||||
"cwe_id": [
|
|
||||||
915
|
|
||||||
],
|
|
||||||
"note": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"warning_type": "Mass Assignment",
|
|
||||||
"warning_code": 105,
|
|
||||||
"fingerprint": "dd59382eb5fda8da4d29f5d52dc8261ed9070d3c61cecc12b8332e18448b1c11",
|
|
||||||
"check_name": "PermitAttributes",
|
|
||||||
"message": "Potentially dangerous key allowed for mass assignment",
|
|
||||||
"file": "app/controllers/api/v2/search_controller.rb",
|
|
||||||
"line": 42,
|
|
||||||
"link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
|
|
||||||
"code": "params.permit(:type, :offset, :min_id, :max_id, :account_id, :following, :searchability)",
|
|
||||||
"render_path": null,
|
|
||||||
"location": {
|
|
||||||
"type": "method",
|
|
||||||
"class": "Api::V2::SearchController",
|
|
||||||
"method": "search_params"
|
|
||||||
},
|
|
||||||
"user_input": ":account_id",
|
|
||||||
"confidence": "High",
|
|
||||||
"cwe_id": [
|
|
||||||
915
|
|
||||||
],
|
|
||||||
"note": ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"updated": "2023-07-30 22:53:30 +0900",
|
|
||||||
"brakeman_version": "6.0.1"
|
|
||||||
}
|
|
|
@ -1,3 +1,5 @@
|
||||||
---
|
---
|
||||||
:skip_checks:
|
:skip_checks:
|
||||||
- CheckPermitAttributes
|
- CheckPermitAttributes
|
||||||
|
:url_safe_methods:
|
||||||
|
- url_for_preview_card
|
||||||
|
|
|
@ -9,9 +9,6 @@ Rails.application.config.middleware.use OmniAuth::Builder do
|
||||||
end
|
end
|
||||||
|
|
||||||
Devise.setup do |config|
|
Devise.setup do |config|
|
||||||
# Devise omniauth strategies
|
|
||||||
options = {}
|
|
||||||
|
|
||||||
# CAS strategy
|
# CAS strategy
|
||||||
if ENV['CAS_ENABLED'] == 'true'
|
if ENV['CAS_ENABLED'] == 'true'
|
||||||
cas_options = {}
|
cas_options = {}
|
||||||
|
|
|
@ -53,3 +53,7 @@ sk:
|
||||||
position:
|
position:
|
||||||
elevated: nemôže byť vyššia ako vaša súčasná rola
|
elevated: nemôže byť vyššia ako vaša súčasná rola
|
||||||
own_role: nie je možné zmeniť s vašou aktuálnou rolou
|
own_role: nie je možné zmeniť s vašou aktuálnou rolou
|
||||||
|
webhook:
|
||||||
|
attributes:
|
||||||
|
events:
|
||||||
|
invalid_permissions: nemožno zahrnúť udalosti, ku ktorým nemáte práva
|
||||||
|
|
|
@ -36,7 +36,7 @@ zh-CN:
|
||||||
status:
|
status:
|
||||||
attributes:
|
attributes:
|
||||||
reblog:
|
reblog:
|
||||||
taken: 已被转嘟过
|
taken: 已经被转嘟过
|
||||||
user:
|
user:
|
||||||
attributes:
|
attributes:
|
||||||
email:
|
email:
|
||||||
|
|
|
@ -13,7 +13,7 @@ fy:
|
||||||
locked: Jo account is blokkearre.
|
locked: Jo account is blokkearre.
|
||||||
not_found_in_database: "%{authentication_keys} of wachtwurd ûnjildich."
|
not_found_in_database: "%{authentication_keys} of wachtwurd ûnjildich."
|
||||||
pending: Jo account moat noch hieltyd beoardiele wurde.
|
pending: Jo account moat noch hieltyd beoardiele wurde.
|
||||||
timeout: Dyn sesje is ferrûn, meld dy opnij oan.
|
timeout: Jo sesje is ferrûn. Meld jo opnij oan om troch te gean.
|
||||||
unauthenticated: Jo moatte oanmelde of registrearje.
|
unauthenticated: Jo moatte oanmelde of registrearje.
|
||||||
unconfirmed: Jo moatte earst jo account befêstigje.
|
unconfirmed: Jo moatte earst jo account befêstigje.
|
||||||
mailer:
|
mailer:
|
||||||
|
|
|
@ -9,7 +9,7 @@ zh-CN:
|
||||||
already_authenticated: 你已登录。
|
already_authenticated: 你已登录。
|
||||||
inactive: 你还没有激活账户。
|
inactive: 你还没有激活账户。
|
||||||
invalid: "%{authentication_keys} 无效或密码错误。"
|
invalid: "%{authentication_keys} 无效或密码错误。"
|
||||||
last_attempt: 你只有最后一次尝试机会,若未通过,账号将被锁定。
|
last_attempt: 你只有最后一次尝试机会,若未通过,帐号将被锁定。
|
||||||
locked: 你的账户已被锁定。
|
locked: 你的账户已被锁定。
|
||||||
not_found_in_database: "%{authentication_keys}或密码错误。"
|
not_found_in_database: "%{authentication_keys}或密码错误。"
|
||||||
pending: 你的账号仍在审核中。
|
pending: 你的账号仍在审核中。
|
||||||
|
@ -85,7 +85,7 @@ zh-CN:
|
||||||
send_instructions: 如果你的电子邮件地址存在于我们的数据库中,你将在几分钟后收到一个密码恢复链接。如果你没有收到这封邮件,请检查你邮箱的垃圾箱。
|
send_instructions: 如果你的电子邮件地址存在于我们的数据库中,你将在几分钟后收到一个密码恢复链接。如果你没有收到这封邮件,请检查你邮箱的垃圾箱。
|
||||||
send_paranoid_instructions: 如果你的电子邮件地址存在于我们的数据库中,你将在几分钟后收到一个密码恢复链接。如果你没有收到这封邮件,请检查你邮箱的垃圾箱。
|
send_paranoid_instructions: 如果你的电子邮件地址存在于我们的数据库中,你将在几分钟后收到一个密码恢复链接。如果你没有收到这封邮件,请检查你邮箱的垃圾箱。
|
||||||
updated: 你的密码已成功修改,现在你已登录。
|
updated: 你的密码已成功修改,现在你已登录。
|
||||||
updated_not_active: 你的密码已成功修改。
|
updated_not_active: 你的密码已修改成功。
|
||||||
registrations:
|
registrations:
|
||||||
destroyed: 再见!你的账户已成功注销。我们希望很快可以再见到你。
|
destroyed: 再见!你的账户已成功注销。我们希望很快可以再见到你。
|
||||||
signed_up: 欢迎!你已成功注册。
|
signed_up: 欢迎!你已成功注册。
|
||||||
|
|
|
@ -43,7 +43,7 @@ fy:
|
||||||
new: Nije tapassing
|
new: Nije tapassing
|
||||||
scopes: Tastimmingen
|
scopes: Tastimmingen
|
||||||
show: Toane
|
show: Toane
|
||||||
title: Dyn tapassingen
|
title: Jo tapassingen
|
||||||
new:
|
new:
|
||||||
title: Nije tapassing
|
title: Nije tapassing
|
||||||
show:
|
show:
|
||||||
|
@ -60,7 +60,7 @@ fy:
|
||||||
error:
|
error:
|
||||||
title: Der is in flater bard
|
title: Der is in flater bard
|
||||||
new:
|
new:
|
||||||
prompt_html: "%{client_name} hat tastimming nedich om tagong te krijen ta dyn account. It giet om in tapassing fan in tredde partij.<strong>Asto dit net fertroust, moatsto gjin tastimming jaan.</strong>"
|
prompt_html: "%{client_name} hat tastimming nedich om tagong te krijen ta jo account. It giet om in tapassing fan in tredde partij.<strong>As jo dit net fertrouwe, moatte jo gjin tastimming jaan.</strong>"
|
||||||
review_permissions: Tastimmingen beoardiele
|
review_permissions: Tastimmingen beoardiele
|
||||||
title: Autorisaasje fereaske
|
title: Autorisaasje fereaske
|
||||||
show:
|
show:
|
||||||
|
@ -69,15 +69,15 @@ fy:
|
||||||
buttons:
|
buttons:
|
||||||
revoke: Ynlûke
|
revoke: Ynlûke
|
||||||
confirmations:
|
confirmations:
|
||||||
revoke: Bisto wis?
|
revoke: Binne jo wis?
|
||||||
index:
|
index:
|
||||||
authorized_at: Autorisearre op %{date}
|
authorized_at: Autorisearre op %{date}
|
||||||
description_html: Dit binne tapassingen dy’t tagong hawwe ta dyn account fia de API. As der tapassingen tusken steane dy’tsto net werkenst of in tapassing harren misdraacht, kinsto de tagongsrjochten fan de tapassing ynlûke.
|
description_html: Dit binne tapassingen dy’t fia de API tagong hawwe ta jo account. As der tapassingen tusken steane dy’t jo net werkenne of in tapassing harren misdraacht, kinne jo de tagongsrjochten fan de tapassing ynlûke.
|
||||||
last_used_at: Lêst brûkt op %{date}
|
last_used_at: Lêst brûkt op %{date}
|
||||||
never_used: Nea brûkt
|
never_used: Nea brûkt
|
||||||
scopes: Tastimmingen
|
scopes: Tastimmingen
|
||||||
superapp: Yntern
|
superapp: Yntern
|
||||||
title: Dyn autorisearre tapassingen
|
title: Jo autorisearre tapassingen
|
||||||
errors:
|
errors:
|
||||||
messages:
|
messages:
|
||||||
access_denied: De boarne-eigener of autorisaasjeserver hat it fersyk wegere.
|
access_denied: De boarne-eigener of autorisaasjeserver hat it fersyk wegere.
|
||||||
|
@ -165,22 +165,22 @@ fy:
|
||||||
admin:write:reports: moderaasjemaatregelen nimme yn rapportaazjes
|
admin:write:reports: moderaasjemaatregelen nimme yn rapportaazjes
|
||||||
crypto: ein-ta-ein-fersifering brûke
|
crypto: ein-ta-ein-fersifering brûke
|
||||||
follow: relaasjes tusken accounts bewurkje
|
follow: relaasjes tusken accounts bewurkje
|
||||||
push: dyn pushmeldingen ûntfange
|
push: jo pushmeldingen ûntfange
|
||||||
read: alle gegevens fan dyn account lêze
|
read: alle gegevens fan jo account lêze
|
||||||
read:accounts: accountynformaasje besjen
|
read:accounts: accountynformaasje besjen
|
||||||
read:blocks: dyn blokkearre brûkers besjen
|
read:blocks: jo blokkearre brûkers besjen
|
||||||
read:bookmarks: dyn blêdwizers besjen
|
read:bookmarks: jo blêdwizers besjen
|
||||||
read:favourites: jo favoriten besjen
|
read:favourites: jo favoriten besjen
|
||||||
read:filters: dyn filters besjen
|
read:filters: jo filters besjen
|
||||||
read:follows: de accounts dy’tsto folgest besjen
|
read:follows: de accounts dy’tsto folgest besjen
|
||||||
read:lists: dyn listen besjen
|
read:lists: jo listen besjen
|
||||||
read:mutes: dyn negearre brûkers besjen
|
read:mutes: jo negearre brûkers besjen
|
||||||
read:notifications: dyn meldingen besjen
|
read:notifications: jo meldingen besjen
|
||||||
read:reports: dyn rapportearre berjochten besjen
|
read:reports: jo rapportearre berjochten besjen
|
||||||
read:search: út dyn namme sykje
|
read:search: út jo namme sykje
|
||||||
read:statuses: alle berjochten besjen
|
read:statuses: alle berjochten besjen
|
||||||
write: alle gegevens fan dyn account bewurkje
|
write: alle gegevens fan jo account bewurkje
|
||||||
write:accounts: dyn profyl bewurkje
|
write:accounts: jo profyl bewurkje
|
||||||
write:blocks: accounts en domeinen blokkearje
|
write:blocks: accounts en domeinen blokkearje
|
||||||
write:bookmarks: berjochten oan blêdwizers tafoegje
|
write:bookmarks: berjochten oan blêdwizers tafoegje
|
||||||
write:conversations: petearen negearre en fuortsmite
|
write:conversations: petearen negearre en fuortsmite
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue