diff options
98 files changed, 428 insertions, 180 deletions
diff --git a/.buildpacks b/.buildpacks index 3450683ce..5e73304a5 100644 --- a/.buildpacks +++ b/.buildpacks @@ -1,4 +1,3 @@ https://github.com/heroku/heroku-buildpack-apt https://github.com/Scalingo/ffmpeg-buildpack -https://github.com/Scalingo/nodejs-buildpack https://github.com/Scalingo/ruby-buildpack diff --git a/.circleci/config.yml b/.circleci/config.yml index 9f43a0573..862fa126b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -72,11 +72,12 @@ aliases: - run: name: Set bundler settings command: | - bundle config clean 'true' - bundle config deployment 'true' - bundle config with 'pam_authentication' - bundle config without 'development production' - bundle config frozen 'true' + bundle config --local clean 'true' + bundle config --local deployment 'true' + bundle config --local with 'pam_authentication' + bundle config --local without 'development production' + bundle config --local frozen 'true' + bundle config --local path $BUNDLE_PATH - run: name: Install bundler dependencies command: bundle check || (bundle install && bundle clean) diff --git a/app.json b/app.json index 211f17d81..e4f7cf403 100644 --- a/app.json +++ b/app.json @@ -89,9 +89,6 @@ "url": "https://github.com/heroku/heroku-buildpack-apt" }, { - "url": "heroku/nodejs" - }, - { "url": "heroku/ruby" } ], diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index b3edce676..c8529318f 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -58,6 +58,7 @@ class Api::V1::StatusesController < Api::BaseController @status.discard RemovalWorker.perform_async(@status.id, redraft: true) + @status.account.statuses_count = @status.account.statuses_count - 1 render json: @status, serializer: REST::StatusSerializer, source_requested: true end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 63d9f91fb..e996c2217 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -56,7 +56,7 @@ class ApplicationController < ActionController::Base end def store_current_location - store_location_for(:user, request.url) unless request.format == :json + store_location_for(:user, request.url) unless [:json, :rss].include?(request.format&.to_sym) end def require_admin! diff --git a/app/javascript/flavours/glitch/components/common_counter.js b/app/javascript/flavours/glitch/components/common_counter.js index 4fdf3babf..e10cd9b76 100644 --- a/app/javascript/flavours/glitch/components/common_counter.js +++ b/app/javascript/flavours/glitch/components/common_counter.js @@ -37,7 +37,7 @@ export function counterRenderer(counterType, isBold = true) { return (displayNumber, pluralReady) => ( <FormattedMessage id='account.following_counter' - defaultMessage='{count, plural, other {{counter} Following}}' + defaultMessage='{count, plural, one {{counter} Following} other {{counter} Following}}' values={{ count: pluralReady, counter: renderCounter(displayNumber), diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js index 5d10ed650..cc8d9f1f3 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.js @@ -20,7 +20,7 @@ const mapStateToProps = (state, { scrollKey }) => { }; }; -export default @connect(mapStateToProps) +export default @connect(mapStateToProps, null, null, { forwardRef: true }) class ScrollableList extends PureComponent { static contextTypes = { diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js index a9abc545e..3e2e95f35 100644 --- a/app/javascript/flavours/glitch/features/status/index.js +++ b/app/javascript/flavours/glitch/features/status/index.js @@ -557,7 +557,7 @@ class Status extends ImmutablePureComponent { showBackButton multiColumn={multiColumn} extraButton={( - <button className='column-header__button' title={intl.formatMessage(!isExpanded ? messages.revealAll : messages.hideAll)} aria-label={intl.formatMessage(!isExpanded ? messages.revealAll : messages.hideAll)} onClick={this.handleToggleAll} aria-pressed={!isExpanded ? 'false' : 'true'}><Icon id={status.get('hidden') ? 'eye-slash' : 'eye'} /></button> + <button className='column-header__button' title={intl.formatMessage(!isExpanded ? messages.revealAll : messages.hideAll)} aria-label={intl.formatMessage(!isExpanded ? messages.revealAll : messages.hideAll)} onClick={this.handleToggleAll} aria-pressed={!isExpanded ? 'false' : 'true'}><Icon id={!isExpanded ? 'eye-slash' : 'eye'} /></button> )} /> @@ -566,7 +566,7 @@ class Status extends ImmutablePureComponent { {ancestors} <HotKeys handlers={handlers}> - <div className='focusable' tabIndex='0' aria-label={textForScreenReader(intl, status, false, !status.get('hidden'))}> + <div className='focusable' tabIndex='0' aria-label={textForScreenReader(intl, status, false, isExpanded)}> <DetailedStatus key={`details-${status.get('id')}`} status={status} diff --git a/app/javascript/flavours/glitch/styles/components/boost.scss b/app/javascript/flavours/glitch/styles/components/boost.scss index f1ad041e9..2d307765c 100644 --- a/app/javascript/flavours/glitch/styles/components/boost.scss +++ b/app/javascript/flavours/glitch/styles/components/boost.scss @@ -9,13 +9,6 @@ button.icon-button i.fa-retweet { // Disabled variant button.icon-button.disabled i.fa-retweet { &, &:hover { - background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='209'><path d='M4.97 3.16c-.1.03-.17.1-.22.18L.8 8.24c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77L5.5 3.35c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.02-2.4.02H7.1l2.32 2.85.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color(darken($action-button-color, 13%))}' stroke-width='0'/></svg>"); - } -} - -// Disabled variant for use with DMs -.status-direct button.icon-button.disabled i.fa-retweet { - &, &:hover { - background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='209'><path d='M4.97 3.16c-.1.03-.17.1-.22.18L.8 8.24c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77L5.5 3.35c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.02-2.4.02H7.1l2.32 2.85.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color(darken($action-button-color, 13%))}' stroke-width='0'/></svg>"); + background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' height='209' width='22'><path d='M 18.972656 1.2011719 C 18.829825 1.1881782 18.685932 1.2302188 18.572266 1.3300781 L 15.990234 3.5996094 C 15.58109 3.6070661 15.297269 3.609375 14.730469 3.609375 L 7.0996094 3.609375 L 9.4199219 6.4609375 L 9.4492188 6.5195312 L 12.664062 6.5195312 L 6.5761719 11.867188 C 6.5674697 11.818249 6.5507813 11.773891 6.5507812 11.720703 L 6.5507812 9.0195312 L 9.0507812 9.0195312 C 9.4207813 9.0495313 9.6792188 8.54 9.4492188 8.25 L 5.5 3.3496094 C 5.38 3.1796094 5.1607031 3.1003906 4.9707031 3.1503906 L 4.9707031 3.1601562 C 4.8707031 3.1901563 4.8 3.2598438 4.75 3.3398438 L 0.80078125 8.2402344 C 0.60078125 8.5402344 0.8292187 9.0190625 1.1992188 9.0390625 L 3.5996094 9.0390625 L 3.5996094 11.720703 C 3.5996094 13.045739 3.5690668 13.895038 3.6503906 14.4375 L 2.6152344 15.347656 C 2.3879011 15.547375 2.3754917 15.901081 2.5859375 16.140625 L 3.1464844 16.78125 C 3.3569308 17.020794 3.7101667 17.053234 3.9375 16.853516 L 19.892578 2.8359375 C 20.119911 2.6362188 20.134275 2.282513 19.923828 2.0429688 L 19.361328 1.4023438 C 19.256105 1.282572 19.115488 1.2141655 18.972656 1.2011719 z M 18.410156 6.7753906 L 15.419922 9.4042969 L 15.419922 9.9394531 L 14.810547 9.9394531 L 13.148438 11.400391 L 16.539062 15.640625 C 16.719062 15.890625 17.140313 15.890625 17.320312 15.640625 L 21.259766 10.740234 C 21.519766 10.460234 21.260625 9.9094531 20.890625 9.9394531 L 18.400391 9.9394531 L 18.400391 7.2402344 C 18.400391 7.0470074 18.407711 6.9489682 18.410156 6.7753906 z M 11.966797 12.439453 L 8.6679688 15.339844 L 14.919922 15.339844 L 12.619141 12.5 C 12.589141 12.48 12.590313 12.459453 12.570312 12.439453 L 11.966797 12.439453 z' fill='#{hex-color(darken($action-button-color, 13%))}' stroke-width='0'/></svg>"); } } diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index a37cef795..843f40ec0 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -1038,7 +1038,7 @@ } } -.no-reduce-motion button.icon-button i.fa-retweet { +button.icon-button i.fa-retweet { background-position: 0 0; height: 19px; transition: background-position 0.9s steps(10); @@ -1051,18 +1051,14 @@ } } -.no-reduce-motion button.icon-button.active i.fa-retweet { +button.icon-button.active i.fa-retweet { transition-duration: 0.9s; background-position: 0 100%; } -.reduce-motion button.icon-button i.fa-retweet { - color: $action-button-color; - transition: color 100ms ease-in; -} - +.reduce-motion button.icon-button i.fa-retweet, .reduce-motion button.icon-button.active i.fa-retweet { - color: $highlight-text-color; + transition: none; } .reduce-motion button.icon-button.disabled i.fa-retweet { diff --git a/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss b/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss index 3b4ffdf3c..c83c82766 100644 --- a/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss +++ b/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss @@ -385,10 +385,3 @@ .directory__tag > div { box-shadow: none; } - -.audio-player .video-player__controls button, -.audio-player .video-player__time-sep, -.audio-player .video-player__time-current, -.audio-player .video-player__time-total { - color: $primary-text-color; -} diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 601a2913c..6ef12f7b9 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -163,7 +163,6 @@ export function submitCompose(routerHistory) { // To make the app more responsive, immediately push the status // into the columns - const insertIfOnline = timelineId => { const timeline = getState().getIn(['timelines', timelineId]); @@ -181,6 +180,7 @@ export function submitCompose(routerHistory) { if (!response.data.local_only) { insertIfOnline('public'); } + insertIfOnline(`account:${response.data.account.id}`); } }).catch(function (error) { dispatch(submitComposeFail(error)); diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js index 5640201c6..e565e0b0a 100644 --- a/app/javascript/mastodon/actions/statuses.js +++ b/app/javascript/mastodon/actions/statuses.js @@ -3,7 +3,7 @@ import openDB from '../storage/db'; import { evictStatus } from '../storage/modifier'; import { deleteFromTimelines } from './timelines'; -import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus } from './importer'; +import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus, importFetchedAccount } from './importer'; import { ensureComposeIsVisible } from './compose'; export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST'; @@ -155,6 +155,7 @@ export function deleteStatus(id, routerHistory, withRedraft = false) { evictStatus(id); dispatch(deleteStatusSuccess(id)); dispatch(deleteFromTimelines(id)); + dispatch(importFetchedAccount(response.data.account)); if (withRedraft) { dispatch(redraft(status, response.data.text)); diff --git a/app/javascript/mastodon/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js index d998fcac4..7cecff66e 100644 --- a/app/javascript/mastodon/actions/streaming.js +++ b/app/javascript/mastodon/actions/streaming.js @@ -71,9 +71,10 @@ const refreshHomeTimelineAndNotification = (dispatch, done) => { dispatch(fetchAnnouncements(done)))))); }; -export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification); -export const connectCommunityStream = ({ onlyMedia } = {}) => connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`); -export const connectPublicStream = ({ onlyMedia, onlyRemote } = {}) => connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`); -export const connectHashtagStream = (id, tag, local, accept) => connectTimelineStream(`hashtag:${id}${local ? ':local' : ''}`, `hashtag${local ? ':local' : ''}&tag=${tag}`, null, accept); -export const connectDirectStream = () => connectTimelineStream('direct', 'direct'); -export const connectListStream = id => connectTimelineStream(`list:${id}`, `list&list=${id}`); +export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification); +export const connectUserTimelineStream = (accountId) => connectTimelineStream(`account:${accountId}`, 'user'); +export const connectCommunityStream = ({ onlyMedia } = {}) => connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`); +export const connectPublicStream = ({ onlyMedia, onlyRemote } = {}) => connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`); +export const connectHashtagStream = (id, tag, local, accept) => connectTimelineStream(`hashtag:${id}${local ? ':local' : ''}`, `hashtag${local ? ':local' : ''}&tag=${tag}`, null, accept); +export const connectDirectStream = () => connectTimelineStream('direct', 'direct'); +export const connectListStream = id => connectTimelineStream(`list:${id}`, `list&list=${id}`); diff --git a/app/javascript/mastodon/components/common_counter.js b/app/javascript/mastodon/components/common_counter.js index 4fdf3babf..e10cd9b76 100644 --- a/app/javascript/mastodon/components/common_counter.js +++ b/app/javascript/mastodon/components/common_counter.js @@ -37,7 +37,7 @@ export function counterRenderer(counterType, isBold = true) { return (displayNumber, pluralReady) => ( <FormattedMessage id='account.following_counter' - defaultMessage='{count, plural, other {{counter} Following}}' + defaultMessage='{count, plural, one {{counter} Following} other {{counter} Following}}' values={{ count: pluralReady, counter: renderCounter(displayNumber), diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js index 35740f226..2689b18ef 100644 --- a/app/javascript/mastodon/components/scrollable_list.js +++ b/app/javascript/mastodon/components/scrollable_list.js @@ -20,7 +20,7 @@ const mapStateToProps = (state, { scrollKey }) => { }; }; -export default @connect(mapStateToProps) +export default @connect(mapStateToProps, null, null, { forwardRef: true }) class ScrollableList extends PureComponent { static contextTypes = { diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js index 5ea907a1f..3846cc637 100644 --- a/app/javascript/mastodon/features/account_timeline/index.js +++ b/app/javascript/mastodon/features/account_timeline/index.js @@ -15,6 +15,8 @@ import { FormattedMessage } from 'react-intl'; import { fetchAccountIdentityProofs } from '../../actions/identity_proofs'; import MissingIndicator from 'mastodon/components/missing_indicator'; import TimelineHint from 'mastodon/components/timeline_hint'; +import { me } from 'mastodon/initial_state'; +import { connectUserTimelineStream } from '../../actions/streaming'; const emptyList = ImmutableList(); @@ -73,6 +75,12 @@ class AccountTimeline extends ImmutablePureComponent { this.props.dispatch(expandAccountTimeline(accountId, { withReplies })); } + componentDidMount () { + if (this.props.params.accountId === me) { + this.disconnect = this.props.dispatch(connectUserTimelineStream(me)); + } + } + componentWillReceiveProps (nextProps) { if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) { this.props.dispatch(fetchAccount(nextProps.params.accountId)); @@ -86,6 +94,13 @@ class AccountTimeline extends ImmutablePureComponent { } } + componentWillUnmount () { + if (this.disconnect) { + this.disconnect(); + this.disconnect = null; + } + } + handleLoadMore = maxId => { this.props.dispatch(expandAccountTimeline(this.props.params.accountId, { maxId, withReplies: this.props.withReplies })); } diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index a0b540432..548471edf 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -16,7 +16,7 @@ "account.followers": "مُتابِعون", "account.followers.empty": "لا أحد يتبع هذا الحساب بعد.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "هذا الحساب لا يتبع أحدًا بعد.", "account.follows_you": "يتابعك", "account.hide_reblogs": "إخفاء ترقيات @{name}", diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json index 491faa057..6c6232262 100644 --- a/app/javascript/mastodon/locales/ast.json +++ b/app/javascript/mastodon/locales/ast.json @@ -16,7 +16,7 @@ "account.followers": "Siguidores", "account.followers.empty": "Naide sigue a esti usuariu entá.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Esti usuariu entá nun sigue a naide.", "account.follows_you": "Síguete", "account.hide_reblogs": "Anubrir les comparticiones de @{name}", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 472c88afc..16520dbad 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -16,7 +16,7 @@ "account.followers": "Последователи", "account.followers.empty": "Все още никой не следва този потребител.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Този потребител все още не следва никого.", "account.follows_you": "Твой последовател", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/bn.json b/app/javascript/mastodon/locales/bn.json index b41cdf16d..7de1a1022 100644 --- a/app/javascript/mastodon/locales/bn.json +++ b/app/javascript/mastodon/locales/bn.json @@ -16,7 +16,7 @@ "account.followers": "অনুসরণকারী", "account.followers.empty": "এই সদস্যকে এখনো কেউ অনুসরণ করে না।.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "এই সদস্য কাওকে এখনো অনুসরণ করেন না.", "account.follows_you": "আপনাকে অনুসরণ করে", "account.hide_reblogs": "@{name}'র সমর্থনগুলি লুকিয়ে ফেলুন", diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index f991b7a25..0ddd18de8 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -16,7 +16,7 @@ "account.followers": "Sledující", "account.followers.empty": "Tohoto uživatele ještě nikdo nesleduje.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Tento uživatel ještě nikoho nesleduje.", "account.follows_you": "Sleduje vás", "account.hide_reblogs": "Skrýt boosty od uživatele @{name}", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index 984237a32..312a0f97a 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -16,7 +16,7 @@ "account.followers": "Dilynwyr", "account.followers.empty": "Nid oes neb yn dilyn y defnyddiwr hwn eto.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Nid yw'r defnyddiwr hwn yn dilyn unrhyw un eto.", "account.follows_you": "Yn eich dilyn chi", "account.hide_reblogs": "Cuddio bwstiau o @{name}", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index e59f5283c..a0fb354e6 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -16,7 +16,7 @@ "account.followers": "Følgere", "account.followers.empty": "Der er endnu ingen der følger denne bruger.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Denne bruger følger endnu ikke nogen.", "account.follows_you": "Følger dig", "account.hide_reblogs": "Skjul fremhævelserne fra @{name}", diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index 24b4634c7..8a12c0ebd 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -146,7 +146,7 @@ "id": "account.statuses_counter" }, { - "defaultMessage": "{count, plural, other {{counter} Following}}", + "defaultMessage": "{count, plural, one {{counter} Following} other {{counter} Following}}", "id": "account.following_counter" }, { @@ -2660,6 +2660,22 @@ "id": "status.reblog" }, { + "defaultMessage": "Public", + "id": "privacy.public.short" + }, + { + "defaultMessage": "Unlisted", + "id": "privacy.unlisted.short" + }, + { + "defaultMessage": "Followers-only", + "id": "privacy.private.short" + }, + { + "defaultMessage": "Direct", + "id": "privacy.direct.short" + }, + { "defaultMessage": "You can press {combo} to skip this next time", "id": "boost_modal.combo" } diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index cec1dacdd..62f0ad66b 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json index fc00a6270..558fe38de 100644 --- a/app/javascript/mastodon/locales/et.json +++ b/app/javascript/mastodon/locales/et.json @@ -16,7 +16,7 @@ "account.followers": "Jälgijad", "account.followers.empty": "Keegi ei jälgi seda kasutajat veel.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "See kasutaja ei jälgi veel kedagi.", "account.follows_you": "Jälgib Teid", "account.hide_reblogs": "Peida upitused kasutajalt @{name}", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index 0a8043d4d..09471ff2a 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -16,7 +16,7 @@ "account.followers": "Jarraitzaileak", "account.followers.empty": "Ez du inork erabiltzaile hau jarraitzen oraindik.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Erabiltzaile honek ez du inor jarraitzen oraindik.", "account.follows_you": "Jarraitzen dizu", "account.hide_reblogs": "Ezkutatu @{name}(r)en bultzadak", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index b808be172..262ee2f4b 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -16,7 +16,7 @@ "account.followers": "Seuraajaa", "account.followers.empty": "Tällä käyttäjällä ei ole vielä seuraajia.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.", "account.follows_you": "Seuraa sinua", "account.hide_reblogs": "Piilota buustaukset käyttäjältä @{name}", diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index 5a27ed96c..5de7b27a5 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 81e713dc3..91fce039f 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -16,7 +16,7 @@ "account.followers": "עוקבים", "account.followers.empty": "אף אחד לא עוקב אחר המשתמש הזה עדיין.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "משתמש זה לא עוקב אחר אף אחד עדיין.", "account.follows_you": "במעקב אחריך", "account.hide_reblogs": "להסתיר הידהודים מאת @{name}", diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json index 4cc12830f..ff207d640 100644 --- a/app/javascript/mastodon/locales/hi.json +++ b/app/javascript/mastodon/locales/hi.json @@ -16,7 +16,7 @@ "account.followers": "फॉलोवर", "account.followers.empty": "कोई भी इस यूज़र् को फ़ॉलो नहीं करता है", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "यह यूज़र् अभी तक किसी को फॉलो नहीं करता है।", "account.follows_you": "आपको फॉलो करता है", "account.hide_reblogs": "@{name} के बूस्ट छुपाएं", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index a7e13b2eb..7179bc536 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -16,7 +16,7 @@ "account.followers": "Sljedbenici", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "te slijedi", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 5b0f345af..91ad76e03 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -16,7 +16,7 @@ "account.followers": "Pengikut", "account.followers.empty": "Tidak ada satupun yang mengkuti pengguna ini saat ini.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Pengguna ini belum mengikuti siapapun.", "account.follows_you": "Mengikuti anda", "account.hide_reblogs": "Sembunyikan boosts dari @{name}", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index 45e74b675..e79bee21d 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -16,7 +16,7 @@ "account.followers": "Sequanti", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Sequas tu", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index 4a281cf80..72d8fefaf 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -16,7 +16,7 @@ "account.followers": "Fylgjendur", "account.followers.empty": "Ennþá fylgist enginn með þessum notanda.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Þessi notandi fylgist ennþá ekki með neinum.", "account.follows_you": "Fylgir þér", "account.hide_reblogs": "Fela endurbirtingar fyrir @{name}", diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json index 36f27e69d..0051fee1f 100644 --- a/app/javascript/mastodon/locales/ka.json +++ b/app/javascript/mastodon/locales/ka.json @@ -16,7 +16,7 @@ "account.followers": "მიმდევრები", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "მოგყვებათ", "account.hide_reblogs": "დაიმალოს ბუსტები @{name}-სგან", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index dceb434d3..05f72596b 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -16,7 +16,7 @@ "account.followers": "Imeḍfaren", "account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.", "account.followers_counter": "{count, plural, one {{count} n umeḍfar} other {{count} n imeḍfaren}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Ar tura, amseqdac-agi ur yeṭṭafaṛ yiwen.", "account.follows_you": "Yeṭṭafaṛ-ik", "account.hide_reblogs": "Ffer ayen i ibeṭṭu @{name}", diff --git a/app/javascript/mastodon/locales/kk.json b/app/javascript/mastodon/locales/kk.json index d7adf5836..322c15fff 100644 --- a/app/javascript/mastodon/locales/kk.json +++ b/app/javascript/mastodon/locales/kk.json @@ -16,7 +16,7 @@ "account.followers": "Оқырмандар", "account.followers.empty": "Әлі ешкім жазылмаған.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Ешкімге жазылмапты.", "account.follows_you": "Сізге жазылыпты", "account.hide_reblogs": "@{name} атты қолданушының әрекеттерін жасыру", diff --git a/app/javascript/mastodon/locales/kn.json b/app/javascript/mastodon/locales/kn.json index 43738ba70..e9618e0f2 100644 --- a/app/javascript/mastodon/locales/kn.json +++ b/app/javascript/mastodon/locales/kn.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json index 36f55e800..e5d833fe8 100644 --- a/app/javascript/mastodon/locales/ku.json +++ b/app/javascript/mastodon/locales/ku.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index 43738ba70..e9618e0f2 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index 01fe7a07c..2812760a6 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -16,7 +16,7 @@ "account.followers": "Sekotāji", "account.followers.empty": "Šim lietotājam nav sekotāju.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.", "account.follows_you": "Seko tev", "account.hide_reblogs": "Paslēpt paceltos ierakstus no lietotāja @{name}", diff --git a/app/javascript/mastodon/locales/mk.json b/app/javascript/mastodon/locales/mk.json index 7e9c0dc42..2bb9a2e2a 100644 --- a/app/javascript/mastodon/locales/mk.json +++ b/app/javascript/mastodon/locales/mk.json @@ -16,7 +16,7 @@ "account.followers": "Следбеници", "account.followers.empty": "Никој не го следи овој корисник сеуште.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Корисникот не следи никој сеуште.", "account.follows_you": "Те следи тебе", "account.hide_reblogs": "Сокриј буст од @{name}", diff --git a/app/javascript/mastodon/locales/ml.json b/app/javascript/mastodon/locales/ml.json index 78dced532..4a390ad70 100644 --- a/app/javascript/mastodon/locales/ml.json +++ b/app/javascript/mastodon/locales/ml.json @@ -16,7 +16,7 @@ "account.followers": "പിന്തുടരുന്നവർ", "account.followers.empty": "ഈ ഉപയോക്താവിനെ ആരും ഇതുവരെ പിന്തുടരുന്നില്ല.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "ഈ ഉപയോക്താവ് ആരേയും ഇതുവരെ പിന്തുടരുന്നില്ല.", "account.follows_you": "നിങ്ങളെ പിന്തുടരുന്നു", "account.hide_reblogs": "@{name} ബൂസ്റ്റ് ചെയ്തവ മറയ്കുക", diff --git a/app/javascript/mastodon/locales/mr.json b/app/javascript/mastodon/locales/mr.json index a56d2544a..5a93ae851 100644 --- a/app/javascript/mastodon/locales/mr.json +++ b/app/javascript/mastodon/locales/mr.json @@ -16,7 +16,7 @@ "account.followers": "अनुयायी", "account.followers.empty": "ह्या वापरकर्त्याचा आतापर्यंत कोणी अनुयायी नाही.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "हा वापरकर्ता अजूनपर्यंत कोणाचा अनुयायी नाही.", "account.follows_you": "तुमचा अनुयायी आहे", "account.hide_reblogs": "@{name} पासून सर्व बूस्ट लपवा", diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json index a19483014..5fc777887 100644 --- a/app/javascript/mastodon/locales/ms.json +++ b/app/javascript/mastodon/locales/ms.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index 1611ba636..a69fee754 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -16,7 +16,7 @@ "account.followers": "Volgers", "account.followers.empty": "Niemand volgt nog deze gebruiker.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Deze gebruiker volgt nog niemand.", "account.follows_you": "Volgt jou", "account.hide_reblogs": "Verberg boosts van @{name}", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index ed151565d..b567a3533 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -16,7 +16,7 @@ "account.followers": "Fylgjarar", "account.followers.empty": "Ingen fylgjer denne brukaren enno.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Denne brukaren fylgjer ikkje nokon enno.", "account.follows_you": "Fylgjer deg", "account.hide_reblogs": "Gøym fremhevingar frå @{name}", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 7ddfea5bc..a15e96fdc 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -16,7 +16,7 @@ "account.followers": "Følgere", "account.followers.empty": "Ingen følger denne brukeren ennå.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Denne brukeren følger ikke noen enda.", "account.follows_you": "Følger deg", "account.hide_reblogs": "Skjul fremhevinger fra @{name}", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index dfee6f157..1aa0193a5 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -16,7 +16,7 @@ "account.followers": "Seguidors", "account.followers.empty": "Degun sèc pas aqueste utilizaire pel moment.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Aqueste utilizaire sèc pas degun pel moment.", "account.follows_you": "Vos sèc", "account.hide_reblogs": "Rescondre los partatges de @{name}", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index c03ab95cf..cb5a81e63 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -16,7 +16,7 @@ "account.followers": "Śledzący", "account.followers.empty": "Nikt jeszcze nie śledzi tego użytkownika.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Ten użytkownik nie śledzi jeszcze nikogo.", "account.follows_you": "Śledzi Cię", "account.hide_reblogs": "Ukryj podbicia od @{name}", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index c00eca297..544d68102 100644 --- a/app/javascript/mastodon/locales/ro.json +++ b/app/javascript/mastodon/locales/ro.json @@ -16,7 +16,7 @@ "account.followers": "Urmăritori", "account.followers.empty": "Acest utilizator nu are încă urmăritori.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Acest utilizator nu urmărește pe nimeni încă.", "account.follows_you": "Te urmărește", "account.hide_reblogs": "Ascunde impulsurile de la @{name}", diff --git a/app/javascript/mastodon/locales/sc.json b/app/javascript/mastodon/locales/sc.json index 916576656..30a3e3374 100644 --- a/app/javascript/mastodon/locales/sc.json +++ b/app/javascript/mastodon/locales/sc.json @@ -16,7 +16,7 @@ "account.followers": "Sighiduras", "account.followers.empty": "Nemos sighit ancora custa persone.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Custa persone non sighit ancora a nemos.", "account.follows_you": "Ti sighit", "account.hide_reblogs": "Cua is cumpartziduras de @{name}", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index 048704872..38bb7542f 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -16,7 +16,7 @@ "account.followers": "Sledujúci", "account.followers.empty": "Tohto používateľa ešte nikto nenásleduje.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Tento používateľ ešte nikoho nenasleduje.", "account.follows_you": "Nasleduje ťa", "account.hide_reblogs": "Skry vyzdvihnutia od @{name}", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index d13bf5e36..71ba0d1b6 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -16,7 +16,7 @@ "account.followers": "Sledilci", "account.followers.empty": "Nihče ne sledi temu uporabniku.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Ta uporabnik še ne sledi nikomur.", "account.follows_you": "Sledi tebi", "account.hide_reblogs": "Skrij spodbude od @{name}", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index 7a17e9134..d7be7380f 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -16,7 +16,7 @@ "account.followers": "Pratioca", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Prati Vas", "account.hide_reblogs": "Sakrij podrške koje daje korisnika @{name}", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index bcaa45ed0..7c42f0e8a 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -16,7 +16,7 @@ "account.followers": "Пратиоци", "account.followers.empty": "Тренутно нико не прати овог корисника.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Корисник тренутно не прати никога.", "account.follows_you": "Прати Вас", "account.hide_reblogs": "Сакриј подршке које даје корисника @{name}", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index f7fa1a1c6..0389e222d 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -16,7 +16,7 @@ "account.followers": "Följare", "account.followers.empty": "Ingen följer denna användare än.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Denna användare följer inte någon än.", "account.follows_you": "Följer dig", "account.hide_reblogs": "Dölj knuffar från @{name}", diff --git a/app/javascript/mastodon/locales/szl.json b/app/javascript/mastodon/locales/szl.json index 36f55e800..e5d833fe8 100644 --- a/app/javascript/mastodon/locales/szl.json +++ b/app/javascript/mastodon/locales/szl.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json index 9caef0582..28f03f781 100644 --- a/app/javascript/mastodon/locales/ta.json +++ b/app/javascript/mastodon/locales/ta.json @@ -16,7 +16,7 @@ "account.followers": "பின்தொடர்பவர்கள்", "account.followers.empty": "இதுவரை யாரும் இந்த பயனரைப் பின்தொடரவில்லை.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "இந்த பயனர் இதுவரை யாரையும் பின்தொடரவில்லை.", "account.follows_you": "உங்களைப் பின்தொடர்கிறார்", "account.hide_reblogs": "இருந்து ஊக்கியாக மறை @{name}", diff --git a/app/javascript/mastodon/locales/tai.json b/app/javascript/mastodon/locales/tai.json index 36f55e800..e5d833fe8 100644 --- a/app/javascript/mastodon/locales/tai.json +++ b/app/javascript/mastodon/locales/tai.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json index a57efd7c6..4763dcbd3 100644 --- a/app/javascript/mastodon/locales/te.json +++ b/app/javascript/mastodon/locales/te.json @@ -16,7 +16,7 @@ "account.followers": "అనుచరులు", "account.followers.empty": "ఈ వినియోగదారుడిని ఇంకా ఎవరూ అనుసరించడంలేదు.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "ఈ వినియోగదారి ఇంకా ఎవరినీ అనుసరించడంలేదు.", "account.follows_you": "మిమ్మల్ని అనుసరిస్తున్నారు", "account.hide_reblogs": "@{name} నుంచి బూస్ట్ లను దాచిపెట్టు", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 5852ec5ca..a5c6b07cd 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -16,7 +16,7 @@ "account.followers": "ผู้ติดตาม", "account.followers.empty": "ยังไม่มีใครติดตามผู้ใช้นี้", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "ผู้ใช้นี้ยังไม่ได้ติดตามใคร", "account.follows_you": "ติดตามคุณ", "account.hide_reblogs": "ซ่อนการดันจาก @{name}", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index a5bbbfcd9..351e80f81 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -16,7 +16,7 @@ "account.followers": "Takipçi", "account.followers.empty": "Henüz kimse bu kullanıcıyı takip etmiyor.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Bu kullanıcı henüz kimseyi takip etmiyor.", "account.follows_you": "Seni takip ediyor", "account.hide_reblogs": "@{name} kişisinin yinelemelerini gizle", diff --git a/app/javascript/mastodon/locales/ug.json b/app/javascript/mastodon/locales/ug.json index 36f55e800..e5d833fe8 100644 --- a/app/javascript/mastodon/locales/ug.json +++ b/app/javascript/mastodon/locales/ug.json @@ -16,7 +16,7 @@ "account.followers": "Followers", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide boosts from @{name}", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 18e151263..244f04a9e 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -16,7 +16,7 @@ "account.followers": "Підписники", "account.followers.empty": "Ніхто ще не підписався на цього користувача.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Цей користувач ще ні на кого не підписався.", "account.follows_you": "Підписаний(-а) на вас", "account.hide_reblogs": "Сховати передмухи від @{name}", diff --git a/app/javascript/mastodon/locales/ur.json b/app/javascript/mastodon/locales/ur.json index 5924d1487..b94b7c162 100644 --- a/app/javascript/mastodon/locales/ur.json +++ b/app/javascript/mastodon/locales/ur.json @@ -16,7 +16,7 @@ "account.followers": "پیروکار", "account.followers.empty": "\"ہنوز اس صارف کی کوئی پیروی نہیں کرتا\".", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "\"یہ صارف ہنوز کسی کی پیروی نہیں کرتا ہے\".", "account.follows_you": "آپ کا پیروکار ہے", "account.hide_reblogs": "@{name} سے فروغ چھپائیں", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index b537ca4f3..24a63ab6b 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -16,7 +16,7 @@ "account.followers": "關注的人", "account.followers.empty": "尚沒有人關注這位使用者。", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "這位使用者尚未關注任何使用者。", "account.follows_you": "關注你", "account.hide_reblogs": "隱藏 @{name} 的轉推", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index d674734c1..e964ccd49 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -16,7 +16,7 @@ "account.followers": "關注者", "account.followers.empty": "尚沒有人關注這位使用者。", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "這位使用者尚未關注任何使用者。", "account.follows_you": "關注了你", "account.hide_reblogs": "隱藏來自 @{name} 的轉推", diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index 7a846bcc6..8c8d69fc4 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -767,10 +767,3 @@ html { .compose-form .compose-form__warning { box-shadow: none; } - -.audio-player .video-player__controls button, -.audio-player .video-player__time-sep, -.audio-player .video-player__time-current, -.audio-player .video-player__time-total { - color: $primary-text-color; -} diff --git a/app/javascript/styles/mastodon/boost.scss b/app/javascript/styles/mastodon/boost.scss index 5a6d6ae40..a18e69a6a 100644 --- a/app/javascript/styles/mastodon/boost.scss +++ b/app/javascript/styles/mastodon/boost.scss @@ -7,5 +7,5 @@ button.icon-button i.fa-retweet { } button.icon-button.disabled i.fa-retweet { - background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='209'><path d='M4.97 3.16c-.1.03-.17.1-.22.18L.8 8.24c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77L5.5 3.35c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.02-2.4.02H7.1l2.32 2.85.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color(darken($action-button-color, 13%))}' stroke-width='0'/><path d='M7.78 19.66c-.24.02-.44.25-.44.5v2.46h-.06c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v4.47c0 4.26-.56 3.62 3.65 3.62H8.5l-1.3-1.06c-.1-.08-.18-.2-.2-.3-.02-.17.06-.35.2-.45l1.33-1.1H7.28c-.44 0-.72-.3-.72-.7v-4.48c0-.44.28-.72.72-.72h.06v2.5c0 .38.54.63.82.38l4.9-3.93c.25-.18.25-.6 0-.78l-4.9-3.92c-.1-.1-.24-.14-.38-.12zm9.34 2.93c-.54-.02-1.3.02-2.4.02h-1.25l1.3 1.07c.1.07.18.2.2.33.02.16-.06.3-.2.4l-1.33 1.1h1.28c.42 0 .72.28.72.72v4.47c0 .42-.3.72-.72.72h-.1v-2.47c0-.3-.3-.53-.6-.47-.07 0-.14.05-.2.1l-4.9 3.93c-.26.18-.26.6 0 .78l4.9 3.92c.27.25.82 0 .8-.38v-2.5h.1c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.15.4-3.62-1.25-3.66zM10.34 38.66c-.24.02-.44.25-.43.5v2.47H7.3c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.47c0 3.66-.23 3.7 2.34 3.66l-1.34-1.1c-.1-.08-.18-.2-.2-.3 0-.17.07-.35.2-.45l1.96-1.6c-.03-.06-.04-.13-.04-.2v-4.48c0-.44.28-.72.72-.72H9.9v2.5c0 .36.5.6.8.38l4.93-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.08-.23-.13-.36-.12zm5.63 2.93l1.34 1.1c.1.07.18.2.2.33.02.16-.03.3-.16.4l-1.96 1.6c.02.07.06.13.06.22v4.47c0 .42-.3.72-.72.72h-2.66v-2.47c0-.3-.3-.53-.6-.47-.06.02-.12.05-.18.1l-4.94 3.93c-.24.18-.24.6 0 .78l4.94 3.92c.28.22.78-.02.78-.38v-2.5h2.66c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.66.34-3.7-2.4-3.66zM13.06 57.66c-.23.03-.4.26-.4.5v2.47H7.28c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.87l2.93-2.37v-2.5c0-.44.28-.72.72-.72h5.38v2.5c0 .36.5.6.78.38l4.94-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.1-.24-.14-.38-.12zm5.3 6.15l-2.92 2.4v2.52c0 .42-.3.72-.72.72h-5.4v-2.47c0-.3-.32-.53-.6-.47-.07.02-.13.05-.2.1L3.6 70.52c-.25.18-.25.6 0 .78l4.93 3.92c.28.22.78-.02.78-.38v-2.5h5.42c4.27 0 3.65.67 3.65-3.62v-4.47-.44zM19.25 78.8c-.1.03-.2.1-.28.17l-.9.9c-.44-.3-1.36-.25-3.35-.25H7.28c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v.7l2.93.3v-1c0-.44.28-.72.72-.72h7.44c.2 0 .37.08.5.2l-1.8 1.8c-.25.26-.08.76.27.8l6.27.7c.28.03.56-.25.53-.53l-.7-6.25c0-.27-.3-.48-.55-.44zm-17.2 6.1c-.2.07-.36.3-.33.54l.7 6.25c.02.36.58.55.83.27l.8-.8c.02 0 .04-.02.04 0 .46.24 1.37.17 3.18.17h7.44c4.27 0 3.65.67 3.65-3.62v-.75l-2.93-.3v1.05c0 .42-.3.72-.72.72H7.28c-.15 0-.3-.03-.4-.1L8.8 86.4c.3-.24.1-.8-.27-.84l-6.28-.65h-.2zM4.88 98.6c-1.33 0-1.34.48-1.3 2.3l1.14-1.37c.08-.1.22-.17.34-.2.16 0 .34.08.44.2l1.66 2.03c.04 0 .07-.03.12-.03h7.44c.34 0 .57.2.65.5h-2.43c-.34.05-.53.52-.3.78l3.92 4.95c.18.24.6.24.78 0l3.94-4.94c.22-.27-.02-.76-.37-.77H18.4c.02-3.9.6-3.4-3.66-3.4H7.28c-1.08 0-1.86-.04-2.4-.04zm.15 2.46c-.1.03-.2.1-.28.2l-3.94 4.9c-.2.28.03.77.4.78H3.6c-.02 3.94-.45 3.4 3.66 3.4h7.44c3.65 0 3.74.3 3.7-2.25l-1.1 1.34c-.1.1-.2.17-.32.2-.16 0-.34-.08-.44-.2l-1.65-2.03c-.06.02-.1.04-.18.04H7.28c-.35 0-.57-.2-.66-.5h2.44c.37 0 .63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.23-.47-.2zM4.88 117.6c-1.16 0-1.3.3-1.3 1.56l1.14-1.38c.08-.1.22-.14.34-.16.16 0 .34.04.44.16l2.22 2.75h7c.42 0 .72.28.72.72v.53h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-.53c0-4.2.72-3.63-3.66-3.63H7.28c-1.08 0-1.86-.03-2.4-.03zm.1 1.74c-.1.03-.17.1-.23.16L.8 124.44c-.2.28.03.77.4.78H3.6v.5c0 4.26-.55 3.62 3.66 3.62h7.44c1.03 0 1.74.02 2.28 0-.16.02-.34-.03-.44-.15l-2.22-2.76H7.28c-.44 0-.72-.3-.72-.72v-.5h2.5c.37.02.63-.5.4-.78L5.5 119.5c-.12-.15-.34-.22-.53-.16zm12.02 10c1.2-.02 1.4-.25 1.4-1.53l-1.1 1.36c-.07.1-.17.17-.3.18zM5.94 136.6l2.37 2.93h6.42c.42 0 .72.28.72.72v1.25h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.25c0-4.2.72-3.63-3.66-3.63H7.28c-.6 0-.92-.02-1.34-.03zm-1.72.06c-.4.08-.54.3-.6.75l.6-.74zm.84.93c-.12 0-.24.08-.3.18l-3.95 4.9c-.24.3 0 .83.4.82H3.6v1.22c0 4.26-.55 3.62 3.66 3.62h7.44c.63 0 .97.02 1.4.03l-2.37-2.93H7.28c-.44 0-.72-.3-.72-.72v-1.22h2.5c.4.04.67-.53.4-.8l-3.96-4.92c-.1-.13-.27-.2-.44-.2zm13.28 10.03l-.56.7c.36-.07.5-.3.56-.7zM17.13 155.6c-.55-.02-1.32.03-2.4.03h-8.2l2.38 2.9h5.82c.42 0 .72.28.72.72v1.97H12.9c-.32.06-.48.52-.28.78l3.94 4.94c.2.23.6.22.78-.03l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.97c0-3.15.4-3.62-1.25-3.66zm-12.1.28c-.1.02-.2.1-.28.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v1.96c0 4.26-.55 3.62 3.66 3.62h8.24l-2.36-2.9H7.28c-.44 0-.72-.3-.72-.72v-1.97h2.5c.37.02.63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.22-.47-.2zM5.13 174.5c-.15 0-.3.07-.38.2L.8 179.6c-.24.27 0 .82.4.8H3.6v2.32c0 4.26-.55 3.62 3.66 3.62h7.94l-2.35-2.9h-5.6c-.43 0-.7-.3-.7-.72v-2.3h2.5c.38.03.66-.54.4-.83l-3.97-4.9c-.1-.13-.23-.2-.38-.2zm12 .1c-.55-.02-1.32.03-2.4.03H6.83l2.35 2.9h5.52c.42 0 .72.28.72.72v2.34h-2.6c-.3.1-.43.53-.2.78l3.92 4.9c.18.24.6.24.78 0l3.94-4.9c.22-.3-.02-.78-.37-.8H18.4v-2.33c0-3.15.4-3.62-1.25-3.66zM4.97 193.16c-.1.03-.17.1-.22.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77l-3.96-4.9c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.03-2.4.03H7.1l2.32 2.84.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color($highlight-text-color)}' stroke-width='0'/></svg>"); + background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' height='209' width='22'><path d='M 18.972656 1.2011719 C 18.829825 1.1881782 18.685932 1.2302188 18.572266 1.3300781 L 15.990234 3.5996094 C 15.58109 3.6070661 15.297269 3.609375 14.730469 3.609375 L 7.0996094 3.609375 L 9.4199219 6.4609375 L 9.4492188 6.5195312 L 12.664062 6.5195312 L 6.5761719 11.867188 C 6.5674697 11.818249 6.5507813 11.773891 6.5507812 11.720703 L 6.5507812 9.0195312 L 9.0507812 9.0195312 C 9.4207813 9.0495313 9.6792188 8.54 9.4492188 8.25 L 5.5 3.3496094 C 5.38 3.1796094 5.1607031 3.1003906 4.9707031 3.1503906 L 4.9707031 3.1601562 C 4.8707031 3.1901563 4.8 3.2598438 4.75 3.3398438 L 0.80078125 8.2402344 C 0.60078125 8.5402344 0.8292187 9.0190625 1.1992188 9.0390625 L 3.5996094 9.0390625 L 3.5996094 11.720703 C 3.5996094 13.045739 3.5690668 13.895038 3.6503906 14.4375 L 2.6152344 15.347656 C 2.3879011 15.547375 2.3754917 15.901081 2.5859375 16.140625 L 3.1464844 16.78125 C 3.3569308 17.020794 3.7101667 17.053234 3.9375 16.853516 L 19.892578 2.8359375 C 20.119911 2.6362188 20.134275 2.282513 19.923828 2.0429688 L 19.361328 1.4023438 C 19.256105 1.282572 19.115488 1.2141655 18.972656 1.2011719 z M 18.410156 6.7753906 L 15.419922 9.4042969 L 15.419922 9.9394531 L 14.810547 9.9394531 L 13.148438 11.400391 L 16.539062 15.640625 C 16.719062 15.890625 17.140313 15.890625 17.320312 15.640625 L 21.259766 10.740234 C 21.519766 10.460234 21.260625 9.9094531 20.890625 9.9394531 L 18.400391 9.9394531 L 18.400391 7.2402344 C 18.400391 7.0470074 18.407711 6.9489682 18.410156 6.7753906 z M 11.966797 12.439453 L 8.6679688 15.339844 L 14.919922 15.339844 L 12.619141 12.5 C 12.589141 12.48 12.590313 12.459453 12.570312 12.439453 L 11.966797 12.439453 z' fill='#{hex-color(darken($action-button-color, 13%))}' stroke-width='0'/></svg>"); } diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index b20db2224..f6deadffa 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -2990,7 +2990,7 @@ a.account__display-name { } } -.no-reduce-motion button.icon-button i.fa-retweet { +button.icon-button i.fa-retweet { background-position: 0 0; height: 19px; transition: background-position 0.9s steps(10); @@ -3004,18 +3004,14 @@ a.account__display-name { } -.no-reduce-motion button.icon-button.active i.fa-retweet { +button.icon-button.active i.fa-retweet { transition-duration: 0.9s; background-position: 0 100%; } -.reduce-motion button.icon-button i.fa-retweet { - color: $action-button-color; - transition: color 100ms ease-in; -} - +.reduce-motion button.icon-button i.fa-retweet, .reduce-motion button.icon-button.active i.fa-retweet { - color: $highlight-text-color; + transition: none; } .status-card { diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 0ce279d28..ab946470b 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -157,6 +157,34 @@ class ActivityPub::Activity fetch_remote_original_status end + def dereference_object! + return unless @object.is_a?(String) + return if invalid_origin?(@object) + + object = fetch_resource(@object, true, signed_fetch_account) + return unless object.present? && object.is_a?(Hash) && supported_context?(object) + + @object = object + end + + def signed_fetch_account + first_mentioned_local_account || first_local_follower + end + + def first_mentioned_local_account + audience = (as_array(@json['to']) + as_array(@json['cc'])).uniq + local_usernames = audience.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) } + .map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) } + + return if local_usernames.empty? + + Account.local.where(username: local_usernames).first + end + + def first_local_follower + @account.followers.local.first + end + def follow_request_from_object @follow_request ||= FollowRequest.find_by(target_account: @account, uri: object_uri) unless object_uri.nil? end diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index 34c646668..9e108985a 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -4,25 +4,32 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity def perform return reject_payload! if delete_arrived_first?(@json['id']) || !related_to_local_activity? - original_status = status_from_object + RedisLock.acquire(lock_options) do |lock| + if lock.acquired? + original_status = status_from_object - return reject_payload! if original_status.nil? || !announceable?(original_status) + return reject_payload! if original_status.nil? || !announceable?(original_status) - status = Status.find_by(account: @account, reblog: original_status) + @status = Status.find_by(account: @account, reblog: original_status) - return status unless status.nil? + return @status unless @status.nil? - status = Status.create!( - account: @account, - reblog: original_status, - uri: @json['id'], - created_at: @json['published'], - override_timestamps: @options[:override_timestamps], - visibility: visibility_from_audience - ) + @status = Status.create!( + account: @account, + reblog: original_status, + uri: @json['id'], + created_at: @json['published'], + override_timestamps: @options[:override_timestamps], + visibility: visibility_from_audience + ) - distribute(status) - status + distribute(@status) + else + raise Mastodon::RaceConditionError + end + end + + @status end private @@ -54,4 +61,8 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity def reblog_of_local_status? status_from_uri(object_uri)&.account&.local? end + + def lock_options + { redis: Redis.current, key: "announce:#{@object['id']}" } + end end diff --git a/app/lib/activitypub/activity/block.rb b/app/lib/activitypub/activity/block.rb index a17a2d50a..90477bf33 100644 --- a/app/lib/activitypub/activity/block.rb +++ b/app/lib/activitypub/activity/block.rb @@ -4,7 +4,12 @@ class ActivityPub::Activity::Block < ActivityPub::Activity def perform target_account = account_from_uri(object_uri) - return if target_account.nil? || !target_account.local? || @account.blocking?(target_account) + return if target_account.nil? || !target_account.local? + + if @account.blocking?(target_account) + @account.block_relationships.find_by(target_account: target_account).update(uri: @json['id']) if @json['id'].present? + return + end UnfollowService.new.call(target_account, @account) if target_account.following?(@account) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index e81452e3c..08dd98e94 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -2,6 +2,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def perform + dereference_object! + case @object['type'] when 'EncryptedMessage' create_encrypted_message diff --git a/app/lib/activitypub/activity/undo.rb b/app/lib/activitypub/activity/undo.rb index 599823c6e..9eff1b71c 100644 --- a/app/lib/activitypub/activity/undo.rb +++ b/app/lib/activitypub/activity/undo.rb @@ -13,11 +13,62 @@ class ActivityPub::Activity::Undo < ActivityPub::Activity undo_like when 'Block' undo_block + when nil + handle_reference end end private + def handle_reference + # Some implementations do not inline the object, and as we don't have a + # global index, we have to guess what object it is. + return if object_uri.nil? + + try_undo_announce || try_undo_accept || try_undo_follow || try_undo_like || try_undo_block || delete_later!(object_uri) + end + + def try_undo_announce + status = Status.where.not(reblog_of_id: nil).find_by(uri: object_uri, account: @account) + if status.present? + RemoveStatusService.new.call(status) + true + else + false + end + end + + def try_undo_accept + # We can't currently handle `Undo Accept` as we don't record `Accept`'s uri + false + end + + def try_undo_follow + follow = @account.follow_requests.find_by(uri: object_uri) || @account.active_relationships.find_by(uri: object_uri) + + if follow.present? + follow.destroy + true + else + false + end + end + + def try_undo_like + # There is an index on accounts, but an account may have *many* favs, so this may be too costly + false + end + + def try_undo_block + block = @account.block_relationships.find_by(uri: object_uri) + if block.present? + UnblockService.new.call(@account, block.target_account) + true + else + false + end + end + def undo_announce return if object_uri.nil? diff --git a/app/lib/activitypub/activity/update.rb b/app/lib/activitypub/activity/update.rb index 70035325b..018e2df54 100644 --- a/app/lib/activitypub/activity/update.rb +++ b/app/lib/activitypub/activity/update.rb @@ -4,6 +4,8 @@ class ActivityPub::Activity::Update < ActivityPub::Activity SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze def perform + dereference_object! + if equals_or_includes_any?(@object['type'], SUPPORTED_TYPES) update_account elsif equals_or_includes_any?(@object['type'], %w(Question)) diff --git a/app/lib/exceptions.rb b/app/lib/exceptions.rb index 3362576b0..7c8e77871 100644 --- a/app/lib/exceptions.rb +++ b/app/lib/exceptions.rb @@ -7,6 +7,7 @@ module Mastodon class HostValidationError < ValidationError; end class LengthValidationError < ValidationError; end class DimensionsValidationError < ValidationError; end + class StreamValidationError < ValidationError; end class RaceConditionError < Error; end class RateLimitExceededError < Error; end diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 6afdd3b08..2dc60092c 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -139,9 +139,15 @@ class FeedManager end def clear_from_timeline(account, target_account) + # Clear from timeline all statuses from or mentionning target_account timeline_key = key(:home, account.id) timeline_status_ids = redis.zrange(timeline_key, 0, -1) - target_statuses = Status.where(id: timeline_status_ids, account: target_account) + statuses = Status.where(id: timeline_status_ids).select(:id, :reblog_of_id, :account_id).to_a + reblogged_ids = Status.where(id: statuses.map(&:reblog_of_id).compact, account: target_account).pluck(:id) + with_mentions_ids = Mention.active.where(status_id: statuses.flat_map { |s| [s.id, s.reblog_of_id] }.compact, account: target_account).pluck(:status_id) + target_statuses = statuses.filter do |status| + status.account_id == target_account.id || reblogged_ids.include?(status.reblog_of_id) || with_mentions_ids.include?(status.id) || with_mentions_ids.include?(status.reblog_of_id) + end target_statuses.each do |status| unpush_from_home(account, status) diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb index c6d0c7f1f..56b9c0164 100644 --- a/app/models/concerns/remotable.rb +++ b/app/models/concerns/remotable.rb @@ -29,7 +29,7 @@ module Remotable rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError => e Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}" raise e unless suppress_errors - rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError => e + rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => e Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}" end diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 0441fc699..cfdd95b22 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -336,6 +336,7 @@ class MediaAttachment < ApplicationRecord return unless movie.valid? + raise Mastodon::StreamValidationError, 'Video has no video stream' if movie.width.nil? || movie.frame_rate.nil? raise Mastodon::DimensionsValidationError, "#{movie.width}x#{movie.height} videos are not supported" if movie.width * movie.height > MAX_VIDEO_MATRIX_LIMIT raise Mastodon::DimensionsValidationError, "#{movie.frame_rate.to_i}fps videos are not supported" if movie.frame_rate > MAX_VIDEO_FRAME_RATE end diff --git a/app/serializers/rest/media_attachment_serializer.rb b/app/serializers/rest/media_attachment_serializer.rb index e65f7acf1..a24f95315 100644 --- a/app/serializers/rest/media_attachment_serializer.rb +++ b/app/serializers/rest/media_attachment_serializer.rb @@ -4,7 +4,7 @@ class REST::MediaAttachmentSerializer < ActiveModel::Serializer include RoutingHelper attributes :id, :type, :url, :preview_url, - :remote_url, :text_url, :meta, + :remote_url, :preview_remote_url, :text_url, :meta, :description, :blurhash def id @@ -35,6 +35,10 @@ class REST::MediaAttachmentSerializer < ActiveModel::Serializer end end + def preview_remote_url + object.thumbnail_remote_url.presence + end + def text_url object.local? ? medium_url(object) : nil end diff --git a/app/services/update_account_service.rb b/app/services/update_account_service.rb index 4172d5774..666db5c71 100644 --- a/app/services/update_account_service.rb +++ b/app/services/update_account_service.rb @@ -12,7 +12,7 @@ class UpdateAccountService < BaseService check_links(account) process_hashtags(account) end - rescue Mastodon::DimensionsValidationError => de + rescue Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => de account.errors.add(:avatar, de.message) false end diff --git a/app/workers/activitypub/processing_worker.rb b/app/workers/activitypub/processing_worker.rb index 05139f616..cef595319 100644 --- a/app/workers/activitypub/processing_worker.rb +++ b/app/workers/activitypub/processing_worker.rb @@ -3,7 +3,7 @@ class ActivityPub::ProcessingWorker include Sidekiq::Worker - sidekiq_options backtrace: true + sidekiq_options backtrace: true, retry: 8 def perform(account_id, body, delivered_to_account_id = nil) ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true, delivered_to_account_id: delivered_to_account_id, delivery: true) diff --git a/chart/values.yaml.template b/chart/values.yaml.template index 4a8286d00..694bc4d42 100644 --- a/chart/values.yaml.template +++ b/chart/values.yaml.template @@ -16,6 +16,12 @@ ingress: kubernetes.io/ingress.class: nginx kubernetes.io/tls-acme: "true" # cert-manager.io/cluster-issuer: "letsencrypt" + # + # ensure that NGINX's upload size matches Mastodon's + # for the K8s ingress controller: + # nginx.ingress.kubernetes.io/proxy-body-size: 40m + # for the NGINX ingress controller: + # nginx.org/client-max-body-size: 40m # this value is used for LOCAL_DOMAIN hostname: mastodon.local tls: diff --git a/lib/paperclip/media_type_spoof_detector_extensions.rb b/lib/paperclip/media_type_spoof_detector_extensions.rb index 363934d8d..43337cc68 100644 --- a/lib/paperclip/media_type_spoof_detector_extensions.rb +++ b/lib/paperclip/media_type_spoof_detector_extensions.rb @@ -18,7 +18,7 @@ module Paperclip @type_from_mime_magic ||= begin begin File.open(@file.path) do |file| - MimeMagic.by_magic(file)&.type + MimeMagic.by_magic(file)&.type || '' end rescue Errno::ENOENT '' diff --git a/package.json b/package.json index 5aea0e69c..bea3fc6ea 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "intl-relativeformat": "^6.4.3", "is-nan": "^1.3.0", "js-yaml": "^3.13.1", - "lodash": "^4.17.14", + "lodash": "^4.17.19", "mark-loader": "^0.1.6", "marky": "^1.2.1", "mini-css-extract-plugin": "^0.9.0", diff --git a/spec/controllers/accounts_controller_spec.rb b/spec/controllers/accounts_controller_spec.rb index bd36f5494..93bf2c83f 100644 --- a/spec/controllers/accounts_controller_spec.rb +++ b/spec/controllers/accounts_controller_spec.rb @@ -5,6 +5,21 @@ RSpec.describe AccountsController, type: :controller do let(:account) { Fabricate(:user).account } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + describe 'GET #show' do let(:format) { 'html' } @@ -323,9 +338,7 @@ RSpec.describe AccountsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'renders account' do json = body_as_json @@ -343,9 +356,7 @@ RSpec.describe AccountsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns Vary header with Signature' do expect(response.headers['Vary']).to include 'Signature' @@ -401,9 +412,7 @@ RSpec.describe AccountsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'renders account' do json = body_as_json @@ -447,9 +456,7 @@ RSpec.describe AccountsController, type: :controller do expect(response).to have_http_status(200) end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' end context do diff --git a/spec/controllers/activitypub/collections_controller_spec.rb b/spec/controllers/activitypub/collections_controller_spec.rb index 56be49be3..89939d1d2 100644 --- a/spec/controllers/activitypub/collections_controller_spec.rb +++ b/spec/controllers/activitypub/collections_controller_spec.rb @@ -6,6 +6,21 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do let!(:account) { Fabricate(:account) } let(:remote_account) { nil } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + before do allow(controller).to receive(:signed_request_account).and_return(remote_account) @@ -31,9 +46,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns orderedItems with pinned statuses' do json = body_as_json @@ -58,9 +71,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns orderedItems with pinned statuses' do json = body_as_json diff --git a/spec/controllers/activitypub/outboxes_controller_spec.rb b/spec/controllers/activitypub/outboxes_controller_spec.rb index 03490533d..1baf5a623 100644 --- a/spec/controllers/activitypub/outboxes_controller_spec.rb +++ b/spec/controllers/activitypub/outboxes_controller_spec.rb @@ -3,6 +3,21 @@ require 'rails_helper' RSpec.describe ActivityPub::OutboxesController, type: :controller do let!(:account) { Fabricate(:account) } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + before do Fabricate(:status, account: account, visibility: :public) Fabricate(:status, account: account, visibility: :unlisted) @@ -39,9 +54,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do expect(json[:totalItems]).to eq 4 end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' end context 'with page requested' do @@ -62,9 +75,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do expect(json[:orderedItems].all? { |item| item[:to].include?(ActivityPub::TagManager::COLLECTIONS[:public]) || item[:cc].include?(ActivityPub::TagManager::COLLECTIONS[:public]) }).to be true end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' end end diff --git a/spec/controllers/activitypub/replies_controller_spec.rb b/spec/controllers/activitypub/replies_controller_spec.rb index d956e1b35..ed383864d 100644 --- a/spec/controllers/activitypub/replies_controller_spec.rb +++ b/spec/controllers/activitypub/replies_controller_spec.rb @@ -7,6 +7,21 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do let(:remote_reply_id) { nil } let(:remote_account) { nil } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + before do allow(controller).to receive(:signed_request_account).and_return(remote_account) @@ -36,9 +51,7 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns items with account\'s own replies' do json = body_as_json @@ -87,9 +100,7 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' context 'without only_other_accounts' do it 'returns items with account\'s own replies' do diff --git a/spec/controllers/statuses_controller_spec.rb b/spec/controllers/statuses_controller_spec.rb index ba1f1370a..cd6e1e607 100644 --- a/spec/controllers/statuses_controller_spec.rb +++ b/spec/controllers/statuses_controller_spec.rb @@ -5,6 +5,21 @@ require 'rails_helper' describe StatusesController do render_views + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + describe 'GET #show' do let(:account) { Fabricate(:account) } let(:status) { Fabricate(:status, account: account) } @@ -80,9 +95,7 @@ describe StatusesController do expect(response.headers['Vary']).to eq 'Accept' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns Content-Type header' do expect(response.headers['Content-Type']).to include 'application/activity+json' @@ -470,9 +483,7 @@ describe StatusesController do expect(response.headers['Vary']).to eq 'Accept' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns Content-Type header' do expect(response.headers['Content-Type']).to include 'application/activity+json' diff --git a/spec/lib/activitypub/activity/block_spec.rb b/spec/lib/activitypub/activity/block_spec.rb index 94d37356d..42bdfdc81 100644 --- a/spec/lib/activitypub/activity/block_spec.rb +++ b/spec/lib/activitypub/activity/block_spec.rb @@ -28,6 +28,28 @@ RSpec.describe ActivityPub::Activity::Block do end end + context 'when the recipient is already blocked' do + before do + sender.block!(recipient, uri: 'old') + end + + describe '#perform' do + subject { described_class.new(json, sender) } + + before do + subject.perform + end + + it 'creates a block from sender to recipient' do + expect(sender.blocking?(recipient)).to be true + end + + it 'sets the uri to that of last received block activity' do + expect(sender.block_relationships.find_by(target_account: recipient).uri).to eq 'foo' + end + end + end + context 'when the recipient follows the sender' do before do recipient.follow!(sender) diff --git a/spec/lib/activitypub/activity/undo_spec.rb b/spec/lib/activitypub/activity/undo_spec.rb index 9545e1f46..c0309e49d 100644 --- a/spec/lib/activitypub/activity/undo_spec.rb +++ b/spec/lib/activitypub/activity/undo_spec.rb @@ -50,6 +50,19 @@ RSpec.describe ActivityPub::Activity::Undo do expect(sender.reblogged?(status)).to be false end end + + context 'with only object uri' do + let(:object_json) { 'bar' } + + before do + Fabricate(:status, reblog: status, account: sender, uri: 'bar') + end + + it 'deletes the reblog by uri' do + subject.perform + expect(sender.reblogged?(status)).to be false + end + end end context 'with Accept' do @@ -91,13 +104,22 @@ RSpec.describe ActivityPub::Activity::Undo do end before do - sender.block!(recipient) + sender.block!(recipient, uri: 'bar') end it 'deletes block from sender to recipient' do subject.perform expect(sender.blocking?(recipient)).to be false end + + context 'with only object uri' do + let(:object_json) { 'bar' } + + it 'deletes block from sender to recipient' do + subject.perform + expect(sender.blocking?(recipient)).to be false + end + end end context 'with Follow' do @@ -113,13 +135,22 @@ RSpec.describe ActivityPub::Activity::Undo do end before do - sender.follow!(recipient) + sender.follow!(recipient, uri: 'bar') end it 'deletes follow from sender to recipient' do subject.perform expect(sender.following?(recipient)).to be false end + + context 'with only object uri' do + let(:object_json) { 'bar' } + + it 'deletes follow from sender to recipient' do + subject.perform + expect(sender.following?(recipient)).to be false + end + end end context 'with Like' do diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index 705e577a6..40e8214b6 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -531,4 +531,29 @@ RSpec.describe FeedManager do expect(Redis.current).to have_received(:publish).with("timeline:#{receiver.id}", deletion) end end + + describe '#clear_from_timeline' do + let(:account) { Fabricate(:account) } + let(:followed_account) { Fabricate(:account) } + let(:target_account) { Fabricate(:account) } + let(:status_1) { Fabricate(:status, account: followed_account) } + let(:status_2) { Fabricate(:status, account: target_account) } + let(:status_3) { Fabricate(:status, account: followed_account, mentions: [Fabricate(:mention, account: target_account)]) } + let(:status_4) { Fabricate(:status, mentions: [Fabricate(:mention, account: target_account)]) } + let(:status_5) { Fabricate(:status, account: followed_account, reblog: status_4) } + let(:status_6) { Fabricate(:status, account: followed_account, reblog: status_2) } + let(:status_7) { Fabricate(:status, account: followed_account) } + + before do + [status_1, status_3, status_5, status_6, status_7].each do |status| + Redis.current.zadd("feed:home:#{account.id}", status.id, status.id) + end + end + + it 'correctly cleans the timeline' do + FeedManager.instance.clear_from_timeline(account, target_account) + + expect(Redis.current.zrange("feed:home:#{account.id}", 0, -1)).to eq [status_1.id.to_s, status_7.id.to_s] + end + end end diff --git a/yarn.lock b/yarn.lock index 89f53f62c..2c51161d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6979,10 +6979,10 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.3.0, lodash@~4.17.12: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.3.0, lodash@~4.17.12: + version "4.17.19" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" + integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== loglevel@^1.6.8: version "1.6.8" |