diff options
author | David Yip <yipdw@member.fsf.org> | 2018-06-12 16:39:30 -0500 |
---|---|---|
committer | David Yip <yipdw@member.fsf.org> | 2018-06-12 16:39:30 -0500 |
commit | e931cf656d1de6d89b5b048d8f1de15be7b52690 (patch) | |
tree | b1c0c66b6a88b56c422ea8be1dbef77e42afae72 /app | |
parent | 97d2df77aae687c983c1294ebcd3962e4f9d985c (diff) | |
parent | 34f1fd2a621ca869c17009487e2f10063812fbd0 (diff) |
Merge remote-tracking branch 'glitchsoc/master' into 454-allow-keyword-mutes-to-skip-mentions
Conflicts: app/models/glitch/keyword_mute.rb
Diffstat (limited to 'app')
84 files changed, 356 insertions, 458 deletions
diff --git a/app/controllers/api/v1/trends_controller.rb b/app/controllers/api/v1/trends_controller.rb deleted file mode 100644 index bcea9857e..000000000 --- a/app/controllers/api/v1/trends_controller.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -class Api::V1::TrendsController < Api::BaseController - before_action :set_tags - - respond_to :json - - def index - render json: @tags, each_serializer: REST::TagSerializer - end - - private - - def set_tags - @tags = TrendingTags.get(limit_param(10)) - end -end diff --git a/app/javascript/flavours/glitch/components/column_back_button.js b/app/javascript/flavours/glitch/components/column_back_button.js index 50c3bf11f..a562ef9b9 100644 --- a/app/javascript/flavours/glitch/components/column_back_button.js +++ b/app/javascript/flavours/glitch/components/column_back_button.js @@ -10,10 +10,10 @@ export default class ColumnBackButton extends React.PureComponent { handleClick = () => { // if history is exhausted, or we would leave mastodon, just go to root. - if (window.history && (window.history.length === 1 || window.history.length === window._mastoInitialHistoryLen)) { - this.context.router.history.push('/'); - } else { + if (window.history.state) { this.context.router.history.goBack(); + } else { + this.context.router.history.push('/'); } } diff --git a/app/javascript/flavours/glitch/components/column_back_button_slim.js b/app/javascript/flavours/glitch/components/column_back_button_slim.js index 2cdf1b25b..c99c202af 100644 --- a/app/javascript/flavours/glitch/components/column_back_button_slim.js +++ b/app/javascript/flavours/glitch/components/column_back_button_slim.js @@ -10,10 +10,10 @@ export default class ColumnBackButtonSlim extends React.PureComponent { handleClick = () => { // if history is exhausted, or we would leave mastodon, just go to root. - if (window.history && (window.history.length === 1 || window.history.length === window._mastoInitialHistoryLen)) { - this.context.router.history.push('/'); - } else { + if (window.history.state) { this.context.router.history.goBack(); + } else { + this.context.router.history.push('/'); } } diff --git a/app/javascript/flavours/glitch/components/column_header.js b/app/javascript/flavours/glitch/components/column_header.js index bfad6467d..72207637d 100644 --- a/app/javascript/flavours/glitch/components/column_header.js +++ b/app/javascript/flavours/glitch/components/column_header.js @@ -66,10 +66,10 @@ export default class ColumnHeader extends React.PureComponent { handleBackClick = () => { // if history is exhausted, or we would leave mastodon, just go to root. - if (window.history && (window.history.length === 1 || window.history.length === window._mastoInitialHistoryLen)) { - this.context.router.history.push('/'); - } else { + if (window.history.state) { this.context.router.history.goBack(); + } else { + this.context.router.history.push('/'); } } diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js index 0e3a83bb6..4a7a7d0f4 100644 --- a/app/javascript/flavours/glitch/features/ui/index.js +++ b/app/javascript/flavours/glitch/features/ui/index.js @@ -99,10 +99,6 @@ const keyMap = { @withRouter export default class UI extends React.Component { - static contextTypes = { - router: PropTypes.object.isRequired, - }; - static propTypes = { dispatch: PropTypes.func.isRequired, children: PropTypes.node, @@ -113,6 +109,7 @@ export default class UI extends React.Component { isComposing: PropTypes.bool, hasComposingText: PropTypes.bool, location: PropTypes.object, + router: PropTypes.object, intl: PropTypes.object.isRequired, dropdownMenuIsOpen: PropTypes.bool, }; @@ -200,7 +197,7 @@ export default class UI extends React.Component { handleServiceWorkerPostMessage = ({ data }) => { if (data.type === 'navigate') { - this.context.router.history.push(data.path); + this.props.router.history.push(data.path); } else { console.warn('Unknown message type:', data.type); } @@ -305,10 +302,11 @@ export default class UI extends React.Component { } handleHotkeyBack = () => { - if (window.history && window.history.length === 1) { - this.context.router.history.push('/'); - } else { + // if history is exhausted, or we would leave mastodon, just go to root. + if (window.history.state) { this.context.router.history.goBack(); + } else { + this.context.router.history.push('/'); } } @@ -318,54 +316,54 @@ export default class UI extends React.Component { handleHotkeyToggleHelp = () => { if (this.props.location.pathname === '/keyboard-shortcuts') { - this.context.router.history.goBack(); + this.props.router.history.goBack(); } else { - this.context.router.history.push('/keyboard-shortcuts'); + this.props.router.history.push('/keyboard-shortcuts'); } } handleHotkeyGoToHome = () => { - this.context.router.history.push('/timelines/home'); + this.props.router.history.push('/timelines/home'); } handleHotkeyGoToNotifications = () => { - this.context.router.history.push('/notifications'); + this.props.router.history.push('/notifications'); } handleHotkeyGoToLocal = () => { - this.context.router.history.push('/timelines/public/local'); + this.props.router.history.push('/timelines/public/local'); } handleHotkeyGoToFederated = () => { - this.context.router.history.push('/timelines/public'); + this.props.router.history.push('/timelines/public'); } handleHotkeyGoToDirect = () => { - this.context.router.history.push('/timelines/direct'); + this.props.router.history.push('/timelines/direct'); } handleHotkeyGoToStart = () => { - this.context.router.history.push('/getting-started'); + this.props.router.history.push('/getting-started'); } handleHotkeyGoToFavourites = () => { - this.context.router.history.push('/favourites'); + this.props.router.history.push('/favourites'); } handleHotkeyGoToPinned = () => { - this.context.router.history.push('/pinned'); + this.props.router.history.push('/pinned'); } handleHotkeyGoToProfile = () => { - this.context.router.history.push(`/accounts/${me}`); + this.props.router.history.push(`/accounts/${me}`); } handleHotkeyGoToBlocked = () => { - this.context.router.history.push('/blocks'); + this.props.router.history.push('/blocks'); } handleHotkeyGoToMuted = () => { - this.context.router.history.push('/mutes'); + this.props.router.history.push('/mutes'); } render () { diff --git a/app/javascript/flavours/glitch/reducers/accounts.js b/app/javascript/flavours/glitch/reducers/accounts.js index 86f4970c9..2156de029 100644 --- a/app/javascript/flavours/glitch/reducers/accounts.js +++ b/app/javascript/flavours/glitch/reducers/accounts.js @@ -27,7 +27,6 @@ import { FAVOURITES_FETCH_SUCCESS, } from 'flavours/glitch/actions/interactions'; import { - TIMELINE_REFRESH_SUCCESS, TIMELINE_UPDATE, TIMELINE_EXPAND_SUCCESS, } from 'flavours/glitch/actions/timelines'; @@ -38,7 +37,6 @@ import { import { SEARCH_FETCH_SUCCESS } from 'flavours/glitch/actions/search'; import { NOTIFICATIONS_UPDATE, - NOTIFICATIONS_REFRESH_SUCCESS, NOTIFICATIONS_EXPAND_SUCCESS, } from 'flavours/glitch/actions/notifications'; import { @@ -144,11 +142,9 @@ export default function accounts(state = initialState, action) { case LIST_ACCOUNTS_FETCH_SUCCESS: case LIST_EDITOR_SUGGESTIONS_READY: return action.accounts ? normalizeAccounts(state, action.accounts) : state; - case NOTIFICATIONS_REFRESH_SUCCESS: case NOTIFICATIONS_EXPAND_SUCCESS: case SEARCH_FETCH_SUCCESS: return normalizeAccountsFromStatuses(normalizeAccounts(state, action.accounts), action.statuses); - case TIMELINE_REFRESH_SUCCESS: case TIMELINE_EXPAND_SUCCESS: case CONTEXT_FETCH_SUCCESS: case FAVOURITED_STATUSES_FETCH_SUCCESS: diff --git a/app/javascript/flavours/glitch/reducers/accounts_counters.js b/app/javascript/flavours/glitch/reducers/accounts_counters.js index 7abcb5dec..64dff9b55 100644 --- a/app/javascript/flavours/glitch/reducers/accounts_counters.js +++ b/app/javascript/flavours/glitch/reducers/accounts_counters.js @@ -29,7 +29,6 @@ import { FAVOURITES_FETCH_SUCCESS, } from 'flavours/glitch/actions/interactions'; import { - TIMELINE_REFRESH_SUCCESS, TIMELINE_UPDATE, TIMELINE_EXPAND_SUCCESS, } from 'flavours/glitch/actions/timelines'; @@ -40,7 +39,6 @@ import { import { SEARCH_FETCH_SUCCESS } from 'flavours/glitch/actions/search'; import { NOTIFICATIONS_UPDATE, - NOTIFICATIONS_REFRESH_SUCCESS, NOTIFICATIONS_EXPAND_SUCCESS, } from 'flavours/glitch/actions/notifications'; import { @@ -119,11 +117,9 @@ export default function accountsCounters(state = initialState, action) { case LIST_ACCOUNTS_FETCH_SUCCESS: case LIST_EDITOR_SUGGESTIONS_READY: return action.accounts ? normalizeAccounts(state, action.accounts) : state; - case NOTIFICATIONS_REFRESH_SUCCESS: case NOTIFICATIONS_EXPAND_SUCCESS: case SEARCH_FETCH_SUCCESS: return normalizeAccountsFromStatuses(normalizeAccounts(state, action.accounts), action.statuses); - case TIMELINE_REFRESH_SUCCESS: case TIMELINE_EXPAND_SUCCESS: case CONTEXT_FETCH_SUCCESS: case FAVOURITED_STATUSES_FETCH_SUCCESS: diff --git a/app/javascript/flavours/glitch/reducers/statuses.js b/app/javascript/flavours/glitch/reducers/statuses.js index bc5bc1804..94f367d72 100644 --- a/app/javascript/flavours/glitch/reducers/statuses.js +++ b/app/javascript/flavours/glitch/reducers/statuses.js @@ -21,14 +21,12 @@ import { STATUS_UNMUTE_SUCCESS, } from 'flavours/glitch/actions/statuses'; import { - TIMELINE_REFRESH_SUCCESS, TIMELINE_UPDATE, TIMELINE_DELETE, TIMELINE_EXPAND_SUCCESS, } from 'flavours/glitch/actions/timelines'; import { NOTIFICATIONS_UPDATE, - NOTIFICATIONS_REFRESH_SUCCESS, NOTIFICATIONS_EXPAND_SUCCESS, } from 'flavours/glitch/actions/notifications'; import { @@ -129,10 +127,8 @@ export default function statuses(state = initialState, action) { return state.setIn([action.id, 'muted'], true); case STATUS_UNMUTE_SUCCESS: return state.setIn([action.id, 'muted'], false); - case TIMELINE_REFRESH_SUCCESS: case TIMELINE_EXPAND_SUCCESS: case CONTEXT_FETCH_SUCCESS: - case NOTIFICATIONS_REFRESH_SUCCESS: case NOTIFICATIONS_EXPAND_SUCCESS: case FAVOURITED_STATUSES_FETCH_SUCCESS: case FAVOURITED_STATUSES_EXPAND_SUCCESS: diff --git a/app/javascript/flavours/glitch/util/main.js b/app/javascript/flavours/glitch/util/main.js index c00210677..b76826481 100644 --- a/app/javascript/flavours/glitch/util/main.js +++ b/app/javascript/flavours/glitch/util/main.js @@ -28,11 +28,6 @@ function main() { store.dispatch(registerPushNotifications.register()); } perf.stop('main()'); - - // remember the initial URL - if (window.history && typeof window._mastoInitialHistoryLen === 'undefined') { - window._mastoInitialHistoryLen = window.history.length; - } }); } diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js index 849cb4f5a..3e1e5f270 100644 --- a/app/javascript/mastodon/actions/statuses.js +++ b/app/javascript/mastodon/actions/statuses.js @@ -29,6 +29,8 @@ export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL'; export const STATUS_REVEAL = 'STATUS_REVEAL'; export const STATUS_HIDE = 'STATUS_HIDE'; +export const REDRAFT = 'REDRAFT'; + export function fetchStatusRequest(id, skipLoading) { return { type: STATUS_FETCH_REQUEST, @@ -131,14 +133,27 @@ export function fetchStatusFail(id, error, skipLoading) { }; }; -export function deleteStatus(id) { +export function redraft(status) { + return { + type: REDRAFT, + status, + }; +}; + +export function deleteStatus(id, withRedraft = false) { return (dispatch, getState) => { + const status = getState().getIn(['statuses', id]); + dispatch(deleteStatusRequest(id)); api(getState).delete(`/api/v1/statuses/${id}`).then(() => { evictStatus(id); dispatch(deleteStatusSuccess(id)); dispatch(deleteFromTimelines(id)); + + if (withRedraft) { + dispatch(redraft(status)); + } }).catch(error => { dispatch(deleteStatusFail(id, error)); }); diff --git a/app/javascript/mastodon/actions/trends.js b/app/javascript/mastodon/actions/trends.js deleted file mode 100644 index 853e4f60a..000000000 --- a/app/javascript/mastodon/actions/trends.js +++ /dev/null @@ -1,32 +0,0 @@ -import api from '../api'; - -export const TRENDS_FETCH_REQUEST = 'TRENDS_FETCH_REQUEST'; -export const TRENDS_FETCH_SUCCESS = 'TRENDS_FETCH_SUCCESS'; -export const TRENDS_FETCH_FAIL = 'TRENDS_FETCH_FAIL'; - -export const fetchTrends = () => (dispatch, getState) => { - dispatch(fetchTrendsRequest()); - - api(getState) - .get('/api/v1/trends') - .then(({ data }) => dispatch(fetchTrendsSuccess(data))) - .catch(err => dispatch(fetchTrendsFail(err))); -}; - -export const fetchTrendsRequest = () => ({ - type: TRENDS_FETCH_REQUEST, - skipLoading: true, -}); - -export const fetchTrendsSuccess = trends => ({ - type: TRENDS_FETCH_SUCCESS, - trends, - skipLoading: true, -}); - -export const fetchTrendsFail = error => ({ - type: TRENDS_FETCH_FAIL, - error, - skipLoading: true, - skipAlert: true, -}); diff --git a/app/javascript/mastodon/components/hashtag.js b/app/javascript/mastodon/components/hashtag.js index cc37a91e2..a407df31e 100644 --- a/app/javascript/mastodon/components/hashtag.js +++ b/app/javascript/mastodon/components/hashtag.js @@ -1,16 +1,9 @@ import React from 'react'; import { Sparklines, SparklinesCurve } from 'react-sparklines'; import { Link } from 'react-router-dom'; -import { FormattedMessage, FormattedNumber } from 'react-intl'; +import { FormattedMessage } from 'react-intl'; import ImmutablePropTypes from 'react-immutable-proptypes'; - -const shortNumberFormat = number => { - if (number < 1000) { - return <FormattedNumber value={number} />; - } else { - return <React.Fragment><FormattedNumber value={number / 1000} maximumFractionDigits={1} />K</React.Fragment>; - } -}; +import { shortNumberFormat } from '../utils/numbers'; const Hashtag = ({ hashtag }) => ( <div className='trends__item'> diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js index d605dbc8a..0ae21e3f0 100644 --- a/app/javascript/mastodon/components/status_action_bar.js +++ b/app/javascript/mastodon/components/status_action_bar.js @@ -9,6 +9,7 @@ import { me } from '../initial_state'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, + redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' }, direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' }, mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, @@ -88,6 +89,10 @@ export default class StatusActionBar extends ImmutablePureComponent { this.props.onDelete(this.props.status); } + handleRedraftClick = () => { + this.props.onDelete(this.props.status, true); + } + handlePinClick = () => { this.props.onPin(this.props.status); } @@ -159,6 +164,7 @@ export default class StatusActionBar extends ImmutablePureComponent { } menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); + menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick }); } else { menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick }); diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js index f22509edf..3e7b5215b 100644 --- a/app/javascript/mastodon/containers/status_container.js +++ b/app/javascript/mastodon/containers/status_container.js @@ -33,6 +33,8 @@ import { showAlertForError } from '../actions/alerts'; const messages = defineMessages({ deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' }, + redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' }, + redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, }); @@ -91,14 +93,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ })); }, - onDelete (status) { + onDelete (status, withRedraft = false) { if (!deleteModal) { - dispatch(deleteStatus(status.get('id'))); + dispatch(deleteStatus(status.get('id'), withRedraft)); } else { dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.deleteMessage), - confirm: intl.formatMessage(messages.deleteConfirm), - onConfirm: () => dispatch(deleteStatus(status.get('id'))), + message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), + confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), + onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)), })); } }, diff --git a/app/javascript/mastodon/features/account/components/action_bar.js b/app/javascript/mastodon/features/account/components/action_bar.js index 3a1f92811..2d0f72be2 100644 --- a/app/javascript/mastodon/features/account/components/action_bar.js +++ b/app/javascript/mastodon/features/account/components/action_bar.js @@ -3,8 +3,9 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; import { Link } from 'react-router-dom'; -import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { me } from '../../../initial_state'; +import { shortNumberFormat } from '../../../utils/numbers'; const messages = defineMessages({ mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' }, @@ -146,17 +147,17 @@ export default class ActionBar extends React.PureComponent { <div className='account__action-bar-links'> <Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}`}> <span><FormattedMessage id='account.posts' defaultMessage='Toots' /></span> - <strong><FormattedNumber value={account.get('statuses_count')} /></strong> + <strong>{shortNumberFormat(account.get('statuses_count'))}</strong> </Link> <Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/following`}> <span><FormattedMessage id='account.follows' defaultMessage='Follows' /></span> - <strong><FormattedNumber value={account.get('following_count')} /></strong> + <strong>{shortNumberFormat(account.get('following_count'))}</strong> </Link> <Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/followers`}> <span><FormattedMessage id='account.followers' defaultMessage='Followers' /></span> - <strong><FormattedNumber value={account.get('followers_count')} /></strong> + <strong>{shortNumberFormat(account.get('followers_count'))}</strong> </Link> </div> </div> diff --git a/app/javascript/mastodon/features/compose/components/search_results.js b/app/javascript/mastodon/features/compose/components/search_results.js index cf022362e..c351b84bb 100644 --- a/app/javascript/mastodon/features/compose/components/search_results.js +++ b/app/javascript/mastodon/features/compose/components/search_results.js @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { FormattedMessage } from 'react-intl'; import AccountContainer from '../../../containers/account_container'; @@ -11,36 +10,14 @@ export default class SearchResults extends ImmutablePureComponent { static propTypes = { results: ImmutablePropTypes.map.isRequired, - trends: ImmutablePropTypes.list, - fetchTrends: PropTypes.func.isRequired, }; - componentDidMount () { - const { fetchTrends } = this.props; - fetchTrends(); - } - render () { - const { results, trends } = this.props; + const { results } = this.props; let accounts, statuses, hashtags; let count = 0; - if (results.isEmpty()) { - return ( - <div className='search-results'> - <div className='trends'> - <div className='trends__header'> - <i className='fa fa-fire fa-fw' /> - <FormattedMessage id='trends.header' defaultMessage='Trending now' /> - </div> - - {trends && trends.map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)} - </div> - </div> - ); - } - if (results.get('accounts') && results.get('accounts').size > 0) { count += results.get('accounts').size; accounts = ( diff --git a/app/javascript/mastodon/features/compose/containers/search_results_container.js b/app/javascript/mastodon/features/compose/containers/search_results_container.js index 2f879f9d9..16d95d417 100644 --- a/app/javascript/mastodon/features/compose/containers/search_results_container.js +++ b/app/javascript/mastodon/features/compose/containers/search_results_container.js @@ -1,14 +1,8 @@ import { connect } from 'react-redux'; import SearchResults from '../components/search_results'; -import { fetchTrends } from '../../../actions/trends'; const mapStateToProps = state => ({ results: state.getIn(['search', 'results']), - trends: state.getIn(['trends', 'items']), }); -const mapDispatchToProps = dispatch => ({ - fetchTrends: () => dispatch(fetchTrends()), -}); - -export default connect(mapStateToProps, mapDispatchToProps)(SearchResults); +export default connect(mapStateToProps)(SearchResults); diff --git a/app/javascript/mastodon/features/getting_started/components/trends.js b/app/javascript/mastodon/features/getting_started/components/trends.js deleted file mode 100644 index 96a646bea..000000000 --- a/app/javascript/mastodon/features/getting_started/components/trends.js +++ /dev/null @@ -1,71 +0,0 @@ -import classNames from 'classnames'; -import React from 'react'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { FormattedMessage, defineMessages } from 'react-intl'; -import Hashtag from '../../../components/hashtag'; -import { Link } from 'react-router-dom'; - -const messages = defineMessages({ - refresh_trends: { id: 'trends.refresh', defaultMessage: 'Refresh' }, -}); - -export default class Trends extends ImmutablePureComponent { - - static defaultProps = { - loading: false, - }; - - static propTypes = { - trends: ImmutablePropTypes.list, - loading: PropTypes.bool.isRequired, - showTrends: PropTypes.bool.isRequired, - fetchTrends: PropTypes.func.isRequired, - toggleTrends: PropTypes.func.isRequired, - }; - - componentDidMount () { - setTimeout(() => this.props.fetchTrends(), 5000); - } - - handleRefreshTrends = () => { - this.props.fetchTrends(); - } - - handleToggle = () => { - this.props.toggleTrends(!this.props.showTrends); - } - - render () { - const { intl, trends, loading, showTrends } = this.props; - - if (!trends || trends.size < 1) { - return null; - } - - return ( - <div className='getting-started__trends'> - <div className='column-header__wrapper'> - <h1 className='column-header'> - <button> - <i className='fa fa-fire fa-fw' /> - <FormattedMessage id='trends.header' defaultMessage='Trending now' /> - </button> - - <div className='column-header__buttons'> - {showTrends && <button onClick={this.handleRefreshTrends} className='column-header__button' title={intl.formatMessage(messages.refresh_trends)} aria-label={intl.formatMessage(messages.refresh_trends)} disabled={loading}><i className={classNames('fa', 'fa-refresh', { 'fa-spin': loading })} /></button>} - <button onClick={this.handleToggle} className='column-header__button'><i className={classNames('fa', showTrends ? 'fa-chevron-down' : 'fa-chevron-up')} /></button> - </div> - </h1> - </div> - - {showTrends && <div className='getting-started__scrollable'> - {trends.take(3).map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)} - <Link to='/trends' className='load-more'><FormattedMessage id='status.load_more' defaultMessage='Load more' /></Link> - </div>} - </div> - ); - } - -} diff --git a/app/javascript/mastodon/features/getting_started/containers/trends_container.js b/app/javascript/mastodon/features/getting_started/containers/trends_container.js deleted file mode 100644 index 65faeae86..000000000 --- a/app/javascript/mastodon/features/getting_started/containers/trends_container.js +++ /dev/null @@ -1,18 +0,0 @@ -import { connect } from 'react-redux'; -import { injectIntl } from 'react-intl'; -import { fetchTrends } from '../../../actions/trends'; -import Trends from '../components/trends'; -import { changeSetting } from '../../../actions/settings'; - -const mapStateToProps = state => ({ - trends: state.getIn(['trends', 'items']), - loading: state.getIn(['trends', 'isLoading']), - showTrends: state.getIn(['settings', 'trends', 'show']), -}); - -const mapDispatchToProps = dispatch => ({ - fetchTrends: () => dispatch(fetchTrends()), - toggleTrends: show => dispatch(changeSetting(['trends', 'show'], show)), -}); - -export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(Trends)); diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js index 67a5b282a..115dfd2b9 100644 --- a/app/javascript/mastodon/features/getting_started/index.js +++ b/app/javascript/mastodon/features/getting_started/index.js @@ -12,7 +12,6 @@ import { fetchFollowRequests } from '../../actions/accounts'; import { List as ImmutableList } from 'immutable'; import { Link } from 'react-router-dom'; import NavigationBar from '../compose/components/navigation_bar'; -import TrendsContainer from './containers/trends_container'; const messages = defineMessages({ home_timeline: { id: 'tabs_bar.home', defaultMessage: 'Home' }, @@ -132,8 +131,6 @@ export default class GettingStarted extends ImmutablePureComponent { {navItems} </div> - {multiColumn && <TrendsContainer />} - {!multiColumn && <div className='flex-spacer' />} <div className='getting-started getting-started__footer'> diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js index 9162e1326..541499668 100644 --- a/app/javascript/mastodon/features/status/components/action_bar.js +++ b/app/javascript/mastodon/features/status/components/action_bar.js @@ -8,6 +8,7 @@ import { me } from '../../../initial_state'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, + redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' }, direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' }, mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, reply: { id: 'status.reply', defaultMessage: 'Reply' }, @@ -67,6 +68,10 @@ export default class ActionBar extends React.PureComponent { this.props.onDelete(this.props.status); } + handleRedraftClick = () => { + this.props.onDelete(this.props.status, true); + } + handleDirectClick = () => { this.props.onDirect(this.props.status.get('account'), this.context.router.history); } @@ -132,6 +137,7 @@ export default class ActionBar extends React.PureComponent { menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick }); menu.push(null); menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); + menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick }); } else { menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick }); diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js index 505a88a3f..ca792043f 100644 --- a/app/javascript/mastodon/features/status/index.js +++ b/app/javascript/mastodon/features/status/index.js @@ -47,6 +47,8 @@ import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from const messages = defineMessages({ deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' }, + redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' }, + redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' }, hideAll: { id: 'status.show_less_all', defaultMessage: 'Show less for all' }, @@ -77,9 +79,12 @@ const makeMapStateToProps = () => { let id = ids.shift(); const replies = state.getIn(['contexts', 'replies', id]); + if (status.get('id') !== id) { + mutable.push(id); + } + if (replies) { - replies.forEach(reply => { - mutable.push(reply); + replies.reverse().forEach(reply => { ids.unshift(reply); }); } @@ -169,16 +174,16 @@ export default class Status extends ImmutablePureComponent { } } - handleDeleteClick = (status) => { + handleDeleteClick = (status, withRedraft = false) => { const { dispatch, intl } = this.props; if (!deleteModal) { - dispatch(deleteStatus(status.get('id'))); + dispatch(deleteStatus(status.get('id'), withRedraft)); } else { dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.deleteMessage), - confirm: intl.formatMessage(messages.deleteConfirm), - onConfirm: () => dispatch(deleteStatus(status.get('id'))), + message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), + confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), + onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)), })); } } diff --git a/app/javascript/mastodon/features/ui/components/report_modal.js b/app/javascript/mastodon/features/ui/components/report_modal.js index 8616f0315..90f001319 100644 --- a/app/javascript/mastodon/features/ui/components/report_modal.js +++ b/app/javascript/mastodon/features/ui/components/report_modal.js @@ -63,6 +63,12 @@ export default class ReportModal extends ImmutablePureComponent { this.props.dispatch(submitReport()); } + handleKeyDown = e => { + if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { + this.handleSubmit(); + } + } + componentDidMount () { this.props.dispatch(expandAccountTimeline(this.props.account.get('id'), { withReplies: true })); } @@ -98,6 +104,7 @@ export default class ReportModal extends ImmutablePureComponent { placeholder={intl.formatMessage(messages.placeholder)} value={comment} onChange={this.handleCommentChange} + onKeyDown={this.handleKeyDown} disabled={isSubmitting} /> diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js index bfed02f98..f1409b946 100644 --- a/app/javascript/mastodon/features/ui/index.js +++ b/app/javascript/mastodon/features/ui/index.js @@ -42,7 +42,6 @@ import { Mutes, PinnedStatuses, Lists, - Trends, } from './util/async-components'; import { HotKeys } from 'react-hotkeys'; import { me } from '../../initial_state'; @@ -155,7 +154,6 @@ class SwitchingColumnsArea extends React.PureComponent { <WrappedRoute path='/pinned' component={PinnedStatuses} content={children} /> <WrappedRoute path='/search' component={Compose} content={children} componentParams={{ isSearchPage: true }} /> - <WrappedRoute path='/trends' component={Trends} content={children} /> <WrappedRoute path='/statuses/new' component={Compose} content={children} /> <WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} /> diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js index dfc796a09..8cf2a6e7d 100644 --- a/app/javascript/mastodon/features/ui/util/async-components.js +++ b/app/javascript/mastodon/features/ui/util/async-components.js @@ -129,7 +129,3 @@ export function EmbedModal () { export function ListEditor () { return import(/* webpackChunkName: "features/list_editor" */'../../list_editor'); } - -export function Trends () { - return import(/* webpackChunkName: "features/trends" */'../../trends'); -} diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index c007cd26f..60d4acc39 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "متأكد من أنك تود حظر إسم النطاق {domain} بالكامل ؟ في غالب الأحيان يُستَحسَن كتم أو حظر بعض الحسابات بدلا من حظر نطاق بالكامل.", "confirmations.mute.confirm": "أكتم", "confirmations.mute.message": "هل أنت متأكد أنك تريد كتم {name} ؟", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "إلغاء المتابعة", "confirmations.unfollow.message": "متأكد من أنك تريد إلغاء متابعة {name} ؟", "embed.instructions": "يمكنكم إدماج هذه الحالة على موقعكم الإلكتروني عن طريق نسخ الشفرة أدناه.", @@ -264,6 +266,7 @@ "status.reblog": "رَقِّي", "status.reblog_private": "القيام بالترقية إلى الجمهور الأصلي", "status.reblogged_by": "{name} رقى", + "status.redraft": "Delete & re-draft", "status.reply": "ردّ", "status.replyAll": "رُد على الخيط", "status.report": "إبلِغ عن @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "سوف تفقد مسودتك إن تركت ماستدون.", "upload_area.title": "إسحب ثم أفلت للرفع", "upload_button.label": "إضافة وسائط", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 80c72ac98..ebee044b8 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", "embed.instructions": "Embed this status on your website by copying the code below.", @@ -264,6 +266,7 @@ "status.reblog": "Споделяне", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} сподели", + "status.redraft": "Delete & re-draft", "status.reply": "Отговор", "status.replyAll": "Reply to thread", "status.report": "Report @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", "upload_area.title": "Drag & drop to upload", "upload_button.label": "Добави медия", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 9598a2796..48b4d28cd 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Estàs realment, realment segur que vols blocar totalment {domain}? En la majoria dels casos blocar o silenciar uns pocs objectius és suficient i preferible.", "confirmations.mute.confirm": "Silencia", "confirmations.mute.message": "Estàs segur que vols silenciar {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Deixa de seguir", "confirmations.unfollow.message": "Estàs segur que vols deixar de seguir {name}?", "embed.instructions": "Incrusta aquest estat al lloc web copiant el codi a continuació.", @@ -264,6 +266,7 @@ "status.reblog": "Impuls", "status.reblog_private": "Impulsar a l'audiència original", "status.reblogged_by": "{name} ha retootejat", + "status.redraft": "Delete & re-draft", "status.reply": "Respondre", "status.replyAll": "Respondre al tema", "status.report": "Informar sobre @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "El vostre esborrany es perdrà si sortiu de Mastodon.", "upload_area.title": "Arrossega i deixa anar per carregar", "upload_button.label": "Afegir multimèdia", diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json index d5e2b2ede..11bb662d8 100644 --- a/app/javascript/mastodon/locales/co.json +++ b/app/javascript/mastodon/locales/co.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Site sicuru·a che vulete piattà tuttu à {domain}? Saria forse abbastanza di bluccà ò piattà alcuni conti da quallà.", "confirmations.mute.confirm": "Piattà", "confirmations.mute.message": "Site sicuru·a che vulete piattà @{name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Disabbunassi", "confirmations.unfollow.message": "Site sicuru·a ch'ùn vulete più siguità @{name}?", "embed.instructions": "Integrà stu statutu à u vostru situ cù u codice quì sottu.", @@ -264,6 +266,7 @@ "status.reblog": "Sparte", "status.reblog_private": "Sparte à l'audienza uriginale", "status.reblogged_by": "{name} hà spartutu", + "status.redraft": "Delete & re-draft", "status.reply": "Risponde", "status.replyAll": "Risponde à tutti", "status.report": "Palisà @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "A bruttacopia sarà persa s'ellu hè chjosu Mastodon.", "upload_area.title": "Drag & drop per caricà un fugliale", "upload_button.label": "Aghjunghje un media", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index e770c74eb..7ccf38059 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Bist du dir wirklich sicher, dass du die ganze Domain {domain} verbergen willst? In den meisten Fällen reichen ein paar gezielte Blocks aus.", "confirmations.mute.confirm": "Stummschalten", "confirmations.mute.message": "Bist du dir sicher, dass du {name} stummschalten möchtest?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Entfolgen", "confirmations.unfollow.message": "Bist du dir sicher, dass du {name} entfolgen möchtest?", "embed.instructions": "Du kannst diesen Beitrag auf deiner Webseite einbetten, indem du den folgenden Code einfügst.", @@ -264,6 +266,7 @@ "status.reblog": "Teilen", "status.reblog_private": "An das eigentliche Publikum teilen", "status.reblogged_by": "{name} teilte", + "status.redraft": "Delete & re-draft", "status.reply": "Antworten", "status.replyAll": "Auf Thread antworten", "status.report": "@{name} melden", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Dein Entwurf geht verloren, wenn du Mastodon verlässt.", "upload_area.title": "Zum Hochladen hereinziehen", "upload_button.label": "Mediendatei hinzufügen", diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index e3b749e86..464592121 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -220,6 +220,10 @@ "id": "status.delete" }, { + "defaultMessage": "Delete & re-draft", + "id": "status.redraft" + }, + { "defaultMessage": "Direct message @{name}", "id": "status.direct" }, @@ -378,6 +382,14 @@ "id": "confirmations.delete.message" }, { + "defaultMessage": "Delete & redraft", + "id": "confirmations.redraft.confirm" + }, + { + "defaultMessage": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", + "id": "confirmations.redraft.message" + }, + { "defaultMessage": "Block", "id": "confirmations.block.confirm" }, @@ -805,10 +817,6 @@ { "descriptors": [ { - "defaultMessage": "Trending now", - "id": "trends.header" - }, - { "defaultMessage": "People", "id": "search_results.accounts" }, @@ -1039,23 +1047,6 @@ { "descriptors": [ { - "defaultMessage": "Refresh", - "id": "trends.refresh" - }, - { - "defaultMessage": "Trending now", - "id": "trends.header" - }, - { - "defaultMessage": "Load more", - "id": "status.load_more" - } - ], - "path": "app/javascript/mastodon/features/getting_started/components/trends.json" - }, - { - "descriptors": [ - { "defaultMessage": "Home", "id": "tabs_bar.home" }, @@ -1508,6 +1499,10 @@ "id": "status.delete" }, { + "defaultMessage": "Delete & re-draft", + "id": "status.redraft" + }, + { "defaultMessage": "Direct message @{name}", "id": "status.direct" }, @@ -1589,6 +1584,14 @@ "id": "confirmations.delete.message" }, { + "defaultMessage": "Delete & redraft", + "id": "confirmations.redraft.confirm" + }, + { + "defaultMessage": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", + "id": "confirmations.redraft.message" + }, + { "defaultMessage": "Block", "id": "confirmations.block.confirm" }, @@ -1610,19 +1613,6 @@ { "descriptors": [ { - "defaultMessage": "Trending now", - "id": "trends.header" - }, - { - "defaultMessage": "Refresh trends", - "id": "trends.refresh" - } - ], - "path": "app/javascript/mastodon/features/trends/index.json" - }, - { - "descriptors": [ - { "defaultMessage": "Boost", "id": "status.reblog" }, diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 9efc0e1bd..64efbd31a 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Σίγουρα θες να μπλοκάρεις ολόκληρο το {domain}; Συνήθως μερικά εστιασμένα μπλοκ ή αποσιωπήσεις επαρκούν και προτιμούνται.", "confirmations.mute.confirm": "Αποσιώπηση", "confirmations.mute.message": "Σίγουρα θες να αποσιωπήσεις τον/την {name};", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Διακοπή παρακολούθησης", "confirmations.unfollow.message": "Σίγουρα θες να πάψεις να ακολουθείς τον/την {name};", "embed.instructions": "Ενσωματώστε αυτή την κατάσταση στην ιστοσελίδα σας αντιγράφοντας τον παρακάτω κώδικα.", @@ -264,6 +266,7 @@ "status.reblog": "Boost", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} boosted", + "status.redraft": "Delete & re-draft", "status.reply": "Reply", "status.replyAll": "Reply to thread", "status.report": "Καταγγελία @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", "upload_area.title": "Drag & drop to upload", "upload_button.label": "Add media", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index b5ce82050..ae3b96c6d 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -87,6 +87,8 @@ "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", "embed.instructions": "Embed this status on your website by copying the code below.", @@ -269,6 +271,7 @@ "status.reblog": "Boost", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} boosted", + "status.redraft": "Delete & re-draft", "status.reply": "Reply", "status.replyAll": "Reply to thread", "status.report": "Report @{name}", @@ -289,8 +292,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", "upload_area.title": "Drag & drop to upload", "upload_button.label": "Add media", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 8740c396e..b01237a2e 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Ĉu vi vere, vere certas, ke vi volas tute bloki {domain}? Plej ofte, trafa blokado kaj silentigado sufiĉas kaj preferindas.", "confirmations.mute.confirm": "Silentigi", "confirmations.mute.message": "Ĉu vi certas, ke vi volas silentigi {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Ne plu sekvi", "confirmations.unfollow.message": "Ĉu vi certas, ke vi volas ĉesi sekvi {name}?", "embed.instructions": "Enkorpigu ĉi tiun mesaĝon en vian retejon per kopio de la suba kodo.", @@ -264,6 +266,7 @@ "status.reblog": "Diskonigi", "status.reblog_private": "Diskonigi al la originala atentaro", "status.reblogged_by": "{name} diskonigis", + "status.redraft": "Delete & re-draft", "status.reply": "Respondi", "status.replyAll": "Respondi al la fadeno", "status.report": "Signali @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Aŭdovidaĵoj", "timeline.posts": "Mesaĝoj", "trends.count_by_accounts": "{count} {rawCount, pluraj, unu {person} alia(j) {people}} parolas", - "trends.header": "Nun furoras", - "trends.refresh": "Aktualigi", "ui.beforeunload": "Via malneto perdiĝos se vi eliras de Mastodon.", "upload_area.title": "Altreni kaj lasi por alŝuti", "upload_button.label": "Aldoni aŭdovidaĵon", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 4386786cb..ba85841f6 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "¿Seguro de que quieres bloquear al dominio entero? En algunos casos es preferible bloquear o silenciar objetivos determinados.", "confirmations.mute.confirm": "Silenciar", "confirmations.mute.message": "¿Estás seguro de que quieres silenciar a {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Dejar de seguir", "confirmations.unfollow.message": "¿Estás seguro de que quieres dejar de seguir a {name}?", "embed.instructions": "Añade este toot a tu sitio web con el siguiente código.", @@ -264,6 +266,7 @@ "status.reblog": "Retootear", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "Retooteado por {name}", + "status.redraft": "Delete & re-draft", "status.reply": "Responder", "status.replyAll": "Responder al hilo", "status.report": "Reportar", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Tu borrador se perderá si sales de Mastodon.", "upload_area.title": "Arrastra y suelta para subir", "upload_button.label": "Subir multimedia", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index 508e4d988..49be810e2 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -13,14 +13,14 @@ "account.follows_you": "Jarraitzen dizu", "account.hide_reblogs": "Ezkutatu @{name}(r)en bultzadak", "account.media": "Media", - "account.mention": "@{name} aipatu", + "account.mention": "Aipatu @{name}", "account.moved_to": "{name} hona lekualdatu da:", "account.mute": "Mututu @{name}", "account.mute_notifications": "Mututu @{name}(r)en jakinarazpenak", "account.muted": "Mutututa", "account.posts": "Toot-ak", "account.posts_with_replies": "Toot eta erantzunak", - "account.report": "@{name} salatu", + "account.report": "Salatu @{name}", "account.requested": "Onarpenaren zain. Klikatu jarraitzeko eskaera ezeztatzeko", "account.share": "@{name}(e)ren profila elkarbanatu", "account.show_reblogs": "Erakutsi @{name}(r)en bultzadak", @@ -67,8 +67,8 @@ "compose_form.placeholder": "Zer duzu buruan?", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.marked": "Multimedia mingarri gisa markatu da", - "compose_form.sensitive.unmarked": "Multimedia ez da mingarri gisa markatu", + "compose_form.sensitive.marked": "Multimedia edukia hunkigarri gisa markatu da", + "compose_form.sensitive.unmarked": "Multimedia edukia ez da hunkigarri gisa markatu", "compose_form.spoiler.marked": "Testua abisu batek ezkutatzen du", "compose_form.spoiler.unmarked": "Testua ez dago ezkutatuta", "compose_form.spoiler_placeholder": "Idatzi zure abisua hemen", @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Ziur, erabat ziur, {domain} domeinu osoa blokeatu nahi duzula? Gehienetan gutxi batzuk blokeatu edo mututzearekin nahikoa da.", "confirmations.mute.confirm": "Mututu", "confirmations.mute.message": "Ziur {name} mututu nahi duzula?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Utzi jarraitzeari", "confirmations.unfollow.message": "Ziur {name} jarraitzeari utzi nahi diozula?", "embed.instructions": "Txertatu mezu hau zure webgunean beheko kodea kopatuz.", @@ -264,11 +266,12 @@ "status.reblog": "Bultzada", "status.reblog_private": "Bultzada jatorrizko hartzaileei", "status.reblogged_by": "{name}(r)en bultzada", + "status.redraft": "Delete & re-draft", "status.reply": "Erantzun", "status.replyAll": "Erantzun harian", "status.report": "Salatu @{name}", "status.sensitive_toggle": "Egin klik ikusteko", - "status.sensitive_warning": "Eduki mingarria", + "status.sensitive_warning": "Eduki hunkigarria", "status.share": "Partekatu", "status.show_less": "Erakutsi gutxiago", "status.show_less_all": "Erakutsi denetarik gutxiago", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toot-ak", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} hitz egiten", - "trends.header": "Joera orain", - "trends.refresh": "Freskatu", "ui.beforeunload": "Zure zirriborroa galduko da Mastodon uzten baduzu.", "upload_area.title": "Arrastatu eta jaregin igotzeko", "upload_button.label": "Gehitu multimedia", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index 82f3af3cd..bf7a256d6 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "آیا جدی جدی میخواهید کل دامین {domain} را مسدود کنید؟ بیشتر وقتها مسدودکردن یا بیصداکردن چند حساب کاربری خاص کافی است و توصیه میشود.", "confirmations.mute.confirm": "بیصدا کن", "confirmations.mute.message": "آیا واقعاً میخواهید {name} را بیصدا کنید؟", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "لغو پیگیری", "confirmations.unfollow.message": "آیا واقعاً میخواهید به پیگیری از {name} پایان دهید؟", "embed.instructions": "برای جاگذاری این نوشته در سایت خودتان، کد زیر را کپی کنید.", @@ -264,6 +266,7 @@ "status.reblog": "بازبوقیدن", "status.reblog_private": "بازبوق به مخاطبان اولیه", "status.reblogged_by": "{name} بازبوقید", + "status.redraft": "Delete & re-draft", "status.reply": "پاسخ", "status.replyAll": "به نوشته پاسخ دهید", "status.report": "گزارش دادن @{name}", @@ -284,8 +287,6 @@ "timeline.media": "عکس و ویدیو", "timeline.posts": "بوقها", "trends.count_by_accounts": "{count} {rawCount, plural, one {نفر نوشته است} other {نفر نوشتهاند}}", - "trends.header": "موضوعات داغ", - "trends.refresh": "بهروزرسانی", "ui.beforeunload": "اگر از ماستدون خارج شوید پیشنویس شما پاک خواهد شد.", "upload_area.title": "برای بارگذاری به اینجا بکشید", "upload_button.label": "افزودن تصویر", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index fa8565431..4cdee49ee 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Haluatko aivan varmasti estää koko verkko-osoitteen {domain}? Useimmiten jokunen kohdistettu esto ja mykistys riittää, ja se on suositeltavampi tapa toimia.", "confirmations.mute.confirm": "Mykistä", "confirmations.mute.message": "Haluatko varmasti mykistää käyttäjän {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Lakkaa seuraamasta", "confirmations.unfollow.message": "Haluatko varmasti lakata seuraamasta käyttäjää {name}?", "embed.instructions": "Upota statuspäivitys sivullesi kopioimalla alla oleva koodi.", @@ -264,6 +266,7 @@ "status.reblog": "Buustaa", "status.reblog_private": "Buustaa alkuperäiselle yleisölle", "status.reblogged_by": "{name} buustasi", + "status.redraft": "Delete & re-draft", "status.reply": "Vastaa", "status.replyAll": "Vastaa ketjuun", "status.report": "Raportoi @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Luonnos häviää, jos poistut Mastodonista.", "upload_area.title": "Lataa raahaamalla ja pudottamalla tähän", "upload_button.label": "Lisää mediaa", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index 0190c7562..35c753091 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Êtes-vous vraiment, vraiment sûr⋅e de vouloir bloquer {domain} en entier ? Dans la plupart des cas, quelques blocages ou masquages ciblés sont suffisants et préférables.", "confirmations.mute.confirm": "Masquer", "confirmations.mute.message": "Confirmez-vous le masquage de {name} ?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Ne plus suivre", "confirmations.unfollow.message": "Voulez-vous arrêter de suivre {name} ?", "embed.instructions": "Intégrez ce statut à votre site en copiant le code ci-dessous.", @@ -264,6 +266,7 @@ "status.reblog": "Partager", "status.reblog_private": "Booster vers l'audience originale", "status.reblogged_by": "{name} a partagé :", + "status.redraft": "Delete & re-draft", "status.reply": "Répondre", "status.replyAll": "Répondre au fil", "status.report": "Signaler @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Pouets", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Votre brouillon sera perdu si vous quittez Mastodon.", "upload_area.title": "Glissez et déposez pour envoyer", "upload_button.label": "Joindre un média", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 7af9a0426..5aab4d648 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Realmente está segura de que quere bloquear por completo o dominio {domain}? Normalmente é suficiente, e preferible, bloquear de xeito selectivo varios elementos.", "confirmations.mute.confirm": "Acalar", "confirmations.mute.message": "Está segura de que quere acalar a {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Deixar de seguir", "confirmations.unfollow.message": "Quere deixar de seguir a {name}?", "embed.instructions": "Copie o código inferior para incrustar no seu sitio web este estado.", @@ -264,6 +266,7 @@ "status.reblog": "Promover", "status.reblog_private": "Promover a audiencia orixinal", "status.reblogged_by": "{name} promoveu", + "status.redraft": "Delete & re-draft", "status.reply": "Resposta", "status.replyAll": "Resposta a conversa", "status.report": "Informar @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "O borrador perderase se sae de Mastodon.", "upload_area.title": "Arrastre e solte para subir", "upload_button.label": "Engadir medios", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 343edec42..188d69553 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "באמת באמת לחסום את כל קהילת {domain}? ברב המקרים השתקות נבחרות של מספר משתמשים מסויימים צריכה להספיק.", "confirmations.mute.confirm": "להשתיק", "confirmations.mute.message": "להשתיק את {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "להפסיק מעקב", "confirmations.unfollow.message": "להפסיק מעקב אחרי {name}?", "embed.instructions": "ניתן להטמיע את ההודעה באתרך ע\"י העתקת הקוד שלהלן.", @@ -264,6 +266,7 @@ "status.reblog": "הדהוד", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "הודהד על ידי {name}", + "status.redraft": "Delete & re-draft", "status.reply": "תגובה", "status.replyAll": "תגובה לכולם", "status.report": "דיווח על @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "הטיוטא תאבד אם תעזבו את מסטודון.", "upload_area.title": "ניתן להעלות על ידי Drag & drop", "upload_button.label": "הוספת מדיה", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index d350cb6e1..fc787366d 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Jesi li zaista, zaista siguran da želiš potpuno blokirati {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Utišaj", "confirmations.mute.message": "Jesi li siguran da želiš utišati {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", "embed.instructions": "Embed this status on your website by copying the code below.", @@ -264,6 +266,7 @@ "status.reblog": "Podigni", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} je podigao", + "status.redraft": "Delete & re-draft", "status.reply": "Odgovori", "status.replyAll": "Odgovori na temu", "status.report": "Prijavi @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", "upload_area.title": "Povuci i spusti kako bi uploadao", "upload_button.label": "Dodaj media", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index 7164951bf..7c850b005 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Nagyon biztos abban, hogy le szeretné tiltani az egész {domain}-t? A legtöbb esetben néhány célszerű tiltás vagy némítás elegendő és kívánatosabb megoldás.", "confirmations.mute.confirm": "Némít", "confirmations.mute.message": "Biztos benne, hogy némítani szeretné {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Követés visszavonása", "confirmations.unfollow.message": "Biztos benne, hogy vissza szeretné vonni {name} követését?", "embed.instructions": "Ágyazza be ezen státuszt weboldalába az alábbi kód másolásával.", @@ -264,6 +266,7 @@ "status.reblog": "Reblog", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} reblogolta", + "status.redraft": "Delete & re-draft", "status.reply": "Válasz", "status.replyAll": "Válaszolj a beszélgetésre", "status.report": "Report @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "A piszkozata el fog vesztődni ha elhagyja Mastodon-t.", "upload_area.title": "Húzza ide a feltöltéshez", "upload_button.label": "Média hozzáadása", diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json index 9f3885076..bb167998e 100644 --- a/app/javascript/mastodon/locales/hy.json +++ b/app/javascript/mastodon/locales/hy.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Հաստատ֊հաստա՞տ վստահ ես, որ ուզում ես արգելափակել ամբողջ {domain} տիրույթը։ Սովորաբար մի երկու թիրախավորված արգելափակում կամ լռեցում բավական է ու նախընտրելի։", "confirmations.mute.confirm": "Լռեցնել", "confirmations.mute.message": "Վստա՞հ ես, որ ուզում ես {name}֊ին լռեցնել։", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Ապահետեւել", "confirmations.unfollow.message": "Վստա՞հ ես, որ ուզում ես այլեւս չհետեւել {name}֊ին։", "embed.instructions": "Այս թութը քո կայքում ներդնելու համար կարող ես պատճենել ներքոհիշյալ կոդը։", @@ -264,6 +266,7 @@ "status.reblog": "Տարածել", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} տարածել է", + "status.redraft": "Delete & re-draft", "status.reply": "Պատասխանել", "status.replyAll": "Պատասխանել թելին", "status.report": "Բողոքել @{name}֊ից", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Քո սեւագիրը կկորի, եթե լքես Մաստոդոնը։", "upload_area.title": "Քաշիր ու նետիր՝ վերբեռնելու համար", "upload_button.label": "Ավելացնել մեդիա", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 9683e69a7..0dee97656 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Apakah anda benar benar yakin untuk memblokir keseluruhan {domain}? Dalam kasus tertentu beberapa pemblokiran atau penyembunyian lebih baik.", "confirmations.mute.confirm": "Bisukan", "confirmations.mute.message": "Apa anda yakin ingin membisukan {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Berhenti mengikuti", "confirmations.unfollow.message": "Apakah anda ingin berhenti mengikuti {name}?", "embed.instructions": "Sematkan status ini di website anda dengan menyalin kode di bawah ini.", @@ -264,6 +266,7 @@ "status.reblog": "Boost", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "di-boost {name}", + "status.redraft": "Delete & re-draft", "status.reply": "Balas", "status.replyAll": "Balas ke semua", "status.report": "Laporkan @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Naskah anda akan hilang jika anda keluar dari Mastodon.", "upload_area.title": "Seret & lepaskan untuk mengunggah", "upload_button.label": "Tambahkan media", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index d63225783..abb81981e 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", "embed.instructions": "Embed this status on your website by copying the code below.", @@ -264,6 +266,7 @@ "status.reblog": "Repetar", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} repetita", + "status.redraft": "Delete & re-draft", "status.reply": "Respondar", "status.replyAll": "Respondar a filo", "status.report": "Denuncar @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", "upload_area.title": "Tranar faligar por kargar", "upload_button.label": "Adjuntar kontenajo", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 87ff78469..f0d58621d 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Sei davvero sicuro che vuoi bloccare l'intero {domain}? Nella maggior parte dei casi, pochi blocchi o silenziamenti mirati sono sufficienti e preferibili.", "confirmations.mute.confirm": "Silenzia", "confirmations.mute.message": "Sei sicuro di voler silenziare {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Smetti di seguire", "confirmations.unfollow.message": "Sei sicuro che non vuoi più seguire {name}?", "embed.instructions": "Inserisci questo status nel tuo sito copiando il codice qui sotto.", @@ -264,6 +266,7 @@ "status.reblog": "Condividi", "status.reblog_private": "Condividi con i destinatari iniziali", "status.reblogged_by": "{name} ha condiviso", + "status.redraft": "Delete & re-draft", "status.reply": "Rispondi", "status.replyAll": "Rispondi alla conversazione", "status.report": "Segnala @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "La bozza andrà persa se esci da Mastodon.", "upload_area.title": "Trascina per caricare", "upload_button.label": "Aggiungi file multimediale", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index fc1a314e8..9bb3fca25 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -87,6 +87,8 @@ "confirmations.domain_block.message": "本当に{domain}全体を非表示にしますか? 多くの場合は個別にブロックやミュートするだけで充分であり、また好ましいです。", "confirmations.mute.confirm": "ミュート", "confirmations.mute.message": "本当に{name}さんをミュートしますか?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "フォロー解除", "confirmations.unfollow.message": "本当に{name}さんのフォローを解除しますか?", "embed.instructions": "下記のコードをコピーしてウェブサイトに埋め込みます。", @@ -269,6 +271,7 @@ "status.reblog": "ブースト", "status.reblog_private": "ブースト", "status.reblogged_by": "{name}さんがブースト", + "status.redraft": "Delete & re-draft", "status.reply": "返信", "status.replyAll": "全員に返信", "status.report": "@{name}さんを通報", @@ -289,8 +292,6 @@ "timeline.media": "メディア", "timeline.posts": "投稿", "trends.count_by_accounts": "{count} {rawCount, plural, one {人} other {人}} がトゥート", - "trends.header": "トレンドタグ", - "trends.refresh": "更新", "ui.beforeunload": "Mastodonから離れると送信前の投稿は失われます。", "upload_area.title": "ドラッグ&ドロップでアップロード", "upload_button.label": "メディアを追加", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 65c6319b4..fef953c66 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "정말로 {domain} 전체를 숨기시겠습니까? 대부분의 경우 개별 차단이나 뮤트로 충분합니다.", "confirmations.mute.confirm": "뮤트", "confirmations.mute.message": "정말로 {name}를 뮤트하시겠습니까?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "언팔로우", "confirmations.unfollow.message": "정말로 {name}를 언팔로우하시겠습니까?", "embed.instructions": "아래의 코드를 복사하여 대화를 원하는 곳으로 공유하세요.", @@ -264,6 +266,7 @@ "status.reblog": "부스트", "status.reblog_private": "원래의 수신자들에게 부스트", "status.reblogged_by": "{name}님이 부스트 했습니다", + "status.redraft": "Delete & re-draft", "status.reply": "답장", "status.replyAll": "전원에게 답장", "status.report": "신고", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "지금 나가면 저장되지 않은 항목을 잃게 됩니다.", "upload_area.title": "드래그 & 드롭으로 업로드", "upload_button.label": "미디어 추가", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index 664cebac0..d744a8723 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Weet je het echt heel erg zeker dat je alles van {domain} wil negeren? In de meeste gevallen is het blokkeren of negeren van een paar specifieke personen voldoende en gepaster.", "confirmations.mute.confirm": "Negeren", "confirmations.mute.message": "Weet je het zeker dat je {name} wilt negeren?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Ontvolgen", "confirmations.unfollow.message": "Weet je het zeker dat je {name} wilt ontvolgen?", "embed.instructions": "Embed deze toot op jouw website, door de onderstaande code te kopiëren.", @@ -264,6 +266,7 @@ "status.reblog": "Boost", "status.reblog_private": "Boost naar oorspronkelijke ontvangers", "status.reblogged_by": "{name} boostte", + "status.redraft": "Delete & re-draft", "status.reply": "Reageren", "status.replyAll": "Reageer op iedereen", "status.report": "Rapporteer @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {persoon praat} other {mensen praten}} hierover", - "trends.header": "Trends", - "trends.refresh": "Vernieuwen", "ui.beforeunload": "Je concept zal verloren gaan als je Mastodon verlaat.", "upload_area.title": "Hierin slepen om te uploaden", "upload_button.label": "Media toevoegen", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 8aaf4de42..d971bfcdc 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Er du sikker på at du vil skjule hele domenet {domain}? I de fleste tilfeller er det bedre med målrettet blokkering eller demping.", "confirmations.mute.confirm": "Demp", "confirmations.mute.message": "Er du sikker på at du vil dempe {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Slutt å følge", "confirmations.unfollow.message": "Er du sikker på at du vil slutte å følge {name}?", "embed.instructions": "Kopier koden under for å bygge inn denne statusen på hjemmesiden din.", @@ -264,6 +266,7 @@ "status.reblog": "Fremhev", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "Fremhevd av {name}", + "status.redraft": "Delete & re-draft", "status.reply": "Svar", "status.replyAll": "Svar til samtale", "status.report": "Rapporter @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Din kladd vil bli forkastet om du forlater Mastodon.", "upload_area.title": "Dra og slipp for å laste opp", "upload_button.label": "Legg til media", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 4056ec2db..cfbd3a83c 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Volètz vertadièrament blocar complètament {domain} ? De còps cal pas que blocar o rescondre unas personas solament.", "confirmations.mute.confirm": "Rescondre", "confirmations.mute.message": "Sètz segur de voler rescondre {name} ?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Quitar de sègre", "confirmations.unfollow.message": "Volètz vertadièrament quitar de sègre {name} ?", "embed.instructions": "Embarcar aqueste estatut per lo far veire sus un site Internet en copiar lo còdi çai-jos.", @@ -264,6 +266,7 @@ "status.reblog": "Partejar", "status.reblog_private": "Partejar a l’audiéncia d’origina", "status.reblogged_by": "{name} a partejat", + "status.redraft": "Delete & re-draft", "status.reply": "Respondre", "status.replyAll": "Respondre a la conversacion", "status.report": "Senhalar @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Tuts", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} ne charra other {people}} ne charran", - "trends.header": "Tendéncia actuala", - "trends.refresh": "Actualizar", "ui.beforeunload": "Vòstre brolhon serà perdut se quitatz Mastodon.", "upload_area.title": "Lisatz e depausatz per mandar", "upload_button.label": "Ajustar un mèdia", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index b62d5b065..759d7c9e8 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -87,6 +87,8 @@ "confirmations.domain_block.message": "Czy na pewno chcesz zablokować całą domenę {domain}? Zwykle lepszym rozwiązaniem jest blokada lub wyciszenie kilku użytkowników.", "confirmations.mute.confirm": "Wycisz", "confirmations.mute.message": "Czy na pewno chcesz wyciszyć {name}?", + "confirmations.redraft.confirm": "Usuń i przeredaguj", + "confirmations.redraft.message": "Czy na pewno chcesz usunąć i przeredagować ten wpis? Utracisz wszystkie odpowiedzi, podbicia i polubienia dotyczące go.", "confirmations.unfollow.confirm": "Przestań śledzić", "confirmations.unfollow.message": "Czy na pewno zamierzasz przestać śledzić {name}?", "embed.instructions": "Osadź ten wpis na swojej stronie wklejając poniższy kod.", @@ -269,6 +271,7 @@ "status.reblog": "Podbij", "status.reblog_private": "Podbij dla odbiorców oryginalnego wpisu", "status.reblogged_by": "{name} podbił", + "status.redraft": "Usuń i przeredaguj", "status.reply": "Odpowiedz", "status.replyAll": "Odpowiedz na wątek", "status.report": "Zgłoś @{name}", @@ -289,8 +292,6 @@ "timeline.media": "Zawartość multimedialna", "timeline.posts": "Wpisy", "trends.count_by_accounts": "{count} {rawCount, plural, one {osoba rozmawia} few {osoby rozmawiają} other {osób rozmawia}} o tym", - "trends.header": "Na czasie", - "trends.refresh": "Odśwież", "ui.beforeunload": "Utracisz tworzony wpis, jeżeli opuścisz Mastodona.", "upload_area.title": "Przeciągnij i upuść aby wysłać", "upload_button.label": "Dodaj zawartość multimedialną", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index fc07266a8..fcb2a5686 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Você quer mesmo bloquear {domain} inteiro? Na maioria dos casos, silenciar ou bloquear alguns usuários é o suficiente e o recomendado.", "confirmations.mute.confirm": "Silenciar", "confirmations.mute.message": "Você tem certeza de que quer silenciar {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Deixar de seguir", "confirmations.unfollow.message": "Você tem certeza de que quer deixar de seguir {name}?", "embed.instructions": "Incorpore esta postagem em seu site copiando o código abaixo.", @@ -264,6 +266,7 @@ "status.reblog": "Compartilhar", "status.reblog_private": "Compartilhar com a audiência original", "status.reblogged_by": "{name} compartilhou", + "status.redraft": "Delete & re-draft", "status.reply": "Responder", "status.replyAll": "Responder à sequência", "status.report": "Denunciar @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {pessoa} other {pessoas}} falando sobre", - "trends.header": "Hashtags do momento", - "trends.refresh": "Atualizar", "ui.beforeunload": "Seu rascunho será perdido se você sair do Mastodon.", "upload_area.title": "Arraste e solte para enviar", "upload_button.label": "Adicionar mídia", diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json index b1e760954..d51a47955 100644 --- a/app/javascript/mastodon/locales/pt.json +++ b/app/javascript/mastodon/locales/pt.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "De certeza que queres bloquear por completo o domínio {domain}? Na maioria dos casos, silenciar ou bloquear alguns utilizadores é o suficiente e o recomendado.", "confirmations.mute.confirm": "Silenciar", "confirmations.mute.message": "De certeza que queres silenciar {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Deixar de seguir", "confirmations.unfollow.message": "De certeza que queres deixar de seguir {name}?", "embed.instructions": "Publicar este post num outro site copiando o código abaixo.", @@ -264,6 +266,7 @@ "status.reblog": "Partilhar", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} partilhou", + "status.redraft": "Delete & re-draft", "status.reply": "Responder", "status.replyAll": "Responder à conversa", "status.report": "Denunciar @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "O teu rascunho vai ser perdido se abandonares o Mastodon.", "upload_area.title": "Arraste e solte para enviar", "upload_button.label": "Adicionar media", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 48bcbf0fb..0ef7a32bb 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Вы на самом деле уверены, что хотите блокировать весь {domain}? В большинстве случаев нескольких отдельных блокировок или глушений достаточно.", "confirmations.mute.confirm": "Заглушить", "confirmations.mute.message": "Вы уверены, что хотите заглушить {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Отписаться", "confirmations.unfollow.message": "Вы уверены, что хотите отписаться от {name}?", "embed.instructions": "Встройте этот статус на Вашем сайте, скопировав код внизу.", @@ -264,6 +266,7 @@ "status.reblog": "Продвинуть", "status.reblog_private": "Продвинуть для своей аудитории", "status.reblogged_by": "{name} продвинул(а)", + "status.redraft": "Delete & re-draft", "status.reply": "Ответить", "status.replyAll": "Ответить на тред", "status.report": "Пожаловаться", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Ваш черновик будет утерян, если вы покинете Mastodon.", "upload_area.title": "Перетащите сюда, чтобы загрузить", "upload_button.label": "Добавить медиаконтент", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index 416816c60..983018dd8 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Ste si naozaj istý, že chcete blokovať celú {domain}? Vo väčšine prípadov stačí blokovať alebo ignorovať daných používateľov, čiže to sa doporučuje.", "confirmations.mute.confirm": "Ignoruj", "confirmations.mute.message": "Naozaj chcete ignorovať {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Nesledovať", "confirmations.unfollow.message": "Naozaj chcete prestať sledovať {name}?", "embed.instructions": "Umiestni kód uvedený nižšie pre pridanie tohto statusu na tvoju web stránku.", @@ -264,6 +266,7 @@ "status.reblog": "Povýšiť", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} povýšil/a", + "status.redraft": "Delete & re-draft", "status.reply": "Odpovedať", "status.replyAll": "Odpovedať na diskusiu", "status.report": "Nahlásiť @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Príspevky", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Čo máte rozpísané sa stratí, ak opustíte Mastodon.", "upload_area.title": "Ťahaj a pusti pre nahratie", "upload_button.label": "Pridať médiá", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index 3caa26f50..2d89b63eb 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Ali ste res, res prepričani, da želite blokirati celotno {domain}? V večini primerov je nekaj ciljnih blokiranj ali utišanj dovolj in boljše.", "confirmations.mute.confirm": "Utišanje", "confirmations.mute.message": "Ali ste prepričani, da želite utišati {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Prenehaj slediti", "confirmations.unfollow.message": "Ali ste prepričani, da ne želite več slediti {name}?", "embed.instructions": "Vstavi ta status na svojo spletno stran tako, da kopirate spodnjo kodo.", @@ -264,6 +266,7 @@ "status.reblog": "Suni", "status.reblog_private": "Suni v prvotno občinstvo", "status.reblogged_by": "{name} sunjen", + "status.redraft": "Delete & re-draft", "status.reply": "Odgovori", "status.replyAll": "Odgovori na objavo", "status.report": "Prijavi @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Vaš osnutek bo izgubljen, če zapustite Mastodona.", "upload_area.title": "Povlecite in spustite za pošiljanje", "upload_button.label": "Dodaj medij", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index 45971e9d4..c17495979 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Da li ste stvarno, stvarno sigurno da želite da blokirate ceo domen {domain}? U većini slučajeva, par dobrih blokiranja ili ućutkavanja su dovoljna i preporučljiva.", "confirmations.mute.confirm": "Ućutkaj", "confirmations.mute.message": "Da li stvarno želite da ućutkate korisnika {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Otprati", "confirmations.unfollow.message": "Da li ste sigurni da želite da otpratite korisnika {name}?", "embed.instructions": "Ugradi ovaj status na Vaš veb sajt kopiranjem koda ispod.", @@ -264,6 +266,7 @@ "status.reblog": "Podrži", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} podržao(la)", + "status.redraft": "Delete & re-draft", "status.reply": "Odgovori", "status.replyAll": "Odgovori na diskusiju", "status.report": "Prijavi korisnika @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Ako napustite Mastodont, izgubićete napisani nacrt.", "upload_area.title": "Prevucite ovde da otpremite", "upload_button.label": "Dodaj multimediju", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index a9e7aca82..f11e3935c 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Да ли сте стварно, стварно сигурно да желите да блокирате цео домен {domain}? У већини случајева, пар добрих блокирања или ућуткавања су довољна и препоручљива.", "confirmations.mute.confirm": "Ућуткај", "confirmations.mute.message": "Да ли стварно желите да ућуткате корисника {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Отпрати", "confirmations.unfollow.message": "Да ли сте сигурни да желите да отпратите корисника {name}?", "embed.instructions": "Угради овај статус на Ваш веб сајт копирањем кода испод.", @@ -264,6 +266,7 @@ "status.reblog": "Подржи", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} подржао(ла)", + "status.redraft": "Delete & re-draft", "status.reply": "Одговори", "status.replyAll": "Одговори на дискусију", "status.report": "Пријави корисника @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Ако напустите Мастодонт, изгубићете написани нацрт.", "upload_area.title": "Превуците овде да отпремите", "upload_button.label": "Додај мултимедију", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index 11bd92a87..fd0cc3268 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Är du verkligen, verkligen säker på att du vill blockera hela {domain}? I de flesta fall är några riktade blockeringar eller nedtystade tillräckligt och föredras.", "confirmations.mute.confirm": "Tysta", "confirmations.mute.message": "Är du säker du vill tysta ner {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Sluta följa", "confirmations.unfollow.message": "Är du säker på att du vill sluta följa {name}?", "embed.instructions": "Bädda in den här statusen på din webbplats genom att kopiera koden nedan.", @@ -264,6 +266,7 @@ "status.reblog": "Knuff", "status.reblog_private": "Knuffa till de ursprungliga åhörarna", "status.reblogged_by": "{name} knuffade", + "status.redraft": "Delete & re-draft", "status.reply": "Svara", "status.replyAll": "Svara på tråden", "status.report": "Rapportera @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Ditt utkast kommer att förloras om du lämnar Mastodon.", "upload_area.title": "Dra & släpp för att ladda upp", "upload_button.label": "Lägg till media", diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json index b82ce1f6c..22b164936 100644 --- a/app/javascript/mastodon/locales/te.json +++ b/app/javascript/mastodon/locales/te.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", "embed.instructions": "Embed this status on your website by copying the code below.", @@ -264,6 +266,7 @@ "status.reblog": "Boost", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} boosted", + "status.redraft": "Delete & re-draft", "status.reply": "Reply", "status.replyAll": "Reply to thread", "status.report": "Report @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", "upload_area.title": "Drag & drop to upload", "upload_button.label": "Add media", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 229189b56..57fe1b5d9 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", "embed.instructions": "Embed this status on your website by copying the code below.", @@ -264,6 +266,7 @@ "status.reblog": "Boost", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} boosted", + "status.redraft": "Delete & re-draft", "status.reply": "Reply", "status.replyAll": "Reply to thread", "status.report": "Report @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", "upload_area.title": "Drag & drop to upload", "upload_button.label": "Add media", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index 30409a803..9c5e89463 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Sessize al", "confirmations.mute.message": "{name} kullanıcısını sessize almak istiyor musunuz?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", "embed.instructions": "Embed this status on your website by copying the code below.", @@ -264,6 +266,7 @@ "status.reblog": "Boost'la", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} boost etti", + "status.redraft": "Delete & re-draft", "status.reply": "Cevapla", "status.replyAll": "Konuşmayı cevapla", "status.report": "@{name}'i raporla", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", "upload_area.title": "Upload için sürükle bırak yapınız", "upload_button.label": "Görsel ekle", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 5c6394b61..0f76a0045 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "Ви точно, точно впевнені, що хочете заблокувати весь домен {domain}? У більшості випадків для нормальної роботи краще заблокувати/заглушити лише деяких користувачів.", "confirmations.mute.confirm": "Заглушити", "confirmations.mute.message": "Ви впевнені, що хочете заглушити {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", "embed.instructions": "Embed this status on your website by copying the code below.", @@ -264,6 +266,7 @@ "status.reblog": "Передмухнути", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} передмухнув(-ла)", + "status.redraft": "Delete & re-draft", "status.reply": "Відповісти", "status.replyAll": "Відповісти на тред", "status.report": "Поскаржитися", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", "upload_area.title": "Перетягніть сюди, щоб завантажити", "upload_button.label": "Додати медіаконтент", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index 854c9fcdd..24bab6f80 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "你真的确定要隐藏所有来自 {domain} 的内容吗?多数情况下,屏蔽或隐藏几个特定的用户应该就能满足你的需要了。", "confirmations.mute.confirm": "隐藏", "confirmations.mute.message": "你确定要隐藏 {name} 吗?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "取消关注", "confirmations.unfollow.message": "你确定要取消关注 {name} 吗?", "embed.instructions": "要在你的网站上嵌入这条嘟文,请复制以下代码。", @@ -264,6 +266,7 @@ "status.reblog": "转嘟", "status.reblog_private": "转嘟给原有关注者", "status.reblogged_by": "{name} 转嘟了", + "status.redraft": "Delete & re-draft", "status.reply": "回复", "status.replyAll": "回复所有人", "status.report": "举报 @{name}", @@ -284,8 +287,6 @@ "timeline.media": "媒体", "timeline.posts": "嘟文", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "如果你现在离开 Mastodon,你的草稿内容将会被丢弃。", "upload_area.title": "将文件拖放到此处开始上传", "upload_button.label": "上传媒体文件", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index 1fea2ced3..578f03842 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "你真的真的確定要隱藏整個 {domain} ?多數情況下,比較推薦封鎖或靜音幾個特定目標就好。", "confirmations.mute.confirm": "靜音", "confirmations.mute.message": "你確定要將{name}靜音嗎?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "取消關注", "confirmations.unfollow.message": "真的不要繼續關注 {name} 了嗎?", "embed.instructions": "要內嵌此文章,請將以下代碼貼進你的網站。", @@ -264,6 +266,7 @@ "status.reblog": "轉推", "status.reblog_private": "轉推到原讀者", "status.reblogged_by": "{name} 轉推", + "status.redraft": "Delete & re-draft", "status.reply": "回應", "status.replyAll": "回應所有人", "status.report": "舉報 @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "文章", "trends.count_by_accounts": "{count} 位用戶在討論", - "trends.header": "現時趨勢", - "trends.refresh": "重新載入", "ui.beforeunload": "如果你現在離開 Mastodon,你的草稿內容將會被丟棄。", "upload_area.title": "將檔案拖放至此上載", "upload_button.label": "上載媒體檔案", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 3f1bc19be..88dd4ac6d 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -83,6 +83,8 @@ "confirmations.domain_block.message": "你真的真的確定要隱藏整個 {domain} ?多數情況下,比較推薦封鎖或消音幾個特定目標就好。", "confirmations.mute.confirm": "消音", "confirmations.mute.message": "你確定要消音 {name} ?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", "confirmations.unfollow.confirm": "取消關注", "confirmations.unfollow.message": "真的不要繼續關注 {name} 了嗎?", "embed.instructions": "要內嵌此貼文,請將以下代碼貼進你的網站。", @@ -264,6 +266,7 @@ "status.reblog": "轉推", "status.reblog_private": "Boost to original audience", "status.reblogged_by": "{name} 轉推了", + "status.redraft": "Delete & re-draft", "status.reply": "回應", "status.replyAll": "回應這串", "status.report": "通報 @{name}", @@ -284,8 +287,6 @@ "timeline.media": "Media", "timeline.posts": "Toots", "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.header": "Trending now", - "trends.refresh": "Refresh", "ui.beforeunload": "如果離開 Mastodon,你的草稿將會不見。", "upload_area.title": "拖放來上傳", "upload_button.label": "增加媒體", diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js index 62461d1a7..8524ddb8e 100644 --- a/app/javascript/mastodon/reducers/compose.js +++ b/app/javascript/mastodon/reducers/compose.js @@ -32,9 +32,11 @@ import { } from '../actions/compose'; import { TIMELINE_DELETE } from '../actions/timelines'; import { STORE_HYDRATE } from '../actions/store'; +import { REDRAFT } from '../actions/statuses'; import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable'; import uuid from '../uuid'; import { me } from '../initial_state'; +import { unescapeHTML } from '../utils/html'; const initialState = ImmutableMap({ mounted: 0, @@ -170,6 +172,18 @@ const hydrate = (state, hydratedState) => { return state; }; +const domParser = new DOMParser(); + +const expandMentions = status => { + const fragment = domParser.parseFromString(status.get('content'), 'text/html').documentElement; + + status.get('mentions').forEach(mention => { + fragment.querySelector(`a[href="${mention.get('url')}"]`).textContent = `@${mention.get('acct')}`; + }); + + return fragment.innerHTML; +}; + export default function compose(state = initialState, action) { switch(action.type) { case STORE_HYDRATE: @@ -301,6 +315,24 @@ export default function compose(state = initialState, action) { return item; })); + case REDRAFT: + return state.withMutations(map => { + map.set('text', unescapeHTML(expandMentions(action.status))); + map.set('in_reply_to', action.status.get('in_reply_to_id')); + map.set('privacy', action.status.get('visibility')); + map.set('media_attachments', action.status.get('media_attachments')); + map.set('focusDate', new Date()); + map.set('caretPosition', null); + map.set('idempotencyKey', uuid()); + + if (action.status.get('spoiler_text').length > 0) { + map.set('spoiler', true); + map.set('spoiler_text', action.status.get('spoiler_text')); + } else { + map.set('spoiler', false); + map.set('spoiler_text', ''); + } + }); default: return state; } diff --git a/app/javascript/mastodon/reducers/index.js b/app/javascript/mastodon/reducers/index.js index 019c1f466..3d9a6a132 100644 --- a/app/javascript/mastodon/reducers/index.js +++ b/app/javascript/mastodon/reducers/index.js @@ -26,7 +26,6 @@ import height_cache from './height_cache'; import custom_emojis from './custom_emojis'; import lists from './lists'; import listEditor from './list_editor'; -import trends from './trends'; const reducers = { dropdown_menu, @@ -56,7 +55,6 @@ const reducers = { custom_emojis, lists, listEditor, - trends, }; export default combineReducers(reducers); diff --git a/app/javascript/mastodon/reducers/trends.js b/app/javascript/mastodon/reducers/trends.js deleted file mode 100644 index 5cecc8fca..000000000 --- a/app/javascript/mastodon/reducers/trends.js +++ /dev/null @@ -1,23 +0,0 @@ -import { TRENDS_FETCH_REQUEST, TRENDS_FETCH_SUCCESS, TRENDS_FETCH_FAIL } from '../actions/trends'; -import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; - -const initialState = ImmutableMap({ - items: ImmutableList(), - isLoading: false, -}); - -export default function trendsReducer(state = initialState, action) { - switch(action.type) { - case TRENDS_FETCH_REQUEST: - return state.set('isLoading', true); - case TRENDS_FETCH_SUCCESS: - return state.withMutations(map => { - map.set('items', fromJS(action.trends)); - map.set('isLoading', false); - }); - case TRENDS_FETCH_FAIL: - return state.set('isLoading', false); - default: - return state; - } -}; diff --git a/app/javascript/mastodon/utils/html.js b/app/javascript/mastodon/utils/html.js index 0b646ce58..5159df9db 100644 --- a/app/javascript/mastodon/utils/html.js +++ b/app/javascript/mastodon/utils/html.js @@ -1,6 +1,5 @@ export const unescapeHTML = (html) => { const wrapper = document.createElement('div'); - html = html.replace(/<br \/>|<br>|\n/g, ' '); - wrapper.innerHTML = html; + wrapper.innerHTML = html.replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n').replace(/<[^>]*>/g, ''); return wrapper.textContent; }; diff --git a/app/javascript/mastodon/utils/numbers.js b/app/javascript/mastodon/utils/numbers.js new file mode 100644 index 000000000..fdd8269ae --- /dev/null +++ b/app/javascript/mastodon/utils/numbers.js @@ -0,0 +1,10 @@ +import React, { Fragment } from 'react'; +import { FormattedNumber } from 'react-intl'; + +export const shortNumberFormat = number => { + if (number < 1000) { + return <FormattedNumber value={number} />; + } else { + return <Fragment><FormattedNumber value={number / 1000} maximumFractionDigits={1} />K</Fragment>; + } +}; diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index fe304317d..460dc53a9 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -26,20 +26,20 @@ } .compose-form .compose-form__modifiers .compose-form__upload__actions .icon-button { - color: $ui-base-color; + color: lighten($white, 7%); &:active, &:focus, &:hover { - color: darken($ui-base-color, 7%); + color: $white; } } .compose-form .compose-form__modifiers .compose-form__upload-description input { - color: $ui-base-color; + color: lighten($white, 7%); &::placeholder { - color: $ui-base-color; + color: lighten($white, 7%); } } @@ -100,7 +100,7 @@ .dropdown-menu__item { a { background: $ui-base-color; - color: $ui-secondary-color; + color: $darker-text-color; } } @@ -189,17 +189,18 @@ // Change the default colors used on some parts of the profile pages .activity-stream-tabs { background: $account-background-color; - - a { - &.active { - color: $ui-primary-color; - } - } + border-bottom-color: lighten($ui-base-color, 8%); } .activity-stream { .entry { background: $account-background-color; + + .detailed-status.light, + .more.light, + .status.light { + border-bottom-color: lighten($ui-base-color, 8%); + } } .status.light { @@ -219,7 +220,7 @@ .account-grid-card { .controls { .icon-button { - color: $ui-secondary-color; + color: $darker-text-color; } } @@ -230,7 +231,7 @@ } .username { - color: $ui-secondary-color; + color: $darker-text-color; } .account__header__content { diff --git a/app/javascript/styles/mastodon/tables.scss b/app/javascript/styles/mastodon/tables.scss index 982bfd990..e54c55947 100644 --- a/app/javascript/styles/mastodon/tables.scss +++ b/app/javascript/styles/mastodon/tables.scss @@ -195,6 +195,7 @@ a.table-action-link { font-weight: 700; background: linear-gradient(to right, orange , yellow, green, cyan, blue, violet,orange , yellow, green, cyan, blue, violet); background-size: 200% 100%; + -webkit-background-clip: text; background-clip: text; color: transparent; animation: Swag 2s linear 0s infinite; diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb index c17f04776..c17f19a60 100644 --- a/app/models/concerns/remotable.rb +++ b/app/models/concerns/remotable.rb @@ -24,14 +24,17 @@ module Remotable Request.new(:get, url).perform do |response| next if response.code != 200 - matches = response.headers['content-disposition']&.match(/filename="([^"]*)"/) - filename = matches.nil? ? parsed_url.path.split('/').last : matches[1] + content_type = parse_content_type(response.headers.get('content-type').last) + extname = detect_extname_from_content_type(content_type) + + if extname.nil? + disposition = response.headers.get('content-disposition').last + matches = disposition&.match(/filename="([^"]*)"/) + filename = matches.nil? ? parsed_url.path.split('/').last : matches[1] + extname = filename.nil? ? '' : File.extname(filename) + end + basename = SecureRandom.hex(8) - extname = if filename.nil? - '' - else - File.extname(filename) - end send("#{attachment_name}=", StringIO.new(response.body_with_limit(limit))) send("#{attachment_name}_file_name=", basename + extname) @@ -57,4 +60,26 @@ module Remotable end end end + + private + + def detect_extname_from_content_type(content_type) + return if content_type.nil? + + type = MIME::Types[content_type].first + + return if type.nil? + + extname = type.extensions.first + + return if extname.nil? + + ".#{extname}" + end + + def parse_content_type(content_type) + return if content_type.nil? + + content_type.split(/\s*;\s*/).first + end end diff --git a/app/models/concerns/status_threading_concern.rb b/app/models/concerns/status_threading_concern.rb index 1ba8fc693..fa441469c 100644 --- a/app/models/concerns/status_threading_concern.rb +++ b/app/models/concerns/status_threading_concern.rb @@ -51,12 +51,16 @@ module StatusThreadingConcern end def descendant_statuses(limit, max_child_id, since_child_id, depth) - Status.find_by_sql([<<-SQL.squish, id: id, limit: limit, max_child_id: max_child_id, since_child_id: since_child_id, depth: depth]) + # use limit + 1 and depth + 1 because 'self' is included + depth += 1 if depth.present? + limit += 1 if limit.present? + + descendants_with_self = Status.find_by_sql([<<-SQL.squish, id: id, limit: limit, max_child_id: max_child_id, since_child_id: since_child_id, depth: depth]) WITH RECURSIVE search_tree(id, path) AS ( SELECT id, ARRAY[id] FROM statuses - WHERE in_reply_to_id = :id AND COALESCE(id < :max_child_id, TRUE) AND COALESCE(id > :since_child_id, TRUE) + WHERE id = :id AND COALESCE(id < :max_child_id, TRUE) AND COALESCE(id > :since_child_id, TRUE) UNION ALL SELECT statuses.id, path || statuses.id FROM search_tree @@ -68,6 +72,8 @@ module StatusThreadingConcern ORDER BY path LIMIT :limit SQL + + descendants_with_self - [self] end def find_statuses_from_tree_path(ids, account) diff --git a/app/models/glitch/keyword_mute.rb b/app/models/glitch/keyword_mute.rb index 11b7958f6..49769cb73 100644 --- a/app/models/glitch/keyword_mute.rb +++ b/app/models/glitch/keyword_mute.rb @@ -67,7 +67,7 @@ class Glitch::KeywordMute < ApplicationRecord def matches?(str, required_scope) ((required_scope & scope) == required_scope) && \ - str =~ (whole_word ? boundary_regex_for_keyword : /#{keyword}/i) + str =~ (whole_word ? boundary_regex_for_keyword : /#{Regexp.escape(keyword)}/i) end end diff --git a/app/models/status.rb b/app/models/status.rb index 69fae2eb6..c0e241ddd 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -55,7 +55,7 @@ class Status < ApplicationRecord has_many :reblogs, foreign_key: 'reblog_of_id', class_name: 'Status', inverse_of: :reblog, dependent: :destroy has_many :replies, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :thread has_many :mentions, dependent: :destroy - has_many :media_attachments, dependent: :destroy + has_many :media_attachments, dependent: :nullify has_and_belongs_to_many :tags has_and_belongs_to_many :preview_cards @@ -194,7 +194,6 @@ class Status < ApplicationRecord before_validation :set_reblog before_validation :set_visibility before_validation :set_conversation - before_validation :set_sensitivity before_validation :set_local class << self @@ -317,7 +316,11 @@ class Status < ApplicationRecord # non-followers can see everything that isn't private/direct, but can see stuff they are mentioned in. visibility.push(:private) if account.following?(target_account) - where(visibility: visibility).or(where(id: account.mentions.select(:status_id))) + scope = left_outer_joins(:reblog) + + scope.where(visibility: visibility) + .or(scope.where(id: account.mentions.select(:status_id))) + .merge(scope.where(reblog_of_id: nil).or(scope.where.not(reblogs_statuses: { account_id: account.excluded_from_timeline_account_ids }))) end end @@ -388,10 +391,6 @@ class Status < ApplicationRecord self.sensitive = false if sensitive.nil? end - def set_sensitivity - self.sensitive = sensitive || spoiler_text.present? - end - def set_locality if account.domain.nil? && !attribute_changed?(:local_only) self.local_only = marked_local_only? diff --git a/app/models/trending_tags.rb b/app/models/trending_tags.rb index 287de2a8a..c3641d7fd 100644 --- a/app/models/trending_tags.rb +++ b/app/models/trending_tags.rb @@ -1,9 +1,7 @@ # frozen_string_literal: true class TrendingTags - KEY = 'trending_tags' EXPIRE_HISTORY_AFTER = 7.days.seconds - THRESHOLD = 5 class << self def record_use!(tag, account, at_time = Time.now.utc) @@ -11,30 +9,10 @@ class TrendingTags increment_historical_use!(tag.id, at_time) increment_unique_use!(tag.id, account.id, at_time) - increment_vote!(tag.id, at_time) - end - - def get(limit) - tag_ids = redis.zrevrange(KEY, 0, limit).map(&:to_i) - tags = Tag.where(id: tag_ids).to_a.map { |tag| [tag.id, tag] }.to_h - tag_ids.map { |tag_id| tags[tag_id] }.compact end private - def increment_vote!(tag_id, at_time) - expected = redis.pfcount("activity:tags:#{tag_id}:#{(at_time - 1.day).beginning_of_day.to_i}:accounts").to_f - expected = 1.0 if expected.zero? - observed = redis.pfcount("activity:tags:#{tag_id}:#{at_time.beginning_of_day.to_i}:accounts").to_f - - if expected > observed || observed < THRESHOLD - redis.zrem(KEY, tag_id.to_s) - else - score = ((observed - expected)**2) / expected - redis.zadd(KEY, score, tag_id.to_s) - end - end - def increment_historical_use!(tag_id, at_time) key = "activity:tags:#{tag_id}:#{at_time.beginning_of_day.to_i}" redis.incrby(key, 1) diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index 86d0f9971..560a81768 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -40,7 +40,7 @@ class FetchLinkCardService < BaseService @card ||= PreviewCard.new(url: @url) failed = Request.new(:head, @url).perform do |res| - res.code != 405 && (res.code != 200 || res.mime_type != 'text/html') + res.code != 405 && res.code != 501 && (res.code != 200 || res.mime_type != 'text/html') end return if failed diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index b1d5bd3a7..6e982c7e6 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -28,7 +28,7 @@ class PostStatusService < BaseService status = account.statuses.create!(text: text, media_attachments: media || [], thread: in_reply_to, - sensitive: (options[:sensitive].nil? ? account.user&.setting_default_sensitive : options[:sensitive]), + sensitive: (options[:sensitive].nil? ? account.user&.setting_default_sensitive : options[:sensitive]) || options[:spoiler_text].present?, spoiler_text: options[:spoiler_text] || '', visibility: options[:visibility] || account.user&.setting_default_privacy, language: language_from_option(options[:language]) || LanguageDetector.instance.detect(text, account), diff --git a/app/views/admin/accounts/_account.html.haml b/app/views/admin/accounts/_account.html.haml index dfa7c5649..c6e63152d 100644 --- a/app/views/admin/accounts/_account.html.haml +++ b/app/views/admin/accounts/_account.html.haml @@ -1,7 +1,7 @@ %tr %td.username = account.username - %td.domain + %td - unless account.local? = link_to account.domain, admin_accounts_path(by_domain: account.domain) %td diff --git a/app/views/layouts/error.html.haml b/app/views/layouts/error.html.haml index 9904b8fdd..be3e9f105 100644 --- a/app/views/layouts/error.html.haml +++ b/app/views/layouts/error.html.haml @@ -5,8 +5,8 @@ %meta{ charset: 'utf-8' }/ %title= safe_join([yield(:page_title), Setting.default_settings['site_title']], ' - ') %meta{ content: 'width=device-width,initial-scale=1', name: 'viewport' }/ - = render partial: 'layouts/theme', object: @core - = render partial: 'layouts/theme', object: @theme + = render partial: 'layouts/theme', object: (@core || { pack: 'common' }) + = render partial: 'layouts/theme', object: (@theme || { pack: 'common', flavour: 'glitch', skin: 'default' }) %body.error .dialog %img{ alt: Setting.default_settings['site_title'], src: '/oops.gif' }/ |