Merge branch 'master' into glitch-soc/merge-upstream

Conflicts:
- `app/javascript/mastodon/actions/compose.js`:
  Not a “real” conflict, but change too close to a change we made to
  fix the vanilla WebUI locally pushing authored local-only toots in the
  public TL view.
This commit is contained in:
Thibaut Girka
2020-07-22 13:38:17 +02:00
90 changed files with 414 additions and 144 deletions

View File

@@ -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

View File

@@ -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!

View File

@@ -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));

View File

@@ -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));

View File

@@ -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}`);

View File

@@ -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),

View File

@@ -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 = {

View File

@@ -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 }));
}

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}'র সমর্থনগুলি লুকিয়ে ফেলুন",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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"
},
{
@@ -2659,6 +2659,22 @@
"defaultMessage": "Boost",
"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"

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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} के बूस्ट छुपाएं",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}-სგან",

View File

@@ -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}",

View File

@@ -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} атты қолданушының әрекеттерін жасыру",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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} ബൂസ്റ്റ് ചെയ്തവ മറയ്കുക",

View File

@@ -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} पासून सर्व बूस्ट लपवा",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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} నుంచి బూస్ట్ లను దాచిపెట్టు",

View File

@@ -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}",

View File

@@ -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",

View File

@@ -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}",

View File

@@ -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}",

View File

@@ -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} سے فروغ چھپائیں",

View File

@@ -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} 的轉推",

View File

@@ -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} 的轉推",

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -2,6 +2,8 @@
class ActivityPub::Activity::Create < ActivityPub::Activity
def perform
dereference_object!
case @object['type']
when 'EncryptedMessage'
create_encrypted_message

View File

@@ -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?

View File

@@ -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))

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)