mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-17 18:18:07 +00:00
Merge commit 'f16f8b51b863d3fcadd17753004adbf8962ead01' into glitch-soc/merge-upstream
Conflicts: - `yarn.lock`: Upstream updated a dependency adjacent to one that is only in glitch-soc. Updated as upstream did.
This commit is contained in:
35
Dockerfile
35
Dockerfile
@@ -17,11 +17,11 @@ ARG RUBY_VERSION="3.4.5"
|
||||
# # Node.js version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
|
||||
# renovate: datasource=node-version depName=node
|
||||
ARG NODE_MAJOR_VERSION="22"
|
||||
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
|
||||
ARG DEBIAN_VERSION="bookworm"
|
||||
# Node.js image to use for base image based on combined variables (ex: 20-bookworm-slim)
|
||||
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="trixie"]
|
||||
ARG DEBIAN_VERSION="trixie"
|
||||
# Node.js image to use for base image based on combined variables (ex: 20-trixie-slim)
|
||||
FROM ${BASE_REGISTRY}/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node
|
||||
# Ruby image to use for base image based on combined variables (ex: 3.4.x-slim-bookworm)
|
||||
# Ruby image to use for base image based on combined variables (ex: 3.4.x-slim-trixie)
|
||||
FROM ${BASE_REGISTRY}/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby
|
||||
|
||||
# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
|
||||
@@ -96,9 +96,6 @@ RUN \
|
||||
# Set /opt/mastodon as working directory
|
||||
WORKDIR /opt/mastodon
|
||||
|
||||
# Add backport repository for some specific packages where we need the latest version
|
||||
RUN echo 'deb http://deb.debian.org/debian bookworm-backports main' >> /etc/apt/sources.list
|
||||
|
||||
# hadolint ignore=DL3008,DL3005
|
||||
RUN \
|
||||
# Mount Apt cache and lib directories from Docker buildx caches
|
||||
@@ -161,11 +158,11 @@ RUN \
|
||||
libexif-dev \
|
||||
libexpat1-dev \
|
||||
libgirepository1.0-dev \
|
||||
libheif-dev/bookworm-backports \
|
||||
libheif-dev \
|
||||
libhwy-dev \
|
||||
libimagequant-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
liblcms2-dev \
|
||||
liborc-dev \
|
||||
libspng-dev \
|
||||
libtiff-dev \
|
||||
libwebp-dev \
|
||||
@@ -209,7 +206,7 @@ FROM build AS ffmpeg
|
||||
|
||||
# ffmpeg version to compile, change with [--build-arg FFMPEG_VERSION="7.0.x"]
|
||||
# renovate: datasource=repology depName=ffmpeg packageName=openpkg_current/ffmpeg
|
||||
ARG FFMPEG_VERSION=7.1
|
||||
ARG FFMPEG_VERSION=7.1.1
|
||||
# ffmpeg download URL, change with [--build-arg FFMPEG_URL="https://ffmpeg.org/releases"]
|
||||
ARG FFMPEG_URL=https://ffmpeg.org/releases
|
||||
|
||||
@@ -327,28 +324,28 @@ RUN \
|
||||
# Apt update install non-dev versions of necessary components
|
||||
apt-get install -y --no-install-recommends \
|
||||
libexpat1 \
|
||||
libglib2.0-0 \
|
||||
libicu72 \
|
||||
libglib2.0-0t64 \
|
||||
libicu76 \
|
||||
libidn12 \
|
||||
libpq5 \
|
||||
libreadline8 \
|
||||
libssl3 \
|
||||
libreadline8t64 \
|
||||
libssl3t64 \
|
||||
libyaml-0-2 \
|
||||
# libvips components
|
||||
libcgif0 \
|
||||
libexif12 \
|
||||
libheif1/bookworm-backports \
|
||||
libheif1 \
|
||||
libhwy1t64 \
|
||||
libimagequant0 \
|
||||
libjpeg62-turbo \
|
||||
liblcms2-2 \
|
||||
liborc-0.4-0 \
|
||||
libspng0 \
|
||||
libtiff6 \
|
||||
libwebp7 \
|
||||
libwebpdemux2 \
|
||||
libwebpmux3 \
|
||||
# ffmpeg components
|
||||
libdav1d6 \
|
||||
libdav1d7 \
|
||||
libmp3lame0 \
|
||||
libopencore-amrnb0 \
|
||||
libopencore-amrwb0 \
|
||||
@@ -358,9 +355,9 @@ RUN \
|
||||
libvorbis0a \
|
||||
libvorbisenc2 \
|
||||
libvorbisfile3 \
|
||||
libvpx7 \
|
||||
libvpx9 \
|
||||
libx264-164 \
|
||||
libx265-199 \
|
||||
libx265-215 \
|
||||
;
|
||||
|
||||
# Copy Mastodon sources into final layer
|
||||
|
||||
2
Gemfile
2
Gemfile
@@ -102,7 +102,7 @@ gem 'rdf-normalize', '~> 0.5'
|
||||
|
||||
gem 'prometheus_exporter', '~> 2.2', require: false
|
||||
|
||||
gem 'opentelemetry-api', '~> 1.5.0'
|
||||
gem 'opentelemetry-api', '~> 1.6.0'
|
||||
|
||||
group :opentelemetry do
|
||||
gem 'opentelemetry-exporter-otlp', '~> 0.30.0', require: false
|
||||
|
||||
@@ -497,7 +497,7 @@ GEM
|
||||
openssl (3.3.0)
|
||||
openssl-signature_algorithm (1.3.0)
|
||||
openssl (> 2.0)
|
||||
opentelemetry-api (1.5.0)
|
||||
opentelemetry-api (1.6.0)
|
||||
opentelemetry-common (0.22.0)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-exporter-otlp (0.30.0)
|
||||
@@ -589,7 +589,7 @@ GEM
|
||||
opentelemetry-instrumentation-base (~> 0.23.0)
|
||||
opentelemetry-registry (0.4.0)
|
||||
opentelemetry-api (~> 1.1)
|
||||
opentelemetry-sdk (1.8.0)
|
||||
opentelemetry-sdk (1.8.1)
|
||||
opentelemetry-api (~> 1.1)
|
||||
opentelemetry-common (~> 0.20)
|
||||
opentelemetry-registry (~> 0.2)
|
||||
@@ -625,7 +625,7 @@ GEM
|
||||
premailer (~> 1.7, >= 1.7.9)
|
||||
prettyprint (0.2.0)
|
||||
prism (1.4.0)
|
||||
prometheus_exporter (2.2.0)
|
||||
prometheus_exporter (2.3.0)
|
||||
webrick
|
||||
propshaft (1.2.1)
|
||||
actionpack (>= 7.0.0)
|
||||
@@ -1025,7 +1025,7 @@ DEPENDENCIES
|
||||
omniauth-rails_csrf_protection (~> 1.0)
|
||||
omniauth-saml (~> 2.0)
|
||||
omniauth_openid_connect (~> 0.8.0)
|
||||
opentelemetry-api (~> 1.5.0)
|
||||
opentelemetry-api (~> 1.6.0)
|
||||
opentelemetry-exporter-otlp (~> 0.30.0)
|
||||
opentelemetry-instrumentation-active_job (~> 0.8.0)
|
||||
opentelemetry-instrumentation-active_model_serializers (~> 0.22.0)
|
||||
|
||||
@@ -53,6 +53,7 @@ const AutosuggestTextarea = forwardRef(({
|
||||
onFocus,
|
||||
autoFocus = true,
|
||||
lang,
|
||||
className,
|
||||
}, textareaRef) => {
|
||||
|
||||
const [suggestionsHidden, setSuggestionsHidden] = useState(true);
|
||||
@@ -192,7 +193,7 @@ const AutosuggestTextarea = forwardRef(({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='autosuggest-textarea'>
|
||||
<div className={classNames('autosuggest-textarea', className)}>
|
||||
<Textarea
|
||||
ref={textareaRef}
|
||||
className='autosuggest-textarea__textarea'
|
||||
|
||||
@@ -10,6 +10,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
|
||||
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
|
||||
import CancelFillIcon from '@/material-icons/400-24px/cancel-fill.svg?react';
|
||||
import { Hotkeys } from 'mastodon/components/hotkeys';
|
||||
import { ContentWarning } from 'mastodon/components/content_warning';
|
||||
import { FilterWarning } from 'mastodon/components/filter_warning';
|
||||
@@ -34,6 +35,8 @@ import StatusActionBar from './status_action_bar';
|
||||
import StatusContent from './status_content';
|
||||
import { StatusThreadLabel } from './status_thread_label';
|
||||
import { VisibilityIcon } from './visibility_icon';
|
||||
import { IconButton } from './icon_button';
|
||||
|
||||
const domParser = new DOMParser();
|
||||
|
||||
export const textForScreenReader = (intl, status, rebloggedByText = false) => {
|
||||
@@ -75,6 +78,7 @@ const messages = defineMessages({
|
||||
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers' },
|
||||
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Specific people' },
|
||||
edited: { id: 'status.edited', defaultMessage: 'Edited {date}' },
|
||||
quote_cancel: { id: 'status.quote.cancel', defaultMessage: 'Cancel quote' },
|
||||
});
|
||||
|
||||
class Status extends ImmutablePureComponent {
|
||||
@@ -126,6 +130,7 @@ class Status extends ImmutablePureComponent {
|
||||
inUse: PropTypes.bool,
|
||||
available: PropTypes.bool,
|
||||
}),
|
||||
contextType: PropTypes.string,
|
||||
...WithOptionalRouterPropTypes,
|
||||
};
|
||||
|
||||
@@ -359,6 +364,10 @@ class Status extends ImmutablePureComponent {
|
||||
this.setState(state => ({ ...state, showDespiteFilter: !state.showDespiteFilter }));
|
||||
};
|
||||
|
||||
handleQuoteCancel = () => {
|
||||
this.props.onQuoteCancel?.();
|
||||
}
|
||||
|
||||
_properStatus () {
|
||||
const { status } = this.props;
|
||||
|
||||
@@ -573,6 +582,16 @@ class Status extends ImmutablePureComponent {
|
||||
|
||||
<DisplayName account={status.get('account')} />
|
||||
</Link>
|
||||
|
||||
{this.props.contextType === 'compose' && isQuotedPost && (
|
||||
<IconButton
|
||||
onClick={this.handleQuoteCancel}
|
||||
className='status__quote-cancel'
|
||||
title={intl.formatMessage(messages.quote_cancel)}
|
||||
icon="cancel-fill"
|
||||
iconComponent={CancelFillIcon}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{matchedFilters && <FilterWarning title={matchedFilters.join(', ')} expanded={this.state.showDespiteFilter} onClick={this.handleFilterToggle} />}
|
||||
|
||||
@@ -44,6 +44,7 @@ import {
|
||||
import Status from '../components/status';
|
||||
import { deleteModal } from '../initial_state';
|
||||
import { makeGetStatus, makeGetPictureInPicture } from '../selectors';
|
||||
import { quoteComposeCancel } from '../actions/compose_typed';
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getStatus = makeGetStatus();
|
||||
@@ -111,6 +112,12 @@ const mapDispatchToProps = (dispatch, { contextType }) => ({
|
||||
}
|
||||
},
|
||||
|
||||
onQuoteCancel() {
|
||||
if (contextType === 'compose') {
|
||||
dispatch(quoteComposeCancel());
|
||||
}
|
||||
},
|
||||
|
||||
onRevokeQuote (status) {
|
||||
dispatch(openModal({ modalType: 'CONFIRM_REVOKE_QUOTE', modalProps: { statusId: status.get('id'), quotedStatusId: status.getIn(['quote', 'quoted_status']) }}));
|
||||
},
|
||||
|
||||
@@ -31,6 +31,7 @@ import { PollForm } from "./poll_form";
|
||||
import { ReplyIndicator } from './reply_indicator';
|
||||
import { UploadForm } from './upload_form';
|
||||
import { Warning } from './warning';
|
||||
import { ComposeQuotedStatus } from './quoted_post';
|
||||
|
||||
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
|
||||
|
||||
@@ -258,6 +259,11 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
<div className={classNames('compose-form__highlightable', { active: highlighted })} ref={this.setRef}>
|
||||
<EditIndicator />
|
||||
|
||||
<div className='compose-form__dropdowns'>
|
||||
<PrivacyDropdownContainer disabled={this.props.isEditing} />
|
||||
<LanguageDropdown />
|
||||
</div>
|
||||
|
||||
{this.props.spoiler && (
|
||||
<div className='spoiler-input'>
|
||||
<div className='spoiler-input__border' />
|
||||
@@ -284,11 +290,6 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className='compose-form__dropdowns'>
|
||||
<PrivacyDropdownContainer disabled={this.props.isEditing} />
|
||||
<LanguageDropdown />
|
||||
</div>
|
||||
|
||||
<AutosuggestTextarea
|
||||
ref={this.textareaRef}
|
||||
placeholder={intl.formatMessage(messages.placeholder)}
|
||||
@@ -304,10 +305,12 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
onPaste={onPaste}
|
||||
autoFocus={autoFocus}
|
||||
lang={this.props.lang}
|
||||
className='compose-form__input'
|
||||
/>
|
||||
|
||||
<UploadForm />
|
||||
<PollForm />
|
||||
<ComposeQuotedStatus />
|
||||
|
||||
<div className='compose-form__footer'>
|
||||
<div className='compose-form__actions'>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { Map } from 'immutable';
|
||||
|
||||
import { QuotedStatus } from '@/mastodon/components/status_quoted';
|
||||
import { useAppSelector } from '@/mastodon/store';
|
||||
|
||||
export const ComposeQuotedStatus: FC = () => {
|
||||
const quotedStatusId = useAppSelector(
|
||||
(state) => state.compose.get('quoted_status_id') as string | null,
|
||||
);
|
||||
const quote = useMemo(
|
||||
() =>
|
||||
quotedStatusId
|
||||
? Map<'state' | 'quoted_status', string>([
|
||||
['state', 'accepted'],
|
||||
['quoted_status', quotedStatusId],
|
||||
])
|
||||
: null,
|
||||
[quotedStatusId],
|
||||
);
|
||||
if (!quote) {
|
||||
return null;
|
||||
}
|
||||
return <QuotedStatus quote={quote} contextType='compose' />;
|
||||
};
|
||||
@@ -3,10 +3,16 @@ import { connect } from 'react-redux';
|
||||
import { addPoll, removePoll } from '../../../actions/compose';
|
||||
import PollButton from '../components/poll_button';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
disabled: state.getIn(['compose', 'is_uploading']) || (state.getIn(['compose', 'media_attachments']).size > 0),
|
||||
active: state.getIn(['compose', 'poll']) !== null,
|
||||
});
|
||||
const mapStateToProps = state => {
|
||||
const readyAttachmentsSize = state.compose.get('media_attachments').size ?? 0;
|
||||
const hasAttachments = readyAttachmentsSize > 0 || !!state.compose.get('is_uploading');
|
||||
const hasQuote = !!state.compose.get('quoted_status_id');
|
||||
|
||||
return ({
|
||||
disabled: hasAttachments || hasQuote,
|
||||
active: state.getIn(['compose', 'poll']) !== null,
|
||||
});
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
|
||||
|
||||
@@ -11,9 +11,10 @@ const mapStateToProps = state => {
|
||||
const attachmentsSize = readyAttachmentsSize + pendingAttachmentsSize;
|
||||
const isOverLimit = attachmentsSize > state.getIn(['server', 'server', 'configuration', 'statuses', 'max_media_attachments'])-1;
|
||||
const hasVideoOrAudio = state.getIn(['compose', 'media_attachments']).some(m => ['video', 'audio'].includes(m.get('type')));
|
||||
const hasQuote = !!state.compose.get('quoted_status_id');
|
||||
|
||||
return {
|
||||
disabled: isPoll || isUploading || isOverLimit || hasVideoOrAudio,
|
||||
disabled: isPoll || isUploading || isOverLimit || hasVideoOrAudio || hasQuote,
|
||||
resetFileKey: state.getIn(['compose', 'resetFileKey']),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -864,6 +864,7 @@
|
||||
"status.mute": "@{name} - səssizə al",
|
||||
"status.mute_conversation": "Danışığın səsini kəs",
|
||||
"status.open": "Bu göndərişi genişləndir",
|
||||
"status.pin": "Profildə sanc",
|
||||
"status.quote_error.filtered": "Bəzi filtrlərinizə görə gizlidir",
|
||||
"status.quote_error.not_available": "Göndəriş əlçatmazdır",
|
||||
"status.quote_error.pending_approval": "Göndəriş gözləmədədir",
|
||||
@@ -893,6 +894,7 @@
|
||||
"status.translated_from_with": "{provider} ilə {lang} dilindən tərcümə edilib",
|
||||
"status.uncached_media_warning": "Önizləmə mövcud deyil",
|
||||
"status.unmute_conversation": "Danışığın səsini aç",
|
||||
"status.unpin": "Profil sancağı götür",
|
||||
"subscribed_languages.lead": "Dəyişiklikdən sonra əsas ekran və siyahı zaman xəttinizdə yalnız seçdiyiniz dillərdəki göndərişlər görünəcək. Bütün dillərdə göndəriş almaq üçün heç birini seçməyin.",
|
||||
"subscribed_languages.save": "Dəyişiklikləri saxla",
|
||||
"subscribed_languages.target": "{target} üçün abunə olunmuş dilləri dəyişdir",
|
||||
|
||||
@@ -879,6 +879,7 @@
|
||||
"status.mute_conversation": "Silencia la conversa",
|
||||
"status.open": "Amplia el tut",
|
||||
"status.pin": "Fixa en el perfil",
|
||||
"status.quote.cancel": "Canceŀlar la citació",
|
||||
"status.quote_error.filtered": "No es mostra a causa d'un dels vostres filtres",
|
||||
"status.quote_error.not_available": "Publicació no disponible",
|
||||
"status.quote_error.pending_approval": "Publicació pendent",
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"account.mute_short": "Stummschalten",
|
||||
"account.muted": "Stummgeschaltet",
|
||||
"account.muting": "Stummgeschaltet",
|
||||
"account.mutual": "Ihr folgt euch",
|
||||
"account.mutual": "Ihr folgt einander",
|
||||
"account.no_bio": "Keine Beschreibung verfügbar.",
|
||||
"account.open_original_page": "Ursprüngliche Seite öffnen",
|
||||
"account.posts": "Beiträge",
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "Unterhaltung stummschalten",
|
||||
"status.open": "Beitrag öffnen",
|
||||
"status.pin": "Im Profil anheften",
|
||||
"status.quote.cancel": "Zitat abbrechen",
|
||||
"status.quote_error.filtered": "Ausgeblendet wegen eines deiner Filter",
|
||||
"status.quote_error.not_available": "Beitrag nicht verfügbar",
|
||||
"status.quote_error.pending_approval": "Beitragsveröffentlichung ausstehend",
|
||||
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "Mute conversation",
|
||||
"status.open": "Expand this post",
|
||||
"status.pin": "Pin on profile",
|
||||
"status.quote.cancel": "Cancel quote",
|
||||
"status.quote_error.filtered": "Hidden due to one of your filters",
|
||||
"status.quote_error.not_available": "Post unavailable",
|
||||
"status.quote_error.pending_approval": "Post pending",
|
||||
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "Silenciar conversación",
|
||||
"status.open": "Expandir este mensaje",
|
||||
"status.pin": "Fijar en el perfil",
|
||||
"status.quote.cancel": "Cancelar cita",
|
||||
"status.quote_error.filtered": "Oculto debido a uno de tus filtros",
|
||||
"status.quote_error.not_available": "Mensaje no disponible",
|
||||
"status.quote_error.pending_approval": "Mensaje pendiente",
|
||||
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "Silenciar conversación",
|
||||
"status.open": "Expandir estado",
|
||||
"status.pin": "Fijar",
|
||||
"status.quote.cancel": "Cancelar cita",
|
||||
"status.quote_error.filtered": "Oculto debido a uno de tus filtros",
|
||||
"status.quote_error.not_available": "Publicación no disponible",
|
||||
"status.quote_error.pending_approval": "Publicación pendiente",
|
||||
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "Silenciar conversación",
|
||||
"status.open": "Expandir publicación",
|
||||
"status.pin": "Fijar",
|
||||
"status.quote.cancel": "Cancelar cita",
|
||||
"status.quote_error.filtered": "Oculto debido a uno de tus filtros",
|
||||
"status.quote_error.not_available": "Publicación no disponible",
|
||||
"status.quote_error.pending_approval": "Publicación pendiente",
|
||||
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "Mykistä keskustelu",
|
||||
"status.open": "Laajenna julkaisu",
|
||||
"status.pin": "Kiinnitä profiiliin",
|
||||
"status.quote.cancel": "Peruuta lainaus",
|
||||
"status.quote_error.filtered": "Piilotettu jonkin asettamasi suodattimen takia",
|
||||
"status.quote_error.not_available": "Julkaisu ei saatavilla",
|
||||
"status.quote_error.pending_approval": "Julkaisu odottaa",
|
||||
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "Doyv samrøðu",
|
||||
"status.open": "Víðka henda postin",
|
||||
"status.pin": "Ger fastan í vangan",
|
||||
"status.quote.cancel": "Ógilda sitat",
|
||||
"status.quote_error.filtered": "Eitt av tínum filtrum fjalir hetta",
|
||||
"status.quote_error.not_available": "Postur ikki tøkur",
|
||||
"status.quote_error.pending_approval": "Postur bíðar",
|
||||
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "Silenciar conversa",
|
||||
"status.open": "Estender esta publicación",
|
||||
"status.pin": "Fixar no perfil",
|
||||
"status.quote.cancel": "Cancelar a cita",
|
||||
"status.quote_error.filtered": "Oculto debido a un dos teus filtros",
|
||||
"status.quote_error.not_available": "Publicación non dispoñible",
|
||||
"status.quote_error.pending_approval": "Publicación pendente",
|
||||
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "השתקת שיחה",
|
||||
"status.open": "הרחבת הודעה זו",
|
||||
"status.pin": "הצמדה לפרופיל שלי",
|
||||
"status.quote.cancel": "ביטול הודעת ציטוט",
|
||||
"status.quote_error.filtered": "מוסתר בהתאם לסננים שלך",
|
||||
"status.quote_error.not_available": "ההודעה לא זמינה",
|
||||
"status.quote_error.pending_approval": "ההודעה בהמתנה לאישור",
|
||||
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "Þagga niður í samtali",
|
||||
"status.open": "Opna þessa færslu",
|
||||
"status.pin": "Festa á notandasnið",
|
||||
"status.quote.cancel": "Hætta við tilvitnun",
|
||||
"status.quote_error.filtered": "Falið vegna einnar síu sem er virk",
|
||||
"status.quote_error.not_available": "Færsla ekki tiltæk",
|
||||
"status.quote_error.pending_approval": "Færsla í bið",
|
||||
@@ -964,6 +965,11 @@
|
||||
"video.volume_up": "Hækka hljóðstyrk",
|
||||
"visibility_modal.button_title": "Stilla sýnileika",
|
||||
"visibility_modal.header": "Sýnileiki og gagnvirkni",
|
||||
"visibility_modal.helper.direct_quoting": "Ekki er hægt að vitna í einkaspjall.",
|
||||
"visibility_modal.helper.privacy_editing": "Ekki er hægt að breyta sýnileika birtra færslna.",
|
||||
"visibility_modal.helper.private_quoting": "Ekki er hægt að vitna í færslur sem eingöngu eru til fylgjenda.",
|
||||
"visibility_modal.helper.unlisted_quoting": "Þegar fólk vitnar í þig verða færslurnar þeirr einnig faldar á vinsældatímalínum.",
|
||||
"visibility_modal.instructions": "Stýrðu hverjir geta átt við þessa færslu. Víðværar stillingar finnast undir <link>Kjörstillingar > Annað</link>.",
|
||||
"visibility_modal.privacy_label": "Persónuvernd",
|
||||
"visibility_modal.quote_followers": "Einungis fylgjendur",
|
||||
"visibility_modal.quote_label": "Breyttu því hver getur tilvitnað",
|
||||
|
||||
@@ -603,6 +603,7 @@
|
||||
"notification.label.mention": "Упоминание",
|
||||
"notification.label.private_mention": "Личное упоминание",
|
||||
"notification.label.private_reply": "Приватный ответ",
|
||||
"notification.label.quote": "{name} процитировал(а) ваш пост",
|
||||
"notification.label.reply": "Ответ",
|
||||
"notification.mention": "Упоминание",
|
||||
"notification.mentioned_you": "{name} упомянул(а) вас",
|
||||
@@ -660,6 +661,7 @@
|
||||
"notifications.column_settings.mention": "Вас упомянули в посте:",
|
||||
"notifications.column_settings.poll": "Опрос, в котором вы приняли участие, завершился:",
|
||||
"notifications.column_settings.push": "Push-уведомления",
|
||||
"notifications.column_settings.quote": "Ваш пост процитировали:",
|
||||
"notifications.column_settings.reblog": "Ваш пост продвинули:",
|
||||
"notifications.column_settings.show": "Отображать в списке",
|
||||
"notifications.column_settings.sound": "Проигрывать звук",
|
||||
@@ -851,7 +853,7 @@
|
||||
"status.cancel_reblog_private": "Отменить продвижение",
|
||||
"status.cannot_reblog": "Этот пост не может быть продвинут",
|
||||
"status.context.load_new_replies": "Доступны новые ответы",
|
||||
"status.context.loading": "Проверяем, есть ли еще ответы",
|
||||
"status.context.loading": "Проверяем, есть ли ещё ответы",
|
||||
"status.continued_thread": "Продолжение предыдущего поста",
|
||||
"status.copy": "Скопировать ссылку на пост",
|
||||
"status.delete": "Удалить",
|
||||
@@ -879,6 +881,8 @@
|
||||
"status.pin": "Закрепить в профиле",
|
||||
"status.quote_error.filtered": "Скрыто одним из ваших фильтров",
|
||||
"status.quote_error.not_available": "Пост недоступен",
|
||||
"status.quote_error.pending_approval": "Пост ожидает подтверждения",
|
||||
"status.quote_error.pending_approval_popout.title": "Цитирование ещё не подтверждено? Не беспокойтесь",
|
||||
"status.read_more": "Читать далее",
|
||||
"status.reblog": "Продвинуть",
|
||||
"status.reblog_private": "Продвинуть для своей аудитории",
|
||||
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "Tắt thông báo",
|
||||
"status.open": "Mở tút",
|
||||
"status.pin": "Ghim lên hồ sơ",
|
||||
"status.quote.cancel": "Bỏ trích dẫn",
|
||||
"status.quote_error.filtered": "Bị ẩn vì một bộ lọc của bạn",
|
||||
"status.quote_error.not_available": "Tút không khả dụng",
|
||||
"status.quote_error.pending_approval": "Tút đang chờ duyệt",
|
||||
|
||||
@@ -240,6 +240,8 @@
|
||||
"confirmations.remove_from_followers.confirm": "移除关注者",
|
||||
"confirmations.remove_from_followers.message": "{name} 将停止关注您。您确定要继续吗?",
|
||||
"confirmations.remove_from_followers.title": "移除关注者?",
|
||||
"confirmations.revoke_quote.confirm": "移除嘟文",
|
||||
"confirmations.revoke_quote.title": "移除嘟文?",
|
||||
"confirmations.unfollow.confirm": "取消关注",
|
||||
"confirmations.unfollow.message": "你确定要取消关注 {name} 吗?",
|
||||
"confirmations.unfollow.title": "确定要取消关注用户?",
|
||||
@@ -491,6 +493,7 @@
|
||||
"keyboard_shortcuts.translate": "翻译嘟文",
|
||||
"keyboard_shortcuts.unfocus": "取消输入/搜索",
|
||||
"keyboard_shortcuts.up": "在列表中让光标上移",
|
||||
"learn_more_link.got_it": "明白了",
|
||||
"lightbox.close": "关闭",
|
||||
"lightbox.next": "下一个",
|
||||
"lightbox.previous": "上一个",
|
||||
@@ -861,6 +864,7 @@
|
||||
"status.mute_conversation": "关闭此对话的通知",
|
||||
"status.open": "展开嘟文",
|
||||
"status.pin": "在个人资料页面置顶",
|
||||
"status.quote.cancel": "取消引用",
|
||||
"status.quote_error.filtered": "已根据你的筛选器过滤",
|
||||
"status.read_more": "查看更多",
|
||||
"status.reblog": "转嘟",
|
||||
|
||||
@@ -880,6 +880,7 @@
|
||||
"status.mute_conversation": "靜音對話",
|
||||
"status.open": "展開此嘟文",
|
||||
"status.pin": "釘選至個人檔案頁面",
|
||||
"status.quote.cancel": "取消引用嘟文",
|
||||
"status.quote_error.filtered": "由於您的過濾器,該嘟文被隱藏",
|
||||
"status.quote_error.not_available": "無法取得該嘟文",
|
||||
"status.quote_error.pending_approval": "嘟文正在發送中",
|
||||
|
||||
@@ -331,8 +331,16 @@ export const composeReducer = (state = initialState, action) => {
|
||||
return state.set('is_changing_upload', false);
|
||||
} else if (quoteComposeByStatus.match(action)) {
|
||||
const status = action.payload;
|
||||
if (status.getIn(['quote_approval', 'current_user']) === 'automatic') {
|
||||
return state.set('quoted_status_id', status.get('id'));
|
||||
if (
|
||||
status.getIn(['quote_approval', 'current_user']) === 'automatic' &&
|
||||
state.get('media_attachments').size === 0 &&
|
||||
!state.get('is_uploading') &&
|
||||
!state.get('poll')
|
||||
) {
|
||||
return state
|
||||
.set('quoted_status_id', status.get('id'))
|
||||
.set('spoiler', status.get('sensitive'))
|
||||
.set('spoiler_text', status.get('spoiler_text'));
|
||||
}
|
||||
} else if (quoteComposeCancel.match(action)) {
|
||||
return state.set('quoted_status_id', null);
|
||||
|
||||
@@ -15,7 +15,7 @@ export const getFilters = createSelector(
|
||||
(_, { contextType }: { contextType: string }) => contextType,
|
||||
],
|
||||
(filters, contextType) => {
|
||||
if (!contextType) {
|
||||
if (!contextType || contextType === 'compose') {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ export function createAppThunk<Arg = void, Returned = void, ExtraArg = unknown>(
|
||||
},
|
||||
}));
|
||||
|
||||
return Object.assign({}, action, actionCreator);
|
||||
return Object.assign(actionCreator, action);
|
||||
}
|
||||
|
||||
const createBaseAsyncThunk = rtkCreateAsyncThunk.withTypes<AppThunkConfig>();
|
||||
|
||||
@@ -656,19 +656,12 @@ body > [data-popper-placement] {
|
||||
background: url('@/images/warning-stripes.svg') repeat-y;
|
||||
width: 5px;
|
||||
flex: 0 0 auto;
|
||||
|
||||
&:first-child {
|
||||
border-start-start-radius: 4px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-start-end-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.autosuggest-input {
|
||||
flex: 1 1 auto;
|
||||
border-bottom: 1px solid var(--background-border-color);
|
||||
border: 1px solid var(--background-border-color);
|
||||
border-width: 1px 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -946,6 +939,24 @@ body > [data-popper-placement] {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status__quote {
|
||||
margin: 0 8px;
|
||||
max-height: 220px;
|
||||
overflow: hidden;
|
||||
|
||||
// Override .status__content .status__content__text.status__content__text--visible
|
||||
.status__content__text.status__content__text {
|
||||
display: -webkit-box;
|
||||
}
|
||||
|
||||
.status__content__text {
|
||||
-webkit-line-clamp: 4;
|
||||
line-clamp: 4;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-button {
|
||||
@@ -1583,6 +1594,7 @@ body > [data-popper-placement] {
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
overflow: hidden;
|
||||
flex-grow: 1;
|
||||
|
||||
.display-name {
|
||||
bdi {
|
||||
@@ -1599,6 +1611,11 @@ body > [data-popper-placement] {
|
||||
}
|
||||
}
|
||||
|
||||
.status__quote-cancel {
|
||||
align-self: self-start;
|
||||
order: 5;
|
||||
}
|
||||
|
||||
.status__info {
|
||||
font-size: 15px;
|
||||
padding-bottom: 10px;
|
||||
|
||||
@@ -21,8 +21,9 @@ class Scheduler::SelfDestructScheduler
|
||||
|
||||
def sidekiq_overwhelmed?
|
||||
redis_mem_info = Sidekiq.default_configuration.redis_info
|
||||
maxmemory = [redis_mem_info['maxmemory'].to_f, redis_mem_info['total_system_memory'].to_f].filter(&:positive?).min
|
||||
|
||||
Sidekiq::Stats.new.enqueued > MAX_ENQUEUED || redis_mem_info['used_memory'].to_f > redis_mem_info['total_system_memory'].to_f * MAX_REDIS_MEM_USAGE
|
||||
Sidekiq::Stats.new.enqueued > MAX_ENQUEUED || redis_mem_info['used_memory'].to_f > maxmemory * MAX_REDIS_MEM_USAGE
|
||||
end
|
||||
|
||||
def delete_accounts!
|
||||
|
||||
@@ -1930,7 +1930,7 @@ cy:
|
||||
last_active: Yn weithgar ddiwethaf
|
||||
most_recent: Y diweddaraf
|
||||
moved: Wedi symud
|
||||
mutual: Cydfudd
|
||||
mutual: Yn Gyffredin
|
||||
primary: Cynradd
|
||||
relationship: Perthynas
|
||||
remove_selected_domains: Tynnu'r holl ddilynwyr o'r parthau a ddewiswyd
|
||||
|
||||
@@ -2059,12 +2059,12 @@ ru:
|
||||
enabled: Двухфакторная аутентификация включена
|
||||
enabled_success: Двухфакторная аутентификация настроена
|
||||
generate_recovery_codes: Сгенерировать резервные коды
|
||||
lost_recovery_codes: Коды восстановления позволяются войти в учётную запись в случае утери смартфона. Если вы потеряли свои коды восстановления, вы можете создать новые здесь. Прошлые коды работать перестанут.
|
||||
lost_recovery_codes: Резервные коды позволят вам восстановить доступ к своей учётной записи в случае потери смартфона. Если вы потеряли свои резервные коды, просто создайте новые. Ваши старые коды будут аннулированы.
|
||||
methods: Способы подтверждения входа
|
||||
otp: Приложение-аутентификатор
|
||||
recovery_codes: Резервные коды
|
||||
recovery_codes_regenerated: Коды восстановления успешно сгенерированы
|
||||
recovery_instructions_html: 'Пожалуйста, сохраните коды ниже в надёжном месте: они понадобятся, чтобы войти в учётную запись, если вы потеряете доступ к своему смартфону. Вы можете вручную переписать их, распечатать и спрятать среди важных документов или, например, в любимой книжке. <strong>Каждый код действителен только один раз</strong>.'
|
||||
recovery_codes_regenerated: Новые резервные коды сгенерированы
|
||||
recovery_instructions_html: Если случится так, что у вас не будет доступа к смартфону, резервные коды позволят вам восстановить доступ к своей учётной записи. <strong>Храните резервные коды в надёжном месте.</strong> К примеру, вы можете распечатать их и убрать туда, где лежат другие важные документы.
|
||||
webauthn: Электронные ключи
|
||||
user_mailer:
|
||||
announcement_published:
|
||||
@@ -2083,16 +2083,16 @@ ru:
|
||||
subtitle: Ваша апелляция отклонена.
|
||||
title: Обжалование отклонено
|
||||
backup_ready:
|
||||
explanation: Вы запросили полное резервное копирование вашей учетной записи Mastodon.
|
||||
extra: Теперь он готов к загрузке!
|
||||
explanation: Вы запросили экспорт данных своей учётной записи Mastodon.
|
||||
extra: Теперь ваш архив готов и доступен для скачивания!
|
||||
subject: Ваш архив готов к загрузке
|
||||
title: Архив ваших данных готов
|
||||
title: Экспорт данных
|
||||
failed_2fa:
|
||||
details: 'Вот подробности попытки регистрации:'
|
||||
explanation: Кто-то пытался войти в вашу учетную запись, но указал неверный второй фактор аутентификации.
|
||||
further_actions_html: Если это не вы, мы рекомендуем %{action} немедленно принять меры, так как он может быть скомпрометирован.
|
||||
subject: Сбой двухфакторной аутентификации
|
||||
title: Сбой двухфакторной аутентификации
|
||||
details: 'Вот подробности попытки входа:'
|
||||
explanation: Кто-то пытался войти в вашу учётную запись, но не смог подтвердить вход при помощи второго фактора.
|
||||
further_actions_html: Если это были не вы, рекомендуем немедленно %{action}, так как он мог быть скомпрометирован.
|
||||
subject: Неудачная попытка подтверждения входа
|
||||
title: Неудачная попытка подтверждения входа
|
||||
suspicious_sign_in:
|
||||
change_password: сменить пароль
|
||||
details: 'Подробности о новом входе:'
|
||||
@@ -2146,58 +2146,45 @@ ru:
|
||||
apps_step: Загрузите наши официальные приложения.
|
||||
apps_title: Приложения Mastodon
|
||||
checklist_subtitle: 'Давайте начнем знакомство с этим новым социальным рубежом:'
|
||||
checklist_title: Приветственный контрольный список
|
||||
edit_profile_action: Персонализация
|
||||
edit_profile_step: Усильте взаимодействие, заполнив полный профиль.
|
||||
edit_profile_title: Персонализируйте свой профиль
|
||||
explanation: Вот несколько советов для новичков
|
||||
feature_action: Подробнее
|
||||
feature_audience: Mastodon предоставляет вам уникальную возможность управлять своей аудиторией без посредников. Mastodon, развернутый на вашей собственной инфраструктуре, позволяет вам следить и быть преследуемым с любого другого сервера Mastodon в Интернете и не контролируется никем, кроме вас.
|
||||
feature_audience_title: Создайте уверенную аудиторию
|
||||
feature_control: Вы сами знаете, что хотите видеть в своей ленте. Никаких алгоритмов или рекламы, чтобы тратить ваше время. Следите за любым человеком на любом сервере Mastodon с одного аккаунта и получайте его сообщения в хронологическом порядке, а также сделайте свой уголок интернета немного больше похожим на себя.
|
||||
feature_control_title: Контролируйте свой график
|
||||
feature_creativity: Mastodon поддерживает аудио-, видео- и фотопосты, описания доступности, опросы, предупреждения о содержании, анимированные аватары, пользовательские emojis, управление обрезкой миниатюр и многое другое, чтобы помочь вам выразить себя в Интернете. Публикуете ли вы свои работы, музыку или подкаст, Mastodon всегда готов помочь вам.
|
||||
feature_creativity_title: Непревзойденная креативность
|
||||
feature_moderation: Mastodon возвращает принятие решений в ваши руки. Каждый сервер создает свои собственные правила и нормы, которые соблюдаются локально, а не сверху вниз, как в корпоративных социальных сетях, что позволяет наиболее гибко реагировать на потребности различных групп людей. Присоединяйтесь к серверу с правилами, с которыми вы согласны, или создайте свой собственный.
|
||||
feature_moderation_title: Модерирование, каким оно должно быть
|
||||
follow_action: Следуйте за
|
||||
follow_step: Следить за интересными людьми - вот что такое Mastodon.
|
||||
follow_title: Персонализируйте свою домашнюю ленту
|
||||
follows_subtitle: Следите за известными аккаунтами
|
||||
follows_title: За кем следить
|
||||
follows_view_more: Посмотреть больше людей, за которыми стоит следить
|
||||
hashtags_recent_count:
|
||||
few: "%{people} человека за последние 2 дня"
|
||||
many: "%{people} человек за последние 2 дня"
|
||||
one: "%{people} человек за последние 2 дня"
|
||||
other: "%{people} человек за последние 2 дня"
|
||||
hashtags_subtitle: Изучите, что было в тренде за последние 2 дня
|
||||
hashtags_title: Модные хэштеги
|
||||
hashtags_view_more: Посмотреть другие трендовые хэштеги
|
||||
post_action: Составить
|
||||
post_step: Поприветствуйте мир с помощью текста, фотографий, видео или опросов.
|
||||
post_title: Сделайте свой первый пост
|
||||
share_step: Пусть ваши друзья знают, как найти вас на Mastodon.
|
||||
share_title: Поделитесь информацией о компании Mastodon
|
||||
sign_in_action: Зарегистрироваться
|
||||
subject: Добро пожаловать в Mastodon
|
||||
title: Добро пожаловать на борт, %{name}!
|
||||
users:
|
||||
follow_limit_reached: Вы не можете подписаться больше, чем на %{limit} человек
|
||||
follow_limit_reached: Вы можете подписаться не больше чем на %{limit} человек
|
||||
go_to_sso_account_settings: Перейти к настройкам сторонних аккаунтов учетной записи
|
||||
invalid_otp_token: Введен неверный код двухфакторной аутентификации
|
||||
otp_lost_help_html: Если Вы потеряли доступ к обоим, свяжитесь с %{email}
|
||||
rate_limited: Слишком много попыток аутентификации, повторите попытку позже.
|
||||
invalid_otp_token: Введён неверный код двухфакторной аутентификации
|
||||
otp_lost_help_html: Если вы утратили доступ и к приложению-аутентификатору, и к резервным кодам, свяжитесь с %{email}
|
||||
rate_limited: Слишком много попыток аутентификации, попробуйте позже.
|
||||
seamless_external_login: Вы вошли в систему через внешнюю службу, поэтому настройки пароля и электронной почты недоступны.
|
||||
signed_in_as: 'Выполнен вход под именем:'
|
||||
signed_in_as: Выполнен вход в учётную запись
|
||||
verification:
|
||||
extra_instructions_html: <strong>Подсказка:</strong> Ссылка на вашем сайте может быть невидимой. Важной частью является <code>rel="me"</code>, который предотвращает выдачу себя за другое лицо на сайтах с пользовательским контентом. Вы даже можете использовать тег <code>link</code> в заголовке страницы вместо <code>a</code>, но HTML должен быть доступен без выполнения JavaScript.
|
||||
here_is_how: Вот как
|
||||
hint_html: "<strong>Подтверждение личности на Mastodon доступно каждому.</strong> Основано на открытых веб-стандартах, отныне и навсегда бесплатно. Всё, что вам нужно, - это персональный сайт, по которому вас узнают. Когда вы ссылаетесь на этот сайт из своего профиля, мы проверим, что сайт ссылается на ваш профиль, и отобразим на нём визуальный индикатор."
|
||||
instructions_html: Скопируйте и вставьте код ниже в HTML вашего сайта. Затем, добавьте адрес вашего веб сайта в одно из дополнительных полей на вкладке "Редактировать профиль" и сохраните изменения.
|
||||
verification: Верификация ссылок
|
||||
verified_links: Ваши ссылки подтверждения
|
||||
website_verification: Проверка веб-сайта
|
||||
extra_instructions_html: <strong>Подсказка:</strong> Ссылка на вашем сайте может быть невидимой. Ключевое значение имеет атрибут <code>rel="me"</code>, который не даёт выдать себя за другое лицо на сайтах, где контент создают сами пользователи. Вместо тега <code>a</code> можно использовать тег <code>link</code> в <code>head</code>-секции страницы, но необходимо, чтобы HTML-код был доступен без выполнения JavaScript.
|
||||
here_is_how: Как это делается?
|
||||
hint_html: "<strong>Подтверждение личности в Mastodon доступно каждому.</strong> Оно предоставляется на основе открытых веб-стандартов, бесплатно навсегда. Всё, что вам нужно, — это личный веб-сайт, по которому другие люди смогут вас узнать. После того как вы разместите ссылку на этот сайт в своём профиле, мы убедимся, что сайт в свою очередь ссылается на ваш профиль, и затем напротив ссылки появится визуальный индикатор."
|
||||
instructions_html: Скопируйте и вставьте следующий код в HTML-разметку вашего сайта. Затем добавьте адрес вашего веб-сайта в одно из дополнительных полей на вкладке «Данные профиля» и сохраните изменения.
|
||||
verification: Верификация
|
||||
verified_links: Верифицированные ссылки
|
||||
website_verification: Верификация по веб-сайту
|
||||
webauthn_credentials:
|
||||
add: Добавить новый электронный ключ
|
||||
create:
|
||||
|
||||
@@ -56,6 +56,7 @@ ru:
|
||||
scopes: Выберите, какие API приложение сможет использовать. Разрешения верхнего уровня имплицитно включают в себя все разрешения более низких уровней.
|
||||
setting_aggregate_reblogs: Не показывать новые продвижения постов, которые уже были недавно продвинуты (применяется только к будущим продвижениям)
|
||||
setting_always_send_emails: По умолчанию уведомления не доставляются по электронной почте, пока вы активно используете Mastodon
|
||||
setting_default_quote_policy: Эта настройка будет применена только к постам, созданным в следующей версии Mastodon, но вы можете заранее определить свои предпочтения.
|
||||
setting_default_sensitive: Медиа деликатного характера скрыты по умолчанию и могут быть показаны по нажатию на них
|
||||
setting_display_media_default: Скрывать медиа деликатного характера
|
||||
setting_display_media_hide_all: Скрывать все медиа
|
||||
@@ -148,6 +149,11 @@ ru:
|
||||
min_age: Не меньше минимального возраста, требуемого по закону в вашей юрисдикции.
|
||||
user:
|
||||
chosen_languages: Отметьте языки, на которых вы желаете видеть посты в публичных лентах. Оставьте выбор пустым, чтобы не фильтровать посты по языку
|
||||
date_of_birth:
|
||||
few: Для регистрации на %{domain} нужно убедиться, что вам не меньше %{count} лет. Мы не храним введённые здесь данные.
|
||||
many: Для регистрации на %{domain} нужно убедиться, что вам не меньше %{count} лет. Мы не храним введённые здесь данные.
|
||||
one: Для регистрации на %{domain} нужно убедиться, что вам не меньше %{count} года. Мы не храним введённые здесь данные.
|
||||
other: Для регистрации на %{domain} нужно убедиться, что вам не меньше %{count} лет. Мы не храним введённые здесь данные.
|
||||
role: Роль определяет, какими правами обладает пользователь.
|
||||
user_role:
|
||||
color: Цвет, который будет использоваться для роли в интерфейсе (UI), как RGB в формате HEX
|
||||
|
||||
13
db/migrate/20250819100545_update_quote_index.rb
Normal file
13
db/migrate/20250819100545_update_quote_index.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class UpdateQuoteIndex < ActiveRecord::Migration[8.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
add_index :quotes, [:account_id, :quoted_account_id, :id], algorithm: :concurrently
|
||||
remove_index :quotes, [:account_id, :quoted_account_id]
|
||||
|
||||
add_index :quotes, [:quoted_status_id, :id], algorithm: :concurrently
|
||||
remove_index :quotes, [:quoted_status_id]
|
||||
end
|
||||
end
|
||||
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.0].define(version: 2025_08_05_075010) do
|
||||
ActiveRecord::Schema[8.0].define(version: 2025_08_19_100545) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_catalog.plpgsql"
|
||||
|
||||
@@ -926,11 +926,11 @@ ActiveRecord::Schema[8.0].define(version: 2025_08_05_075010) do
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.boolean "legacy", default: false, null: false
|
||||
t.index ["account_id", "quoted_account_id"], name: "index_quotes_on_account_id_and_quoted_account_id"
|
||||
t.index ["account_id", "quoted_account_id", "id"], name: "index_quotes_on_account_id_and_quoted_account_id_and_id"
|
||||
t.index ["activity_uri"], name: "index_quotes_on_activity_uri", unique: true, where: "(activity_uri IS NOT NULL)"
|
||||
t.index ["approval_uri"], name: "index_quotes_on_approval_uri", where: "(approval_uri IS NOT NULL)"
|
||||
t.index ["quoted_account_id"], name: "index_quotes_on_quoted_account_id"
|
||||
t.index ["quoted_status_id"], name: "index_quotes_on_quoted_status_id"
|
||||
t.index ["quoted_status_id", "id"], name: "index_quotes_on_quoted_status_id_and_id"
|
||||
t.index ["status_id"], name: "index_quotes_on_status_id", unique: true
|
||||
end
|
||||
|
||||
|
||||
@@ -130,14 +130,19 @@ RSpec.describe 'Settings applications page' do
|
||||
|
||||
describe 'Regenerating an app token' do
|
||||
it 'updates the app token' do
|
||||
visit settings_application_path(application)
|
||||
expect { visit settings_application_path(application) }
|
||||
.to change(user_application_token, :first).from(be_nil).to(be_present)
|
||||
|
||||
expect { regenerate_token }
|
||||
.to(change { user.token_for_app(application) })
|
||||
.to(change { user_application_token.first.token })
|
||||
expect(page)
|
||||
.to have_content(I18n.t('applications.token_regenerated'))
|
||||
end
|
||||
|
||||
def user_application_token
|
||||
Doorkeeper::AccessToken.where(application:).where(resource_owner_id: user)
|
||||
end
|
||||
|
||||
def regenerate_token
|
||||
click_on I18n.t('applications.regenerate_token')
|
||||
end
|
||||
|
||||
@@ -11,9 +11,9 @@ ARG BASE_REGISTRY="docker.io"
|
||||
# Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
|
||||
# renovate: datasource=node-version depName=node
|
||||
ARG NODE_MAJOR_VERSION="22"
|
||||
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
|
||||
ARG DEBIAN_VERSION="bookworm"
|
||||
# Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
|
||||
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="trixie"]
|
||||
ARG DEBIAN_VERSION="trixie"
|
||||
# Node image to use for base image based on combined variables (ex: 20-trixie-slim)
|
||||
FROM ${BASE_REGISTRY}/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS streaming
|
||||
|
||||
# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
|
||||
|
||||
112
yarn.lock
112
yarn.lock
@@ -73,39 +73,39 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/core@npm:^7.18.9, @babel/core@npm:^7.21.3, @babel/core@npm:^7.24.4, @babel/core@npm:^7.26.10, @babel/core@npm:^7.28.0":
|
||||
version: 7.28.0
|
||||
resolution: "@babel/core@npm:7.28.0"
|
||||
"@babel/core@npm:^7.18.9, @babel/core@npm:^7.21.3, @babel/core@npm:^7.24.4, @babel/core@npm:^7.26.10, @babel/core@npm:^7.28.0, @babel/core@npm:^7.28.3":
|
||||
version: 7.28.3
|
||||
resolution: "@babel/core@npm:7.28.3"
|
||||
dependencies:
|
||||
"@ampproject/remapping": "npm:^2.2.0"
|
||||
"@babel/code-frame": "npm:^7.27.1"
|
||||
"@babel/generator": "npm:^7.28.0"
|
||||
"@babel/generator": "npm:^7.28.3"
|
||||
"@babel/helper-compilation-targets": "npm:^7.27.2"
|
||||
"@babel/helper-module-transforms": "npm:^7.27.3"
|
||||
"@babel/helpers": "npm:^7.27.6"
|
||||
"@babel/parser": "npm:^7.28.0"
|
||||
"@babel/helper-module-transforms": "npm:^7.28.3"
|
||||
"@babel/helpers": "npm:^7.28.3"
|
||||
"@babel/parser": "npm:^7.28.3"
|
||||
"@babel/template": "npm:^7.27.2"
|
||||
"@babel/traverse": "npm:^7.28.0"
|
||||
"@babel/types": "npm:^7.28.0"
|
||||
"@babel/traverse": "npm:^7.28.3"
|
||||
"@babel/types": "npm:^7.28.2"
|
||||
convert-source-map: "npm:^2.0.0"
|
||||
debug: "npm:^4.1.0"
|
||||
gensync: "npm:^1.0.0-beta.2"
|
||||
json5: "npm:^2.2.3"
|
||||
semver: "npm:^6.3.1"
|
||||
checksum: 10c0/423302e7c721e73b1c096217880272e02020dfb697a55ccca60ad01bba90037015f84d0c20c6ce297cf33a19bb704bc5c2b3d3095f5284dfa592bd1de0b9e8c3
|
||||
checksum: 10c0/e6b3eb830c4b93f5a442b305776df1cd2bb4fafa4612355366f67c764f3e54a69d45b84def77fb2d4fd83439102667b0a92c3ea2838f678733245b748c602a7b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/generator@npm:^7.28.0":
|
||||
version: 7.28.0
|
||||
resolution: "@babel/generator@npm:7.28.0"
|
||||
"@babel/generator@npm:^7.28.3":
|
||||
version: 7.28.3
|
||||
resolution: "@babel/generator@npm:7.28.3"
|
||||
dependencies:
|
||||
"@babel/parser": "npm:^7.28.0"
|
||||
"@babel/types": "npm:^7.28.0"
|
||||
"@babel/parser": "npm:^7.28.3"
|
||||
"@babel/types": "npm:^7.28.2"
|
||||
"@jridgewell/gen-mapping": "npm:^0.3.12"
|
||||
"@jridgewell/trace-mapping": "npm:^0.3.28"
|
||||
jsesc: "npm:^3.0.2"
|
||||
checksum: 10c0/1b3d122268ea3df50fde707ad864d9a55c72621357d5cebb972db3dd76859c45810c56e16ad23123f18f80cc2692f5a015d2858361300f0f224a05dc43d36a92
|
||||
checksum: 10c0/0ff58bcf04f8803dcc29479b547b43b9b0b828ec1ee0668e92d79f9e90f388c28589056637c5ff2fd7bcf8d153c990d29c448d449d852bf9d1bc64753ca462bc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -203,16 +203,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-module-transforms@npm:^7.27.1, @babel/helper-module-transforms@npm:^7.27.3":
|
||||
version: 7.27.3
|
||||
resolution: "@babel/helper-module-transforms@npm:7.27.3"
|
||||
"@babel/helper-module-transforms@npm:^7.27.1, @babel/helper-module-transforms@npm:^7.28.3":
|
||||
version: 7.28.3
|
||||
resolution: "@babel/helper-module-transforms@npm:7.28.3"
|
||||
dependencies:
|
||||
"@babel/helper-module-imports": "npm:^7.27.1"
|
||||
"@babel/helper-validator-identifier": "npm:^7.27.1"
|
||||
"@babel/traverse": "npm:^7.27.3"
|
||||
"@babel/traverse": "npm:^7.28.3"
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0
|
||||
checksum: 10c0/fccb4f512a13b4c069af51e1b56b20f54024bcf1591e31e978a30f3502567f34f90a80da6a19a6148c249216292a8074a0121f9e52602510ef0f32dbce95ca01
|
||||
checksum: 10c0/549be62515a6d50cd4cfefcab1b005c47f89bd9135a22d602ee6a5e3a01f27571868ada10b75b033569f24dc4a2bb8d04bfa05ee75c16da7ade2d0db1437fcdb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -300,24 +300,24 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helpers@npm:^7.27.6":
|
||||
version: 7.27.6
|
||||
resolution: "@babel/helpers@npm:7.27.6"
|
||||
"@babel/helpers@npm:^7.28.3":
|
||||
version: 7.28.3
|
||||
resolution: "@babel/helpers@npm:7.28.3"
|
||||
dependencies:
|
||||
"@babel/template": "npm:^7.27.2"
|
||||
"@babel/types": "npm:^7.27.6"
|
||||
checksum: 10c0/448bac96ef8b0f21f2294a826df9de6bf4026fd023f8a6bb6c782fe3e61946801ca24381490b8e58d861fee75cd695a1882921afbf1f53b0275ee68c938bd6d3
|
||||
"@babel/types": "npm:^7.28.2"
|
||||
checksum: 10c0/03a8f94135415eec62d37be9c62c63908f2d5386c7b00e04545de4961996465775330e3eb57717ea7451e19b0e24615777ebfec408c2adb1df3b10b4df6bf1ce
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.25.4, @babel/parser@npm:^7.27.2, @babel/parser@npm:^7.28.0":
|
||||
version: 7.28.0
|
||||
resolution: "@babel/parser@npm:7.28.0"
|
||||
"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.25.4, @babel/parser@npm:^7.27.2, @babel/parser@npm:^7.28.3":
|
||||
version: 7.28.3
|
||||
resolution: "@babel/parser@npm:7.28.3"
|
||||
dependencies:
|
||||
"@babel/types": "npm:^7.28.0"
|
||||
"@babel/types": "npm:^7.28.2"
|
||||
bin:
|
||||
parser: ./bin/babel-parser.js
|
||||
checksum: 10c0/c2ef81d598990fa949d1d388429df327420357cb5200271d0d0a2784f1e6d54afc8301eb8bdf96d8f6c77781e402da93c7dc07980fcc136ac5b9d5f1fce701b5
|
||||
checksum: 10c0/1f41eb82623b0ca0f94521b57f4790c6c457cd922b8e2597985b36bdec24114a9ccf54640286a760ceb60f11fe9102d192bf60477aee77f5d45f1029b9b72729
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1179,22 +1179,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.26.10, @babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.27.3, @babel/traverse@npm:^7.28.0":
|
||||
version: 7.28.0
|
||||
resolution: "@babel/traverse@npm:7.28.0"
|
||||
"@babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.26.10, @babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.0, @babel/traverse@npm:^7.28.3":
|
||||
version: 7.28.3
|
||||
resolution: "@babel/traverse@npm:7.28.3"
|
||||
dependencies:
|
||||
"@babel/code-frame": "npm:^7.27.1"
|
||||
"@babel/generator": "npm:^7.28.0"
|
||||
"@babel/generator": "npm:^7.28.3"
|
||||
"@babel/helper-globals": "npm:^7.28.0"
|
||||
"@babel/parser": "npm:^7.28.0"
|
||||
"@babel/parser": "npm:^7.28.3"
|
||||
"@babel/template": "npm:^7.27.2"
|
||||
"@babel/types": "npm:^7.28.0"
|
||||
"@babel/types": "npm:^7.28.2"
|
||||
debug: "npm:^4.3.1"
|
||||
checksum: 10c0/32794402457827ac558173bcebdcc0e3a18fa339b7c41ca35621f9f645f044534d91bb923ff385f5f960f2e495f56ce18d6c7b0d064d2f0ccb55b285fa6bc7b9
|
||||
checksum: 10c0/26e95b29a46925b7b41255e03185b7e65b2c4987e14bbee7bbf95867fb19c69181f301bbe1c7b201d4fe0cce6aa0cbea0282dad74b3a0fef3d9058f6c76fdcb3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.18.9, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.25.4, @babel/types@npm:^7.26.10, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.27.6, @babel/types@npm:^7.28.0, @babel/types@npm:^7.4.4":
|
||||
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.18.9, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.25.4, @babel/types@npm:^7.26.10, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.4.4":
|
||||
version: 7.28.2
|
||||
resolution: "@babel/types@npm:7.28.2"
|
||||
dependencies:
|
||||
@@ -3212,10 +3212,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@rolldown/pluginutils@npm:1.0.0-beta.30":
|
||||
version: 1.0.0-beta.30
|
||||
resolution: "@rolldown/pluginutils@npm:1.0.0-beta.30"
|
||||
checksum: 10c0/aff8b532cb9d82d94c9a4101fa12ecb10620ad47d52dbb9135a5c65bde1ad19895b41026b821f4d607083699239a5d0010198401b6a6a54ab6a10d0015302768
|
||||
"@rolldown/pluginutils@npm:1.0.0-beta.32":
|
||||
version: 1.0.0-beta.32
|
||||
resolution: "@rolldown/pluginutils@npm:1.0.0-beta.32"
|
||||
checksum: 10c0/ba3582fc3c35c8eb57b0df2d22d0733b1be83d37edcc258203364773f094f58fc0cb7a056d604603573a69dd0105a466506cad467f59074e1e53d0dc26191f06
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -4714,18 +4714,18 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@vitejs/plugin-react@npm:^5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "@vitejs/plugin-react@npm:5.0.0"
|
||||
version: 5.0.1
|
||||
resolution: "@vitejs/plugin-react@npm:5.0.1"
|
||||
dependencies:
|
||||
"@babel/core": "npm:^7.28.0"
|
||||
"@babel/core": "npm:^7.28.3"
|
||||
"@babel/plugin-transform-react-jsx-self": "npm:^7.27.1"
|
||||
"@babel/plugin-transform-react-jsx-source": "npm:^7.27.1"
|
||||
"@rolldown/pluginutils": "npm:1.0.0-beta.30"
|
||||
"@rolldown/pluginutils": "npm:1.0.0-beta.32"
|
||||
"@types/babel__core": "npm:^7.20.5"
|
||||
react-refresh: "npm:^0.17.0"
|
||||
peerDependencies:
|
||||
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
|
||||
checksum: 10c0/e5813839d319ab5dc1b90cab40b6c08388f26e456166ba9df10ffc3c3f4ecc594cec06715b5c93390bba56140ca5f68a18f2233f7d275d77e5bbfeb979e4fd9b
|
||||
checksum: 10c0/2641171beedfc38edc5671abb47706906f9af2a79a6dfff4e946106c9550de4f83ccae41c164f3ee26a3edf07127ecc0e415fe5cddbf7abc71fbb2540016c27d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -7387,15 +7387,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fdir@npm:^6.4.4, fdir@npm:^6.4.6":
|
||||
version: 6.4.6
|
||||
resolution: "fdir@npm:6.4.6"
|
||||
"fdir@npm:^6.4.4, fdir@npm:^6.5.0":
|
||||
version: 6.5.0
|
||||
resolution: "fdir@npm:6.5.0"
|
||||
peerDependencies:
|
||||
picomatch: ^3 || ^4
|
||||
peerDependenciesMeta:
|
||||
picomatch:
|
||||
optional: true
|
||||
checksum: 10c0/45b559cff889934ebb8bc498351e5acba40750ada7e7d6bde197768d2fa67c149be8ae7f8ff34d03f4e1eb20f2764116e56440aaa2f6689e9a4aa7ef06acafe9
|
||||
checksum: 10c0/e345083c4306b3aed6cb8ec551e26c36bab5c511e99ea4576a16750ddc8d3240e63826cc624f5ae17ad4dc82e68a253213b60d556c11bfad064b7607847ed07f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -13899,11 +13899,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"vite@npm:^5.0.0 || ^6.0.0 || ^7.0.0-0, vite@npm:^7.1.1":
|
||||
version: 7.1.2
|
||||
resolution: "vite@npm:7.1.2"
|
||||
version: 7.1.3
|
||||
resolution: "vite@npm:7.1.3"
|
||||
dependencies:
|
||||
esbuild: "npm:^0.25.0"
|
||||
fdir: "npm:^6.4.6"
|
||||
fdir: "npm:^6.5.0"
|
||||
fsevents: "npm:~2.3.3"
|
||||
picomatch: "npm:^4.0.3"
|
||||
postcss: "npm:^8.5.6"
|
||||
@@ -13949,7 +13949,7 @@ __metadata:
|
||||
optional: true
|
||||
bin:
|
||||
vite: bin/vite.js
|
||||
checksum: 10c0/4ed825b20bc0f49db99cd382de9506b2721ccd47dcebd4a68e0ef65e3cdd2347fded52b306c34178308e0fd7fe78fd5ff517623002cb00710182ad3012c92ced
|
||||
checksum: 10c0/a0aa418beab80673dc9a3e9d1fa49472955d6ef9d41a4c9c6bd402953f411346f612864dae267adfb2bb8ceeb894482369316ffae5816c84fd45990e352b727d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user