Merge commit '5f87ae101c5e0e940e148d493eaac1ce31fe24c1' into glitch-soc/merge-upstream

This commit is contained in:
Claire 2025-04-04 20:00:24 +02:00
commit 99e3ea232f
60 changed files with 667 additions and 512 deletions

View file

@ -15,6 +15,8 @@
// to `null` after any other rule set it to something.
dependencyDashboardHeader: 'This issue lists Renovate updates and detected dependencies. Read the [Dependency Dashboard](https://docs.renovatebot.com/key-concepts/dashboard/) docs to learn more. Before approving any upgrade: read the description and comments in the [`renovate.json5` file](https://github.com/mastodon/mastodon/blob/main/.github/renovate.json5).',
postUpdateOptions: ['yarnDedupeHighest'],
// The types are now included in recent versions,we ignore them here until we upgrade and remove the dependency
ignoreDeps: ['@types/emoji-mart'],
packageRules: [
{
// Require Dependency Dashboard Approval for major version bumps of these node packages

View file

@ -94,7 +94,7 @@ GEM
ast (2.4.3)
attr_required (1.0.2)
aws-eventstream (1.3.2)
aws-partitions (1.1066.0)
aws-partitions (1.1080.0)
aws-sdk-core (3.215.1)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
@ -126,7 +126,7 @@ GEM
blurhash (0.1.8)
bootsnap (1.18.4)
msgpack (~> 1.2)
brakeman (7.0.0)
brakeman (7.0.1)
racc
browser (6.2.0)
brpoplpush-redis_script (0.1.3)
@ -194,7 +194,7 @@ GEM
devise_pam_authenticatable2 (9.2.0)
devise (>= 4.0.0)
rpam2 (~> 4.0)
diff-lcs (1.6.0)
diff-lcs (1.6.1)
discard (1.4.0)
activerecord (>= 4.2, < 9.0)
docile (1.4.1)
@ -266,10 +266,10 @@ GEM
raabro (~> 1.4)
globalid (1.2.1)
activesupport (>= 6.1)
google-protobuf (4.30.1)
google-protobuf (4.30.2)
bigdecimal
rake (>= 13)
googleapis-common-protos-types (1.18.0)
googleapis-common-protos-types (1.19.0)
google-protobuf (>= 3.18, < 5.a)
haml (6.3.0)
temple (>= 0.8.2)
@ -328,7 +328,7 @@ GEM
activesupport (>= 3.0)
nokogiri (>= 1.6)
io-console (0.8.0)
irb (1.15.1)
irb (1.15.2)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
@ -426,7 +426,7 @@ GEM
mime-types (3.6.2)
logger
mime-types-data (~> 3.2015)
mime-types-data (3.2025.0318)
mime-types-data (3.2025.0402)
mini_mime (1.1.5)
mini_portile2 (2.8.8)
minitest (5.25.5)
@ -569,7 +569,7 @@ GEM
opentelemetry-instrumentation-redis (0.26.1)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.23.0)
opentelemetry-instrumentation-sidekiq (0.26.0)
opentelemetry-instrumentation-sidekiq (0.26.1)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.23.0)
opentelemetry-registry (0.4.0)
@ -688,7 +688,7 @@ GEM
link_header (~> 0.0, >= 0.0.8)
rdf-normalize (0.7.0)
rdf (~> 3.3)
rdoc (6.12.0)
rdoc (6.13.1)
psych (>= 4.0.0)
redcarpet (3.6.1)
redis (4.8.1)
@ -740,7 +740,7 @@ GEM
rspec-mocks (~> 3.0)
sidekiq (>= 5, < 9)
rspec-support (3.13.2)
rubocop (1.75.1)
rubocop (1.75.2)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
@ -748,10 +748,10 @@ GEM
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.43.0, < 2.0)
rubocop-ast (>= 1.44.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.43.0)
rubocop-ast (1.44.0)
parser (>= 3.3.7.2)
prism (~> 1.4)
rubocop-capybara (2.22.1)
@ -840,7 +840,7 @@ GEM
stoplight (4.1.1)
redlock (~> 1.0)
stringio (3.1.6)
strong_migrations (2.2.1)
strong_migrations (2.3.0)
activerecord (>= 7)
swd (2.0.3)
activesupport (>= 3)
@ -851,7 +851,7 @@ GEM
temple (0.10.3)
terminal-table (4.0.0)
unicode-display_width (>= 1.1.1, < 4)
terrapin (1.0.1)
terrapin (1.1.0)
climate_control
test-prof (1.4.4)
thor (1.3.2)
@ -1085,4 +1085,4 @@ RUBY VERSION
ruby 3.4.1p0
BUNDLED WITH
2.6.6
2.6.7

View file

@ -10,8 +10,6 @@ module SignatureVerification
EXPIRATION_WINDOW_LIMIT = 12.hours
CLOCK_SKEW_MARGIN = 1.hour
class SignatureVerificationError < StandardError; end
def require_account_signature!
render json: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_account
end
@ -34,7 +32,7 @@ module SignatureVerification
def signature_key_id
signature_params['keyId']
rescue SignatureVerificationError
rescue Mastodon::SignatureVerificationError
nil
end
@ -45,17 +43,17 @@ module SignatureVerification
def signed_request_actor
return @signed_request_actor if defined?(@signed_request_actor)
raise SignatureVerificationError, 'Request not signed' unless signed_request?
raise SignatureVerificationError, 'Incompatible request signature. keyId and signature are required' if missing_required_signature_parameters?
raise SignatureVerificationError, 'Unsupported signature algorithm (only rsa-sha256 and hs2019 are supported)' unless %w(rsa-sha256 hs2019).include?(signature_algorithm)
raise SignatureVerificationError, 'Signed request date outside acceptable time window' unless matches_time_window?
raise Mastodon::SignatureVerificationError, 'Request not signed' unless signed_request?
raise Mastodon::SignatureVerificationError, 'Incompatible request signature. keyId and signature are required' if missing_required_signature_parameters?
raise Mastodon::SignatureVerificationError, 'Unsupported signature algorithm (only rsa-sha256 and hs2019 are supported)' unless %w(rsa-sha256 hs2019).include?(signature_algorithm)
raise Mastodon::SignatureVerificationError, 'Signed request date outside acceptable time window' unless matches_time_window?
verify_signature_strength!
verify_body_digest!
actor = actor_from_key_id(signature_params['keyId'])
raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil?
raise Mastodon::SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil?
signature = Base64.decode64(signature_params['signature'])
compare_signed_string = build_signed_string(include_query_string: true)
@ -68,7 +66,7 @@ module SignatureVerification
actor = stoplight_wrapper.run { actor_refresh_key!(actor) }
raise SignatureVerificationError, "Could not refresh public key #{signature_params['keyId']}" if actor.nil?
raise Mastodon::SignatureVerificationError, "Could not refresh public key #{signature_params['keyId']}" if actor.nil?
compare_signed_string = build_signed_string(include_query_string: true)
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
@ -78,7 +76,7 @@ module SignatureVerification
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)", signed_string: compare_signed_string, signature: signature_params['signature']
rescue SignatureVerificationError => e
rescue Mastodon::SignatureVerificationError => e
fail_with! e.message
rescue *Mastodon::HTTP_CONNECTION_ERRORS => e
fail_with! "Failed to fetch remote data: #{e.message}"
@ -104,7 +102,7 @@ module SignatureVerification
def signature_params
@signature_params ||= SignatureParser.parse(request.headers['Signature'])
rescue SignatureParser::ParsingError
raise SignatureVerificationError, 'Error parsing signature parameters'
raise Mastodon::SignatureVerificationError, 'Error parsing signature parameters'
end
def signature_algorithm
@ -116,31 +114,31 @@ module SignatureVerification
end
def verify_signature_strength!
raise SignatureVerificationError, 'Mastodon requires the Date header or (created) pseudo-header to be signed' unless signed_headers.include?('date') || signed_headers.include?('(created)')
raise SignatureVerificationError, 'Mastodon requires the Digest header or (request-target) pseudo-header to be signed' unless signed_headers.include?(HttpSignatureDraft::REQUEST_TARGET) || signed_headers.include?('digest')
raise SignatureVerificationError, 'Mastodon requires the Host header to be signed when doing a GET request' if request.get? && !signed_headers.include?('host')
raise SignatureVerificationError, 'Mastodon requires the Digest header to be signed when doing a POST request' if request.post? && !signed_headers.include?('digest')
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Date header or (created) pseudo-header to be signed' unless signed_headers.include?('date') || signed_headers.include?('(created)')
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Digest header or (request-target) pseudo-header to be signed' unless signed_headers.include?(HttpSignatureDraft::REQUEST_TARGET) || signed_headers.include?('digest')
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Host header to be signed when doing a GET request' if request.get? && !signed_headers.include?('host')
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Digest header to be signed when doing a POST request' if request.post? && !signed_headers.include?('digest')
end
def verify_body_digest!
return unless signed_headers.include?('digest')
raise SignatureVerificationError, 'Digest header missing' unless request.headers.key?('Digest')
raise Mastodon::SignatureVerificationError, 'Digest header missing' unless request.headers.key?('Digest')
digests = request.headers['Digest'].split(',').map { |digest| digest.split('=', 2) }.map { |key, value| [key.downcase, value] }
sha256 = digests.assoc('sha-256')
raise SignatureVerificationError, "Mastodon only supports SHA-256 in Digest header. Offered algorithms: #{digests.map(&:first).join(', ')}" if sha256.nil?
raise Mastodon::SignatureVerificationError, "Mastodon only supports SHA-256 in Digest header. Offered algorithms: #{digests.map(&:first).join(', ')}" if sha256.nil?
return if body_digest == sha256[1]
digest_size = begin
Base64.strict_decode64(sha256[1].strip).length
rescue ArgumentError
raise SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a valid base64 string. Given digest: #{sha256[1]}"
raise Mastodon::SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a valid base64 string. Given digest: #{sha256[1]}"
end
raise SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a SHA-256 digest. Given digest: #{sha256[1]}" if digest_size != 32
raise Mastodon::SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a SHA-256 digest. Given digest: #{sha256[1]}" if digest_size != 32
raise SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{sha256[1]}"
raise Mastodon::SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{sha256[1]}"
end
def verify_signature(actor, signature, compare_signed_string)
@ -165,13 +163,13 @@ module SignatureVerification
"#{HttpSignatureDraft::REQUEST_TARGET}: #{request.method.downcase} #{request.path}"
end
when '(created)'
raise SignatureVerificationError, 'Invalid pseudo-header (created) for rsa-sha256' unless signature_algorithm == 'hs2019'
raise SignatureVerificationError, 'Pseudo-header (created) used but corresponding argument missing' if signature_params['created'].blank?
raise Mastodon::SignatureVerificationError, 'Invalid pseudo-header (created) for rsa-sha256' unless signature_algorithm == 'hs2019'
raise Mastodon::SignatureVerificationError, 'Pseudo-header (created) used but corresponding argument missing' if signature_params['created'].blank?
"(created): #{signature_params['created']}"
when '(expires)'
raise SignatureVerificationError, 'Invalid pseudo-header (expires) for rsa-sha256' unless signature_algorithm == 'hs2019'
raise SignatureVerificationError, 'Pseudo-header (expires) used but corresponding argument missing' if signature_params['expires'].blank?
raise Mastodon::SignatureVerificationError, 'Invalid pseudo-header (expires) for rsa-sha256' unless signature_algorithm == 'hs2019'
raise Mastodon::SignatureVerificationError, 'Pseudo-header (expires) used but corresponding argument missing' if signature_params['expires'].blank?
"(expires): #{signature_params['expires']}"
else
@ -193,7 +191,7 @@ module SignatureVerification
expires_time = Time.at(signature_params['expires'].to_i).utc if signature_params['expires'].present?
rescue ArgumentError => e
raise SignatureVerificationError, "Invalid Date header: #{e.message}"
raise Mastodon::SignatureVerificationError, "Invalid Date header: #{e.message}"
end
expires_time ||= created_time + 5.minutes unless created_time.nil?
@ -233,9 +231,9 @@ module SignatureVerification
account
end
rescue Mastodon::PrivateNetworkAddressError => e
raise SignatureVerificationError, "Requests to private network addresses are disallowed (tried to query #{e.host})"
raise Mastodon::SignatureVerificationError, "Requests to private network addresses are disallowed (tried to query #{e.host})"
rescue Mastodon::HostValidationError, ActivityPub::FetchRemoteActorService::Error, ActivityPub::FetchRemoteKeyService::Error, Webfinger::Error => e
raise SignatureVerificationError, e.message
raise Mastodon::SignatureVerificationError, e.message
end
def stoplight_wrapper
@ -251,8 +249,8 @@ module SignatureVerification
ActivityPub::FetchRemoteActorService.new.call(actor.uri, only_key: true, suppress_errors: false)
rescue Mastodon::PrivateNetworkAddressError => e
raise SignatureVerificationError, "Requests to private network addresses are disallowed (tried to query #{e.host})"
raise Mastodon::SignatureVerificationError, "Requests to private network addresses are disallowed (tried to query #{e.host})"
rescue Mastodon::HostValidationError, ActivityPub::FetchRemoteActorService::Error, Webfinger::Error => e
raise SignatureVerificationError, e.message
raise Mastodon::SignatureVerificationError, e.message
end
end

View file

@ -12,14 +12,6 @@ export const DOMAIN_BLOCK_FAIL = 'DOMAIN_BLOCK_FAIL';
export const DOMAIN_UNBLOCK_REQUEST = 'DOMAIN_UNBLOCK_REQUEST';
export const DOMAIN_UNBLOCK_FAIL = 'DOMAIN_UNBLOCK_FAIL';
export const DOMAIN_BLOCKS_FETCH_REQUEST = 'DOMAIN_BLOCKS_FETCH_REQUEST';
export const DOMAIN_BLOCKS_FETCH_SUCCESS = 'DOMAIN_BLOCKS_FETCH_SUCCESS';
export const DOMAIN_BLOCKS_FETCH_FAIL = 'DOMAIN_BLOCKS_FETCH_FAIL';
export const DOMAIN_BLOCKS_EXPAND_REQUEST = 'DOMAIN_BLOCKS_EXPAND_REQUEST';
export const DOMAIN_BLOCKS_EXPAND_SUCCESS = 'DOMAIN_BLOCKS_EXPAND_SUCCESS';
export const DOMAIN_BLOCKS_EXPAND_FAIL = 'DOMAIN_BLOCKS_EXPAND_FAIL';
export function blockDomain(domain) {
return (dispatch, getState) => {
dispatch(blockDomainRequest(domain));
@ -79,80 +71,6 @@ export function unblockDomainFail(domain, error) {
};
}
export function fetchDomainBlocks() {
return (dispatch) => {
dispatch(fetchDomainBlocksRequest());
api().get('/api/v1/domain_blocks').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(fetchDomainBlocksSuccess(response.data, next ? next.uri : null));
}).catch(err => {
dispatch(fetchDomainBlocksFail(err));
});
};
}
export function fetchDomainBlocksRequest() {
return {
type: DOMAIN_BLOCKS_FETCH_REQUEST,
};
}
export function fetchDomainBlocksSuccess(domains, next) {
return {
type: DOMAIN_BLOCKS_FETCH_SUCCESS,
domains,
next,
};
}
export function fetchDomainBlocksFail(error) {
return {
type: DOMAIN_BLOCKS_FETCH_FAIL,
error,
};
}
export function expandDomainBlocks() {
return (dispatch, getState) => {
const url = getState().getIn(['domain_lists', 'blocks', 'next']);
if (!url) {
return;
}
dispatch(expandDomainBlocksRequest());
api().get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(expandDomainBlocksSuccess(response.data, next ? next.uri : null));
}).catch(err => {
dispatch(expandDomainBlocksFail(err));
});
};
}
export function expandDomainBlocksRequest() {
return {
type: DOMAIN_BLOCKS_EXPAND_REQUEST,
};
}
export function expandDomainBlocksSuccess(domains, next) {
return {
type: DOMAIN_BLOCKS_EXPAND_SUCCESS,
domains,
next,
};
}
export function expandDomainBlocksFail(error) {
return {
type: DOMAIN_BLOCKS_EXPAND_FAIL,
error,
};
}
export const initDomainBlockModal = account => dispatch => dispatch(openModal({
modalType: 'DOMAIN_BLOCK',
modalProps: {

View file

@ -0,0 +1,13 @@
import api, { getLinks } from 'mastodon/api';
export const apiGetDomainBlocks = async (url?: string) => {
const response = await api().request<string[]>({
method: 'GET',
url: url ?? '/api/v1/domain_blocks',
});
return {
domains: response.data,
links: getLinks(response),
};
};

View file

@ -1,29 +1,36 @@
import PropTypes from 'prop-types';
import { useState, useCallback } from 'react';
import { defineMessages } from 'react-intl';
import classNames from 'classnames';
import { useDispatch } from 'react-redux';
import ContentCopyIcon from '@/material-icons/400-24px/content_copy.svg?react';
import { showAlert } from 'mastodon/actions/alerts';
import { IconButton } from 'mastodon/components/icon_button';
import { useAppDispatch } from 'mastodon/store';
const messages = defineMessages({
copied: { id: 'copy_icon_button.copied', defaultMessage: 'Copied to clipboard' },
copied: {
id: 'copy_icon_button.copied',
defaultMessage: 'Copied to clipboard',
},
});
export const CopyIconButton = ({ title, value, className }) => {
export const CopyIconButton: React.FC<{
title: string;
value: string;
className: string;
}> = ({ title, value, className }) => {
const [copied, setCopied] = useState(false);
const dispatch = useDispatch();
const dispatch = useAppDispatch();
const handleClick = useCallback(() => {
navigator.clipboard.writeText(value);
void navigator.clipboard.writeText(value);
setCopied(true);
dispatch(showAlert({ message: messages.copied }));
setTimeout(() => setCopied(false), 700);
setTimeout(() => {
setCopied(false);
}, 700);
}, [setCopied, value, dispatch]);
return (
@ -31,13 +38,8 @@ export const CopyIconButton = ({ title, value, className }) => {
className={classNames(className, copied ? 'copied' : 'copyable')}
title={title}
onClick={handleClick}
icon=''
iconComponent={ContentCopyIcon}
/>
);
};
CopyIconButton.propTypes = {
title: PropTypes.string,
value: PropTypes.string,
className: PropTypes.string,
};

View file

@ -1,24 +1,15 @@
import { useCallback } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { FormattedMessage } from 'react-intl';
import LockOpenIcon from '@/material-icons/400-24px/lock_open.svg?react';
import { unblockDomain } from 'mastodon/actions/domain_blocks';
import { useAppDispatch } from 'mastodon/store';
import { IconButton } from './icon_button';
const messages = defineMessages({
unblockDomain: {
id: 'account.unblock_domain',
defaultMessage: 'Unblock domain {domain}',
},
});
import { Button } from './button';
export const Domain: React.FC<{
domain: string;
}> = ({ domain }) => {
const intl = useIntl();
const dispatch = useAppDispatch();
const handleDomainUnblock = useCallback(() => {
@ -27,20 +18,17 @@ export const Domain: React.FC<{
return (
<div className='domain'>
<div className='domain__wrapper'>
<span className='domain__domain-name'>
<div className='domain__domain-name'>
<strong>{domain}</strong>
</span>
</div>
<div className='domain__buttons'>
<IconButton
active
icon='unlock'
iconComponent={LockOpenIcon}
title={intl.formatMessage(messages.unblockDomain, { domain })}
onClick={handleDomainUnblock}
<Button onClick={handleDomainUnblock}>
<FormattedMessage
id='account.unblock_domain_short'
defaultMessage='Unblock'
/>
</div>
</Button>
</div>
</div>
);

View file

@ -1,85 +0,0 @@
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { Helmet } from 'react-helmet';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
import { debounce } from 'lodash';
import BlockIcon from '@/material-icons/400-24px/block-fill.svg?react';
import { Domain } from 'mastodon/components/domain';
import { fetchDomainBlocks, expandDomainBlocks } from '../../actions/domain_blocks';
import { LoadingIndicator } from '../../components/loading_indicator';
import ScrollableList from '../../components/scrollable_list';
import Column from '../ui/components/column';
const messages = defineMessages({
heading: { id: 'column.domain_blocks', defaultMessage: 'Blocked domains' },
});
const mapStateToProps = state => ({
domains: state.getIn(['domain_lists', 'blocks', 'items']),
hasMore: !!state.getIn(['domain_lists', 'blocks', 'next']),
});
class Blocks extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
hasMore: PropTypes.bool,
domains: ImmutablePropTypes.orderedSet,
intl: PropTypes.object.isRequired,
multiColumn: PropTypes.bool,
};
UNSAFE_componentWillMount () {
this.props.dispatch(fetchDomainBlocks());
}
handleLoadMore = debounce(() => {
this.props.dispatch(expandDomainBlocks());
}, 300, { leading: true });
render () {
const { intl, domains, hasMore, multiColumn } = this.props;
if (!domains) {
return (
<Column>
<LoadingIndicator />
</Column>
);
}
const emptyMessage = <FormattedMessage id='empty_column.domain_blocks' defaultMessage='There are no blocked domains yet.' />;
return (
<Column bindToDocument={!multiColumn} icon='ban' iconComponent={BlockIcon} heading={intl.formatMessage(messages.heading)} alwaysShowBackButton>
<ScrollableList
scrollKey='domain_blocks'
onLoadMore={this.handleLoadMore}
hasMore={hasMore}
emptyMessage={emptyMessage}
bindToDocument={!multiColumn}
>
{domains.map(domain =>
<Domain key={domain} domain={domain} />,
)}
</ScrollableList>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</Column>
);
}
}
export default connect(mapStateToProps)(injectIntl(Blocks));

View file

@ -0,0 +1,113 @@
import { useEffect, useRef, useCallback, useState } from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { Helmet } from 'react-helmet';
import BlockIcon from '@/material-icons/400-24px/block-fill.svg?react';
import { apiGetDomainBlocks } from 'mastodon/api/domain_blocks';
import { Column } from 'mastodon/components/column';
import type { ColumnRef } from 'mastodon/components/column';
import { ColumnHeader } from 'mastodon/components/column_header';
import { Domain } from 'mastodon/components/domain';
import ScrollableList from 'mastodon/components/scrollable_list';
const messages = defineMessages({
heading: { id: 'column.domain_blocks', defaultMessage: 'Blocked domains' },
});
const Blocks: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
const intl = useIntl();
const [domains, setDomains] = useState<string[]>([]);
const [loading, setLoading] = useState(false);
const [next, setNext] = useState<string | undefined>();
const hasMore = !!next;
const columnRef = useRef<ColumnRef>(null);
useEffect(() => {
setLoading(true);
void apiGetDomainBlocks()
.then(({ domains, links }) => {
const next = links.refs.find((link) => link.rel === 'next');
setLoading(false);
setDomains(domains);
setNext(next?.uri);
return '';
})
.catch(() => {
setLoading(false);
});
}, [setLoading, setDomains, setNext]);
const handleLoadMore = useCallback(() => {
setLoading(true);
void apiGetDomainBlocks(next)
.then(({ domains, links }) => {
const next = links.refs.find((link) => link.rel === 'next');
setLoading(false);
setDomains((previousDomains) => [...previousDomains, ...domains]);
setNext(next?.uri);
return '';
})
.catch(() => {
setLoading(false);
});
}, [setLoading, setDomains, setNext, next]);
const handleHeaderClick = useCallback(() => {
columnRef.current?.scrollTop();
}, []);
const emptyMessage = (
<FormattedMessage
id='empty_column.domain_blocks'
defaultMessage='There are no blocked domains yet.'
/>
);
return (
<Column
bindToDocument={!multiColumn}
ref={columnRef}
label={intl.formatMessage(messages.heading)}
>
<ColumnHeader
icon='ban'
iconComponent={BlockIcon}
title={intl.formatMessage(messages.heading)}
onClick={handleHeaderClick}
multiColumn={multiColumn}
showBackButton
/>
<ScrollableList
scrollKey='domain_blocks'
onLoadMore={handleLoadMore}
hasMore={hasMore}
isLoading={loading}
showLoading={loading && domains.length === 0}
emptyMessage={emptyMessage}
trackScroll={!multiColumn}
bindToDocument={!multiColumn}
>
{domains.map((domain) => (
<Domain key={domain} domain={domain} />
))}
</ScrollableList>
<Helmet>
<title>{intl.formatMessage(messages.heading)}</title>
<meta name='robots' content='noindex' />
</Helmet>
</Column>
);
};
// eslint-disable-next-line import/no-default-export
export default Blocks;

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} publicació} other {{counter} publicacions}}",
"account.unblock": "Desbloca @{name}",
"account.unblock_domain": "Desbloca el domini {domain}",
"account.unblock_domain_short": "Desbloca",
"account.unblock_short": "Desbloca",
"account.unendorse": "No recomanis en el perfil",
"account.unfollow": "Deixa de seguir",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} příspěvek} few {{counter} příspěvky} many {{counter} příspěvků} other {{counter} příspěvků}}",
"account.unblock": "Odblokovat @{name}",
"account.unblock_domain": "Odblokovat doménu {domain}",
"account.unblock_domain_short": "Odblokovat",
"account.unblock_short": "Odblokovat",
"account.unendorse": "Nezvýrazňovat na profilu",
"account.unfollow": "Přestat sledovat",
@ -79,7 +80,7 @@
"admin.dashboard.retention.cohort_size": "Noví uživatelé",
"admin.impact_report.instance_accounts": "Profily účtů, které by byli odstaněny",
"admin.impact_report.instance_followers": "Sledující, o které by naši uživatelé přišli",
"admin.impact_report.instance_follows": "Sledující, o které by naši uživatelé přišli",
"admin.impact_report.instance_follows": "Sledující, o které by jejich uživatelé přišli",
"admin.impact_report.title": "Shrnutí dopadu",
"alert.rate_limited.message": "Zkuste to prosím znovu po {retry_time, time, medium}.",
"alert.rate_limited.title": "Spojení omezena",
@ -101,7 +102,7 @@
"annual_report.summary.archetype.replier": "Sociální motýlek",
"annual_report.summary.followers.followers": "sledujících",
"annual_report.summary.followers.total": "{count} celkem",
"annual_report.summary.here_it_is": "Zde je tvůj {year} v přehledu:",
"annual_report.summary.here_it_is": "Zde je tvůj rok {year} v přehledu:",
"annual_report.summary.highlighted_post.by_favourites": "nejvíce oblíbený příspěvek",
"annual_report.summary.highlighted_post.by_reblogs": "nejvíce boostovaný příspěvek",
"annual_report.summary.highlighted_post.by_replies": "příspěvek s nejvíce odpověďmi",
@ -267,7 +268,7 @@
"domain_pill.activitypub_like_language": "ActivityPub je jako jazyk, kterým Mastodon mluví s jinými sociálními sítěmi.",
"domain_pill.server": "Server",
"domain_pill.their_handle": "Handle:",
"domain_pill.their_server": "Jejich digitální domov, kde žijí jejich všechny příspěvky.",
"domain_pill.their_server": "Jejich digitální domov, kde žijí všechny jejich příspěvky.",
"domain_pill.their_username": "Jejich jedinečný identifikátor na jejich serveru. Je možné, že na jiných serverech jsou uživatelé se stejným uživatelským jménem.",
"domain_pill.username": "Uživatelské jméno",
"domain_pill.whats_in_a_handle": "Co obsahuje handle?",
@ -572,7 +573,7 @@
"notification.label.private_reply": "Privátní odpověď",
"notification.label.reply": "Odpověď",
"notification.mention": "Zmínka",
"notification.mentioned_you": "{name} vás zmínil",
"notification.mentioned_you": "{name} vás zmínil*a",
"notification.moderation-warning.learn_more": "Zjistit více",
"notification.moderation_warning": "Obdrželi jste varování od moderátorů",
"notification.moderation_warning.action_delete_statuses": "Některé z vašich příspěvků byly odstraněny.",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} postiad} two {{counter} bostiad} few {{counter} phostiad} many {{counter} postiad} other {{counter} postiad}}",
"account.unblock": "Dadrwystro @{name}",
"account.unblock_domain": "Dadrwystro parth {domain}",
"account.unblock_domain_short": "Dadrwystro",
"account.unblock_short": "Dadrwystro",
"account.unendorse": "Peidio a'i ddangos ar fy mhroffil",
"account.unfollow": "Dad-ddilyn",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} indlæg} other {{counter} indlæg}}",
"account.unblock": "Fjern blokering af @{name}",
"account.unblock_domain": "Fjern blokering af domænet {domain}",
"account.unblock_domain_short": "Afblokér",
"account.unblock_short": "Fjern blokering",
"account.unendorse": "Fjern visning på din profil",
"account.unfollow": "Følg ikke længere",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} Beitrag} other {{counter} Beiträge}}",
"account.unblock": "{name} nicht mehr blockieren",
"account.unblock_domain": "Blockierung von {domain} aufheben",
"account.unblock_domain_short": "Entsperren",
"account.unblock_short": "Blockierung aufheben",
"account.unendorse": "Im Profil nicht mehr empfehlen",
"account.unfollow": "Entfolgen",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} post} other {{counter} posts}}",
"account.unblock": "Unblock @{name}",
"account.unblock_domain": "Unblock domain {domain}",
"account.unblock_domain_short": "Unblock",
"account.unblock_short": "Unblock",
"account.unendorse": "Don't feature on profile",
"account.unfollow": "Unfollow",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} mensaje} other {{counter} mensajes}}",
"account.unblock": "Desbloquear a @{name}",
"account.unblock_domain": "Desbloquear dominio {domain}",
"account.unblock_domain_short": "Desbloquear",
"account.unblock_short": "Desbloquear",
"account.unendorse": "No destacar en el perfil",
"account.unfollow": "Dejar de seguir",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} publicación} other {{counter} publicaciones}}",
"account.unblock": "Desbloquear a @{name}",
"account.unblock_domain": "Mostrar a {domain}",
"account.unblock_domain_short": "Desbloquear",
"account.unblock_short": "Desbloquear",
"account.unendorse": "No mostrar en el perfil",
"account.unfollow": "Dejar de seguir",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} publicación} other {{counter} publicaciones}}",
"account.unblock": "Desbloquear a @{name}",
"account.unblock_domain": "Desbloquear dominio {domain}",
"account.unblock_domain_short": "Desbloquear",
"account.unblock_short": "Desbloquear",
"account.unendorse": "No mostrar en el perfil",
"account.unfollow": "Dejar de seguir",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}",
"account.unblock": "Kumoa käyttäjän @{name} esto",
"account.unblock_domain": "Kumoa verkkotunnuksen {domain} esto",
"account.unblock_domain_short": "Kumoa esto",
"account.unblock_short": "Kumoa esto",
"account.unendorse": "Kumoa suosittelu profiilissasi",
"account.unfollow": "Älä seuraa",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} postur} other {{counter} postar}}",
"account.unblock": "Banna ikki @{name}",
"account.unblock_domain": "Banna ikki økisnavnið {domain}",
"account.unblock_domain_short": "Banna ikki",
"account.unblock_short": "Banna ikki",
"account.unendorse": "Vís ikki á vanga",
"account.unfollow": "Fylg ikki",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} publicación} other {{counter} publicacións}}",
"account.unblock": "Desbloquear @{name}",
"account.unblock_domain": "Amosar {domain}",
"account.unblock_domain_short": "Desbloquear",
"account.unblock_short": "Desbloquear",
"account.unendorse": "Non amosar no perfil",
"account.unfollow": "Deixar de seguir",

View file

@ -64,8 +64,9 @@
"account.show_reblogs": "הצג הדהודים מאת @{name}",
"account.statuses_counter": "{count, plural, one {הודעה אחת} two {הודעותיים} many {{counter} הודעות} other {{counter} הודעות}}",
"account.unblock": "להסיר חסימה ל- @{name}",
"account.unblock_domain": "הסירי את החסימה של קהילת {domain}",
"account.unblock_short": "הסר חסימה",
"account.unblock_domain": "הסרת החסימה של קהילת {domain}",
"account.unblock_domain_short": "הסרת חסימה",
"account.unblock_short": "הסרת חסימה",
"account.unendorse": "אל תקדם בפרופיל",
"account.unfollow": "הפסקת מעקב",
"account.unmute": "הפסקת השתקת @{name}",
@ -905,6 +906,12 @@
"video.expand": "להרחיב וידאו",
"video.fullscreen": "מסך מלא",
"video.hide": "להסתיר וידאו",
"video.mute": "השתקה",
"video.pause": "השהיה",
"video.play": "ניגון"
"video.play": "ניגון",
"video.skip_backward": "דילוג אחורה",
"video.skip_forward": "דילוג קדימה",
"video.unmute": "ביטול השתקה",
"video.volume_down": "הנמכת עוצמת השמע",
"video.volume_up": "הגברת עוצמת שמע"
}

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} bejegyzés} other {{counter} bejegyzés}}",
"account.unblock": "@{name} letiltásának feloldása",
"account.unblock_domain": "{domain} domain tiltásának feloldása",
"account.unblock_domain_short": "Tiltás feloldása",
"account.unblock_short": "Tiltás feloldása",
"account.unendorse": "Ne jelenjen meg a profilodon",
"account.unfollow": "Követés megszüntetése",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} færsla} other {{counter} færslur}}",
"account.unblock": "Aflétta útilokun af @{name}",
"account.unblock_domain": "Aflétta útilokun lénsins {domain}",
"account.unblock_domain_short": "Aflétta útilokun",
"account.unblock_short": "Hætta að loka á",
"account.unendorse": "Ekki birta á notandasniði",
"account.unfollow": "Hætta að fylgja",

View file

@ -70,7 +70,7 @@
"account.unfollow": "Smetti di seguire",
"account.unmute": "Riattiva @{name}",
"account.unmute_notifications_short": "Riattiva notifiche",
"account.unmute_short": "Riattiva",
"account.unmute_short": "Attiva audio",
"account_note.placeholder": "Clicca per aggiungere una nota",
"admin.dashboard.daily_retention": "Tasso di ritenzione dell'utente per giorno, dopo la registrazione",
"admin.dashboard.monthly_retention": "Tasso di ritenzione dell'utente per mese, dopo la registrazione",
@ -905,6 +905,12 @@
"video.expand": "Espandi il video",
"video.fullscreen": "Schermo intero",
"video.hide": "Nascondi il video",
"video.mute": "Muta",
"video.pause": "Pausa",
"video.play": "Riproduci"
"video.play": "Riproduci",
"video.skip_backward": "Vai indietro",
"video.skip_forward": "Vai avanti",
"video.unmute": "Muta",
"video.volume_down": "Abbassa volume",
"video.volume_up": "Alza volume"
}

View file

@ -61,6 +61,7 @@
"account.statuses_counter": "{count, plural, one {{counter} n tsuffeɣt} other {{counter} n tsuffaɣ}}",
"account.unblock": "Serreḥ i @{name}",
"account.unblock_domain": "Ssken-d {domain}",
"account.unblock_domain_short": "Serreḥ",
"account.unblock_short": "Serreḥ",
"account.unendorse": "Ur ttwellih ara fell-as deg umaɣnu-inek",
"account.unfollow": "Ur ṭṭafaṛ ara",
@ -77,6 +78,7 @@
"alt_text_modal.cancel": "Semmet",
"alt_text_modal.done": "Immed",
"announcement.announcement": "Ulɣu",
"annual_report.summary.most_used_app.most_used_app": "asnas yettwasqedcen s waṭas",
"annual_report.summary.most_used_hashtag.none": "Ula yiwen",
"annual_report.summary.new_posts.new_posts": "tisuffaɣ timaynutin",
"audio.hide": "Ffer amesli",
@ -162,6 +164,7 @@
"confirmations.discard_edit_media.confirm": "Sefsex",
"confirmations.edit.confirm": "Ẓreg",
"confirmations.edit.message": "Abeddel tura ad d-yaru izen-nni i d-tegreḍ akka tura. Tetḥeqqeḍ tebɣiḍ ad tkemmleḍ?",
"confirmations.follow_to_list.confirm": "Ḍfeṛ-it sakin rnu-t ɣer tebdart",
"confirmations.logout.confirm": "Ffeɣ",
"confirmations.logout.message": "D tidet tebɣiḍ ad teffɣeḍ?",
"confirmations.logout.title": "Tebɣiḍ ad teffɣeḍ ssya?",
@ -245,6 +248,7 @@
"filter_modal.select_filter.search": "Nadi neɣ snulfu-d",
"filter_modal.select_filter.title": "Sizdeg tassufeɣt-a",
"filter_modal.title.status": "Sizdeg tassufeɣt",
"filtered_notifications_banner.title": "Ilɣa yettwasizdgen",
"firehose.all": "Akk",
"firehose.local": "Deg uqeddac-ayi",
"firehose.remote": "Iqeddacen nniḍen",
@ -350,9 +354,12 @@
"lists.add_to_lists": "Rnu {name} ɣer tebdarin",
"lists.create": "Snulfu-d",
"lists.delete": "Kkes tabdart",
"lists.done": "Immed",
"lists.edit": "Ẓreg tabdart",
"lists.list_name": "Isem n tebdart",
"lists.new_list_name": "Isem n tebdart tamaynut",
"lists.no_lists_yet": "Ulac tibdarin akka tura.",
"lists.no_results_found": "Ulac igemmad.",
"lists.remove_member": "Kkes",
"lists.replies_policy.followed": "Kra n useqdac i yettwaḍefren",
"lists.replies_policy.list": "Iɛeggalen n tebdart",
@ -389,6 +396,7 @@
"navigation_bar.follows_and_followers": "Imeḍfaṛen akked wid i teṭṭafaṛeḍ",
"navigation_bar.lists": "Tibdarin",
"navigation_bar.logout": "Ffeɣ",
"navigation_bar.moderation": "Aseɣyed",
"navigation_bar.mutes": "Iseqdacen yettwasusmen",
"navigation_bar.opened_in_classic_interface": "Tisuffaɣ, imiḍanen akked isebtar-nniḍen igejdanen ldin-d s wudem amezwer deg ugrudem web aklasiki.",
"navigation_bar.personal": "Udmawan",
@ -419,6 +427,7 @@
"notification_requests.edit_selection": "Ẓreg",
"notification_requests.exit_selection": "Immed",
"notification_requests.notifications_from": "Alɣuten sɣur {name}",
"notification_requests.title": "Ilɣa yettwasizdgen",
"notifications.clear": "Sfeḍ alɣuten",
"notifications.clear_confirmation": "Tebɣiḍ s tidet ad tekkseḍ akk alɣuten-inek·em i lebda?",
"notifications.column_settings.admin.report": "Ineqqisen imaynuten:",
@ -463,6 +472,7 @@
"onboarding.follows.back": "Uɣal",
"onboarding.follows.done": "Immed",
"onboarding.follows.search": "Nadi",
"onboarding.follows.title": "Ḍfeṛ walbɛaḍ i wakken ad ttebdud",
"onboarding.profile.display_name": "Isem ara d-yettwaskanen",
"onboarding.profile.display_name_hint": "Isem-ik·im ummid neɣ isem-ik·im n uqeṣṣer…",
"onboarding.profile.note": "Tameddurt",
@ -484,15 +494,18 @@
"poll_button.remove_poll": "Kkes asenqed",
"privacy.change": "Seggem tabaḍnit n yizen",
"privacy.direct.long": "Wid akk i d-yettwabdaren deg tsuffeɣt",
"privacy.direct.short": "Abdar uslig",
"privacy.private.long": "Ala wid i k·m-yeṭṭafaṛen",
"privacy.private.short": "Imeḍfaren",
"privacy.public.long": "Kra n win yellan deg Masṭudun neɣ berra-s",
"privacy.public.short": "Azayez",
"privacy.unlisted.long": "Kra kan yiwarzimen",
"privacy.unlisted.short": "Azayez asusam",
"privacy_policy.last_updated": "Aleqqem aneggaru {date}",
"privacy_policy.title": "Tasertit tabaḍnit",
"recommended": "Yettuwelleh",
"refresh": "Smiren",
"regeneration_indicator.please_stand_by": "Ttxil rǧu.",
"relative_time.days": "{number}u",
"relative_time.full.just_now": "tura kan",
"relative_time.hours": "{number}isr",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} bericht} other {{counter} berichten}}",
"account.unblock": "@{name} deblokkeren",
"account.unblock_domain": "{domain} niet langer blokkeren",
"account.unblock_domain_short": "Deblokkeren",
"account.unblock_short": "Deblokkeren",
"account.unendorse": "Niet op profiel weergeven",
"account.unfollow": "Ontvolgen",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} publicação} other {{counter} publicações}}",
"account.unblock": "Desbloquear @{name}",
"account.unblock_domain": "Desbloquear o domínio {domain}",
"account.unblock_domain_short": "Desbloquear",
"account.unblock_short": "Desbloquear",
"account.unendorse": "Não destacar no perfil",
"account.unfollow": "Deixar de seguir",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} postim} other {{counter} postime}}",
"account.unblock": "Zhbllokoje @{name}",
"account.unblock_domain": "Zhblloko përkatësinë {domain}",
"account.unblock_domain_short": "Zhbllokoje",
"account.unblock_short": "Zhbllokoje",
"account.unendorse": "Mos e përfshi në profil",
"account.unfollow": "Resht së ndjekuri",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} gönderi} other {{counter} gönderi}}",
"account.unblock": "@{name} adlı kişinin engelini kaldır",
"account.unblock_domain": "{domain} alan adının engelini kaldır",
"account.unblock_domain_short": "Engeli kaldır",
"account.unblock_short": "Engeli kaldır",
"account.unendorse": "Profilimde öne çıkarma",
"account.unfollow": "Takibi bırak",
@ -905,6 +906,12 @@
"video.expand": "Videoyu genişlet",
"video.fullscreen": "Tam ekran",
"video.hide": "Videoyu gizle",
"video.mute": "Sessiz",
"video.pause": "Duraklat",
"video.play": "Oynat"
"video.play": "Oynat",
"video.skip_backward": "Geriye atla",
"video.skip_forward": "İleriye atla",
"video.unmute": "Sesi aç",
"video.volume_down": "Sesi kıs",
"video.volume_up": "Sesi yükselt"
}

View file

@ -1,21 +1,34 @@
{
"about.blocks": "ئوتتۇراھال مۇلازىمېتىر",
"about.contact": "ئالاقىلاشقۇچى:",
"account.badges.bot": "Bot",
"account.cancel_follow_request": "Withdraw follow request",
"account.posts": "Toots",
"account.posts_with_replies": "Toots and replies",
"about.blocks": "باشقۇرۇلىدىغان مۇلازىمېتىر",
"about.contact": "ئالاقە:",
"about.disclaimer": "Mastodon ھەقسىز، ئوچۇق كودلۇق يۇمشاق دېتال تاۋار ماركىسى Mastodon gGmbH غا تەۋە.",
"about.domain_blocks.no_reason_available": "سەۋەبىنى ئىشلەتكىلى بولمايدۇ",
"account.badges.bot": "ماشىنا ئادەم",
"account.cancel_follow_request": "ئەگىشىش ئىلتىماسىدىن ۋاز كەچ",
"account.posts": "يازما",
"account.posts_with_replies": "يازما ۋە ئىنكاس",
"account.report": "@{name} نى پاش قىل",
"account.requested": "Awaiting approval",
"account_note.placeholder": "Click to add a note",
"column.pins": "Pinned toot",
"community.column_settings.media_only": "Media only",
"account_note.placeholder": "چېكىلسە ئىزاھات قوشىدۇ",
"column.pins": "چوققىلانغان يازما",
"community.column_settings.media_only": "ۋاسىتەلا",
"compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
"compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
"compose_form.placeholder": "What is on your mind?",
"compose_form.publish_form": "Publish",
"compose_form.spoiler.marked": "Text is hidden behind warning",
"compose_form.publish_form": "يېڭى يازما",
"compose_form.reply": "جاۋاب",
"compose_form.save_changes": "يېڭىلا",
"compose_form.spoiler.marked": "مەزمۇن ئاگاھلاندۇرۇشىنى چىقىرىۋەت",
"compose_form.spoiler.unmarked": "Text is not hidden",
"confirmations.delete.message": "Are you sure you want to delete this status?",
"compose_form.spoiler_placeholder": "مەزمۇن ئاگاھلاندۇرۇشى (تاللاشچان)",
"confirmation_modal.cancel": "ۋاز كەچ",
"confirmations.block.confirm": "توس",
"confirmations.delete.message": "بۇ يازمىنى راستىنلا ئۆچۈرەمسىز؟",
"confirmations.delete.title": "يازما ئۆچۈرەمدۇ؟",
"confirmations.delete_list.confirm": "ئۆچۈر",
"confirmations.delete_list.message": "بۇ تىزىمنى راستتىنلا مەڭگۈلۈك ئۆچۈرەمسىز؟",
"confirmations.delete_list.title": "تىزىمنى ئۆچۈرەمدۇ؟",
"confirmations.discard_edit_media.confirm": "تاشلىۋەت",
"embed.instructions": "Embed this status on your website by copying the code below.",
"empty_column.account_timeline": "No toots here!",
"empty_column.bookmarked_statuses": "You don't have any bookmarked toots yet. When you bookmark one, it will show up here.",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, one {{counter} допис} few {{counter} дописи} many {{counter} дописів} other {{counter} допис}}",
"account.unblock": "Розблокувати @{name}",
"account.unblock_domain": "Розблокувати {domain}",
"account.unblock_domain_short": "Розблокувати",
"account.unblock_short": "Розблокувати",
"account.unendorse": "Не публікувати у профілі",
"account.unfollow": "Відписатися",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, other {{counter} Tút}}",
"account.unblock": "Bỏ chặn @{name}",
"account.unblock_domain": "Bỏ ẩn {domain}",
"account.unblock_domain_short": "Bỏ chặn",
"account.unblock_short": "Bỏ chặn",
"account.unendorse": "Ngưng tôn vinh người này",
"account.unfollow": "Bỏ theo dõi",

View file

@ -65,6 +65,7 @@
"account.statuses_counter": "{count, plural, other {{count} 則嘟文}}",
"account.unblock": "解除封鎖 @{name}",
"account.unblock_domain": "解除封鎖網域 {domain}",
"account.unblock_domain_short": "解除封鎖",
"account.unblock_short": "解除封鎖",
"account.unendorse": "取消於個人檔案推薦對方",
"account.unfollow": "取消跟隨",

View file

@ -1,26 +0,0 @@
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable';
import {
DOMAIN_BLOCKS_FETCH_SUCCESS,
DOMAIN_BLOCKS_EXPAND_SUCCESS,
unblockDomainSuccess
} from '../actions/domain_blocks';
const initialState = ImmutableMap({
blocks: ImmutableMap({
items: ImmutableOrderedSet(),
}),
});
export default function domainLists(state = initialState, action) {
switch(action.type) {
case DOMAIN_BLOCKS_FETCH_SUCCESS:
return state.setIn(['blocks', 'items'], ImmutableOrderedSet(action.domains)).setIn(['blocks', 'next'], action.next);
case DOMAIN_BLOCKS_EXPAND_SUCCESS:
return state.updateIn(['blocks', 'items'], set => set.union(action.domains)).setIn(['blocks', 'next'], action.next);
case unblockDomainSuccess.type:
return state.updateIn(['blocks', 'items'], set => set.delete(action.payload.domain));
default:
return state;
}
}

View file

@ -11,7 +11,6 @@ import { composeReducer } from './compose';
import contexts from './contexts';
import conversations from './conversations';
import custom_emojis from './custom_emojis';
import domain_lists from './domain_lists';
import { dropdownMenuReducer } from './dropdown_menu';
import filters from './filters';
import followed_tags from './followed_tags';
@ -49,7 +48,6 @@ const reducers = {
loadingBar: loadingBarReducer,
modal: modalReducer,
user_lists,
domain_lists,
status_lists,
accounts: accountsReducer,
accounts_map,

View file

@ -1882,29 +1882,21 @@ body > [data-popper-placement] {
}
.domain {
padding: 10px;
padding: 16px;
border-bottom: 1px solid var(--background-border-color);
display: flex;
align-items: center;
gap: 8px;
.domain__domain-name {
&__domain-name {
flex: 1 1 auto;
display: block;
color: $primary-text-color;
text-decoration: none;
font-size: 14px;
font-size: 15px;
line-height: 21px;
font-weight: 500;
}
}
.domain__wrapper {
display: flex;
}
.domain_buttons {
height: 18px;
padding: 10px;
white-space: nowrap;
}
.account {
padding: 16px;
border-bottom: 1px solid var(--background-border-color);

View file

@ -130,12 +130,7 @@ class ActivityPub::Activity
def first_mentioned_local_account
audience = (as_array(@json['to']) + as_array(@json['cc'])).map { |x| value_or_id(x) }.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
ActivityPub::TagManager.instance.uris_to_local_accounts(audience).first
end
def first_local_follower

View file

@ -412,11 +412,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
def addresses_local_accounts?
return true if @options[:delivered_to_account_id]
local_usernames = (audience_to + audience_cc).uniq.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }.map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) }
return false if local_usernames.empty?
Account.local.exists?(username: local_usernames)
ActivityPub::TagManager.instance.uris_to_local_accounts((audience_to + audience_cc).uniq).exists?
end
def tombstone_exists?

View file

@ -203,6 +203,19 @@ class ActivityPub::TagManager
path_params[param]
end
def uris_to_local_accounts(uris)
usernames = []
ids = []
uris.each do |uri|
param, value = uri_to_local_account_params(uri)
usernames << value.downcase if param == :username
ids << value if param == :id
end
Account.local.with_username(usernames).or(Account.local.where(id: ids))
end
def uri_to_actor(uri)
uri_to_resource(uri, Account)
end
@ -213,7 +226,7 @@ class ActivityPub::TagManager
if local_uri?(uri)
case klass.name
when 'Account'
klass.find_local(uri_to_local_id(uri, :username))
uris_to_local_accounts([uri]).first
else
StatusFinder.new(uri).status
end
@ -225,4 +238,20 @@ class ActivityPub::TagManager
rescue ActiveRecord::RecordNotFound
nil
end
private
def uri_to_local_account_params(uri)
return unless local_uri?(uri)
path_params = Rails.application.routes.recognize_path(uri)
# TODO: handle numeric IDs
case path_params[:controller]
when 'accounts'
[:username, path_params[:username]]
when 'instance_actors'
[:id, -99]
end
end
end

View file

@ -53,11 +53,11 @@ class Fasp::Request
def validate!(response)
content_digest_header = response.headers['content-digest']
raise SignatureVerification::SignatureVerificationError, 'content-digest missing' if content_digest_header.blank?
raise SignatureVerification::SignatureVerificationError, 'content-digest does not match' if content_digest_header != content_digest(response.body)
raise Mastodon::SignatureVerificationError, 'content-digest missing' if content_digest_header.blank?
raise Mastodon::SignatureVerificationError, 'content-digest does not match' if content_digest_header != content_digest(response.body)
signature_input = response.headers['signature-input']&.encode('UTF-8')
raise SignatureVerification::SignatureVerificationError, 'signature-input is missing' if signature_input.blank?
raise Mastodon::SignatureVerificationError, 'signature-input is missing' if signature_input.blank?
linzer_response = Linzer.new_response(
response.body,

View file

@ -23,6 +23,8 @@
class Poll < ApplicationRecord
include Expireable
MAKE_FETCH_HAPPEN = 1.minute
belongs_to :account
belongs_to :status
@ -113,7 +115,7 @@ class Poll < ApplicationRecord
end
def time_passed_since_last_fetch?
last_fetched_at.nil? || last_fetched_at < 1.minute.ago
last_fetched_at.nil? || last_fetched_at < MAKE_FETCH_HAPPEN.ago
end
def show_totals_now?

View file

@ -30,10 +30,7 @@ class ActivityPub::SynchronizeFollowersService < BaseService
# Account record, and should we not do that, we should have sent a Delete.
# In any case there is not much we can do if that occurs.
# TODO: this will need changes when switching to numeric IDs
usernames = items.filter_map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username)&.downcase }
Account.local.with_username(usernames)
ActivityPub::TagManager.instance.uris_to_local_accounts(items)
end
def remove_unexpected_local_followers!

View file

@ -79,6 +79,8 @@ br:
public: Publik
reject: Nac'hañ
remove_header: Dilemel an talbenn
resend_confirmation:
send: Adkas al liamm-kadarnaat
reset: Adderaouekaat
reset_password: Adderaouekaat ar ger-tremen
resubscribe: Adkoumanantiñ
@ -99,6 +101,12 @@ br:
web: Web
action_logs:
action_types:
approve_user: Aprouiñ an implijer
change_role_user: Kemmañ perzh an implijer
confirm_user: Aprouiñ an implijer
create_ip_block: Krouiñ ur reolenn IP
create_user_role: Krouiñ ur perzh
destroy_ip_block: Dilemel ar reolenn IP
destroy_status: Dilemel ar c'hannad
reset_password_user: Adderaouekaat ar ger-tremen
update_status: Hizivaat ar c'hannad
@ -141,12 +149,15 @@ br:
export: Ezporzhiañ
import: Enporzhiañ
domain_blocks:
confirm_suspension:
cancel: Nullañ
domain: Domani
new:
create: Sevel ur stanker
severity:
noop: Hini ebet
suspend: Astalañ
public_comment: Evezhiadenn foran
email_domain_blocks:
add_new: Ouzhpenniñ unan nevez
delete: Dilemel
@ -158,6 +169,18 @@ br:
create: Ouzhpenniñ un domani
export_domain_allows:
no_file: Restr ebet diuzet
fasp:
debug:
callbacks:
delete: Dilemel
ip: Chomlec'h IP
providers:
active: Oberiant
delete: Dilemel
name: Anv
registrations:
confirm: Kadarnaat
status: Statud
follow_recommendations:
status: Statud
suppressed: Dilamet
@ -172,6 +195,7 @@ br:
suspend: Astalañ
policy: Reolennoù
dashboard:
instance_languages_dimension: Yezhoù pennañ
instance_statuses_measure: toudoù stoket
delivery:
all: Pep tra
@ -182,6 +206,9 @@ br:
title: Habaskadur
purge: Spurjañ
title: Kevread
total_blocked_by_us: Stanket ganeomp
total_followed_by_them: Heuliet ganto
total_followed_by_us: Heuliet ganeomp
total_storage: Restroù media stag
invites:
filter:
@ -191,6 +218,7 @@ br:
title: Sil
title: Pedadennoù
ip_blocks:
add_new: Krouiñ ur reolenn
delete: Dilemel
expires_in:
'1209600': 2 sizhunvezh
@ -198,6 +226,9 @@ br:
'31556952': 1 bloavezh
'86400': 1 devezh
'94670856': 3 bloavezh
new:
title: Krouiñ ur reolenn IP nevez
title: Reolennoù IP
relays:
delete: Dilemel
disable: Diweredekaat
@ -218,6 +249,7 @@ br:
are_you_sure: Ha sur oc'h?
comment:
none: Hini ebet
confirm: Kadarnaat
delete_and_resolve: Dilemel ar c'hannadoù
forwarded: Treuzkaset
no_one_assigned: Den ebet

View file

@ -232,7 +232,7 @@ he:
silence_account: הגבלת חשבון
suspend_account: השעיית חשבון
unassigned_report: ביטול הקצאת דו"ח
unblock_email_account: ביטול חסימת כתובת דוא"ל
unblock_email_account: הסרת חסימת כתובת דוא"ל
unsensitive_account: ביטול Force-Sensitive לחשבון
unsilence_account: ביטול השתקת חשבון
unsuspend_account: ביטול השעיית חשבון
@ -263,11 +263,11 @@ he:
create_user_role_html: "%{name} יצר את התפקיד של %{target}"
demote_user_html: "%{name} הוריד/ה בדרגה את המשתמש %{target}"
destroy_announcement_html: "%{name} מחק/ה את ההכרזה %{target}"
destroy_canonical_email_block_html: "%{name} הסיר חסימה מדואל %{target}"
destroy_canonical_email_block_html: "%{name} הסירו חסימה מדואל %{target}"
destroy_custom_emoji_html: "%{name} מחק אמוג'י של %{target}"
destroy_domain_allow_html: "%{name} לא התיר/ה פדרציה עם הדומיין %{target}"
destroy_domain_block_html: "%{name} הסיר/ה חסימה מהדומיין %{target}"
destroy_email_domain_block_html: '%{name} הסיר/ה חסימה מדומיין הדוא"ל %{target}'
destroy_domain_block_html: החסימה על מתחם %{target} הוסרה ע"י %{name}
destroy_email_domain_block_html: הוסרה חסימת מתחם דוא"ל %{target} בידי %{name}
destroy_instance_html: "%{name} טיהר/ה את הדומיין %{target}"
destroy_ip_block_html: "%{name} מחק/ה את הכלל עבור IP %{target}"
destroy_relay_html: "%{name} מחקו את הממסר %{target}"
@ -495,6 +495,36 @@ he:
new:
title: יבוא רשימת שרתים חסומים
no_file: לא נבחר קובץ
fasp:
debug:
callbacks:
created_at: תאריך יצירה
delete: מחיקה
ip: כתובת IP
request_body: גוף הבקשה
title: ניפוי תקלות בקריאות חוזרות
providers:
active: פעילים
base_url: קישור בסיס
callback: קריאה חוזרת
delete: מחיקה
edit: עריכת ספק
finish_registration: סיום הרשמה
name: שם
providers: ספקים
public_key_fingerprint: טביעת האצבע של המפתח הציבורי
registration_requested: נדרשת הרשמה
registrations:
confirm: אישור
description: קיבלת הרשמה דרך FASP. יש לדחות אותה אם לא ביקשת את ההרשמה הזו מיוזמתך. אם זו בקשה מיוזמתך, יש להשוות בהקפדה אם השם וטביעת האצבע של המפתח הציבורי תואמים לפני אישור הרישום.
reject: דחיה
title: אישור הרשמת FASP
save: שמירה
select_capabilities: בחירת יכולות
sign_in: כניסה
status: מצב
title: ספקי משנה לפדיוורס
title: פרוטוקול FASP
follow_recommendations:
description_html: "<strong>עקבו אחר ההמלצות על מנת לעזור למשתמשים חדשים למצוא תוכן מעניין</strong>. במידה ומשתמש לא תקשר מספיק עם משתמשים אחרים כדי ליצור המלצות מעקב, חשבונות אלה יומלצו במקום. הם מחושבים מחדש על בסיסי יומיומי מתערובת של החשבונות הפעילים ביותר עם החשבונות הנעקבים ביותר עבור שפה נתונה."
language: עבור שפה

View file

@ -479,6 +479,36 @@ it:
new:
title: Importare i blocchi di dominio
no_file: Nessun file selezionato
fasp:
debug:
callbacks:
created_at: Creato il
delete: Cancella
ip: Indirizzo IP
request_body: Request body
title: Debug Callbacks
providers:
active: Attivo
base_url: Url di base
callback: Callback
delete: Cancella
edit: Modifica Provider
finish_registration: Registrazione terminata
name: Nome
providers: Providers
public_key_fingerprint: Chiave pubblica fingerprint
registration_requested: Registrazione richiesta
registrations:
confirm: Conferma
description: Hai ricevuto una registrazione da un FASP. Rifiutala se non l'hai avviata tu. Se l'hai avviata tu, confronta attentamente nome e impronta della chiave prima di confermare la registrazione.
reject: Rifiuta
title: Conferma registrazione FASP
save: Salva
select_capabilities: Seleziona Capacità
sign_in: Connettiti
status: Stato
title: Fornitori di Servizi Ausiliari per il Fediverso
title: FASP
follow_recommendations:
description_html: "<strong>I consigli su chi seguire aiutano i nuovi utenti a trovare rapidamente dei contenuti interessanti</strong>. Quando un utente non ha interagito abbastanza con altri per avere dei consigli personalizzati, vengono consigliati questi account. Sono ricalcolati ogni giorno da un misto di account con le più alte interazioni recenti e con il maggior numero di seguaci locali per una data lingua."
language: Per lingua

View file

@ -268,6 +268,15 @@ kab:
no_file: Ula d yiwen ufaylu ma yettwafran
export_domain_blocks:
no_file: Ulac afaylu yettwafernen
fasp:
debug:
callbacks:
delete: Kkes
ip: Tansa IP
providers:
delete: Kkes
save: Sekles
title: FASP
follow_recommendations:
language: I tutlayt
status: Addad
@ -378,6 +387,7 @@ kab:
everyone: Tisirag timezwura
privileges:
administrator: Anedbal
view_dashboard: Timẓriwt n tfelwit
rules:
add_new: Rnu alugen
delete: Kkes
@ -391,6 +401,7 @@ kab:
title: Udem
discovery:
profile_directory: Akaram n imaɣnuten
title: Asnirem
trends: Ayen mucaɛen
domain_blocks:
all: I medden akk
@ -431,6 +442,9 @@ kab:
software_version_patch_check:
action: Wali ileqqman yellan
tags:
name: Isem
newest: Amaynut
oldest: Aqbur
search: Anadi
title: Ihacṭagen
terms_of_service:
@ -705,6 +719,7 @@ kab:
units:
billion: AṬ
million: A
thousand: GM
trillion: Am
otp_authentication:
enable: Rmed
@ -864,6 +879,7 @@ kab:
warning:
categories:
spam: Aspam
reason: 'Taɣẓint:'
title:
disable: Amiḍan i igersen
none: Ɣur-wat

View file

@ -304,6 +304,7 @@ lv:
title: Audita žurnāls
unavailable_instance: "(domēna vārds nav pieejams)"
announcements:
back: Atgriezties pie paziņojumiem
destroyed_msg: Paziņojums sekmīgi izdzēsts.
edit:
title: Labot paziņojumu
@ -312,6 +313,9 @@ lv:
new:
create: Izveidot paziņojumu
title: Jauns paziņojums
preview:
explanation_html: 'E-pasta ziņojums tiks nosūtīts <strong>%{display_count} lietotājiem</strong>. Šis teksts tiks iekļauts e-pasta ziņojumā:'
title: Priekšskatīt paziņojumu
publish: Publicēt
published_msg: Paziņojums sekmīgi publicēts.
scheduled_for: Plānots uz %{time}
@ -455,7 +459,9 @@ lv:
create: Pievienot domēnu
resolve: Atrisināt domēnu
title: Liegt jaunu e-pasta domēnu
no_email_domain_block_selected: Neviens e-pasta domēna bloks netika mainīts, jo neviens netika atlasīts
not_permitted: Nav atļauta
resolved_dns_records_hint_html: Domēna vārds saistās ar zemāk norādītajiem MX domēniem, kuri beigās ir atbildīgi par e-pasta pieņemšana. MX domēna liegšana liegs reģistrēšanos no jebkuras e-pasta adreses, kas izmanto to pašu MX domēnu, pat ja redzamais domēna vārds ir atšķirīgs. <strong>Jāuzmanās, lai neliegtu galvenos e-pasta pakalpojuma sniedzējus.</strong>
resolved_through_html: Atrisināts, izmantojot %{domain}
title: Bloķētie e-pasta domēni
export_domain_allows:
@ -473,6 +479,13 @@ lv:
new:
title: Importēt bloķētos domēnus
no_file: Nav atlasīts neviens fails
fasp:
debug:
callbacks:
created_at: Izveidots
delete: Izdzēst
ip: IP adrese
request_body: Pieprasījuma saturs
follow_recommendations:
description_html: "<strong>Sekošanas ieteikumi palīdz jauniem lietotājiem ātri arast saistošu saturu</strong>. Kad lietotājs nav pietiekami mijiedarbojies ar citiem, lai veidotos pielāgoti sekošanas iteikumi, tiek ieteikti šie konti. Tie tiek pārskaitļoti ik dienas, izmantojot kontu, kuriem ir augstākās nesenās iesaistīšanās un lielākais vietējo sekotāju skaits norādītajā valodā."
language: Valodai
@ -934,6 +947,7 @@ lv:
chance_to_review_html: "<strong>Izveidotie pakalpojuma izmantošanas noteikumi netiks laisti klajā automātiski.</strong> Būs iespēja izskatīt iznākumu. Lūgums norādīt nepieciešamo informāciju, lai turpinātu."
explanation_html: Pakalpojuma izmantošanas noteikumu sagatave tiek piedāvāta tikai izzināšanas nolūkam, un to nevajadzētu izmantot kā juridisku padomu jebkurā jautājumā. Lūgums sazināties ar savu juridisko padomdevēju par saviem apstākļiem un noteiktiem juridiskiem jautājumiem.
title: Pakalpojuma izmantošānas noteikumu uzstādīšana
going_live_on_html: Darbībā, spēkā no %{date}
history: Vēsture
live: Darbībā
no_history: Nav ierakstu par pakalpojuma izmantošanas noteikumu izmaiņām.
@ -1060,6 +1074,7 @@ lv:
admin_mailer:
auto_close_registrations:
body: Nesenu satura pārraudzības darbību trūkuma dēļ reģistrācija %{instance} ir automātiski pārslēgta nepieciešamība pēc pašrocīgas izskatīšanas, lai novērstu %{instance} izmantošana kā platformu iespējami sliktiem dalībniekiem. Jebkurā brīdī var ieslēgt atpakaļ atvērtu reģistrēšanos.
subject: Reģistrēšanās %{instance} tika automātiski pārslēgta, lai pieprasītu apstiprināšanu
new_appeal:
actions:
delete_statuses: lai izdzēstu viņu ierakstus
@ -1186,6 +1201,7 @@ lv:
set_new_password: Iestatīt jaunu paroli
setup:
email_below_hint_html: Jāpārbauda sava surogātpasta mape vai jāpieprasa vēl vienu! Savu e-pasta adresi var labot, ja tā ir nepareiza.
email_settings_hint_html: Jāatver saite, kuru mēs nosūtījām uz %{email}, lai sāktu izmantot Mastodon. Mēs gaidīsim šeit pat.
link_not_received: Vai nesaņēmi sati?
new_confirmation_instructions_sent: Pēc dažām minūtēm saņemsi jaunu e-pasta ziņojumu ar apstiprinājuma saiti.
title: Pārbaudi savu iesūtni
@ -1194,21 +1210,27 @@ lv:
title: Pieteikties %{domain}
sign_up:
manual_review: Reģistrāciju %{domain} pašrocīgi izskata mūsu satura pārraudzītāji. Lai palīdzētu mums apstrādāt Tavu reģistrāciju, uzraksti mazliet par sevi un to, kāpēc vēlies kontu %{domain}!
preamble: Ar kontu šajā Mastodon serverī varēsi sekot jebkuram citam cilvēkam fediversā, neatkarīgi no tā, kur tiek mitināts viņu konts.
title: Atļauj tevi iestatīt %{domain}.
status:
account_status: Konta statuss
confirming: Gaida e-pasta adreses apstiprināšanas pabeigšanu.
functional: Tavs konts ir pilnā darba kārtībā.
pending: Tavs pieteikums ir rindā uz izskatīšanu, ko veic mūsu personāls. Tas var aizņemt kādu laiku. Tu saņemsi e-pasta ziņojumu, ja Tavs pieteikums tiks apstiprināts.
redirecting_to: Tavs konts ir neaktīvs, jo pašlaik tas tiek novirzīts uz %{acct}.
self_destruct: Tā kā %{domain} tiek slēgts, tu iegūsi tikai ierobežotu piekļuvi savam kontam.
view_strikes: Skati iepriekšējos brīdinājumus par savu kontu
too_fast: Veidlapa ir iesniegta pārāk ātri, mēģini vēlreiz.
use_security_key: Lietot drošības atslēgu
user_agreement_html: Es esmu izlasījis un piekrītu <a href="%{terms_of_service_path}" target="_blank">pakalpojuma izmantošanas noteikumiem</a> un <a href="%{privacy_policy_path}" target="_blank">privātuma nosacījumiem</a>
user_privacy_agreement_html: Es izlasīju un piekrītu <a href="%{privacy_policy_path}" target="_blank">privātuma pamatnostādnēm</a>
author_attribution:
example_title: Parauga teksts
hint_html: Vai Tu Raksti ziņu vai emuāra rakstus ārpus Mastodon? Pārraugi apliecinājumus, kad raksti tiek kopīgoti Mastodon.
instructions: 'Jāpārliecinās, ka šis kods ir raksta HTML:'
more_from_html: Vairāk no %{name}
s_blog: "%{name} emuāri"
then_instructions: Tad jāpievieno publicējuma domēna vārds zemāk esošajā laukā.
title: Autora attiecinājums
challenge:
confirm: Turpināt
@ -1413,6 +1435,48 @@ lv:
merge_long: Saglabāt esošos ierakstus un pievienot jaunus
overwrite: Pārrakstīt
overwrite_long: Nomainīt pašreizējos ierakstus ar jauniem
overwrite_preambles:
blocking_html:
one: Tu gatavojies <strong>aizstāt savu lieguma sarakstu</strong> ar līdz <strong>%{count} kontam</strong> no <strong>%{filename}</strong>.
other: Tu gatavojies <strong>aizstāt savu lieguma sarakstu</strong> ar līdz <strong>%{count} kontiem</strong> no <strong>%{filename}</strong>.
zero: Tu gatavojies <strong>aizstāt savu lieguma sarakstu</strong> ar līdz <strong>%{count} kontiem</strong> no <strong>%{filename}</strong>.
bookmarks_html:
one: Tu gatavojies <strong>aizstāt savas grāmatzīmes</strong> ar līdz <strong>%{count} ierakstam</strong> no <strong>%{filename}</strong>.
other: Tu gatavojies <strong>aizstāt savas grāmatzīmes</strong> ar līdz <strong>%{count} ierakstiem</strong> no <strong>%{filename}</strong>.
zero: Tu gatavojies <strong>aizstāt savas grāmatzīmes</strong> ar līdz <strong>%{count} ierakstiem</strong> no <strong>%{filename}</strong>.
domain_blocking_html:
one: Tu gatavojies <strong>aizstāt savu liegto domēnu sarakstu</strong> ar līdz <strong>%{count} domēnam</strong> no <strong>%{filename}</strong>.
other: Tu gatavojies <strong>aizstāt savu liegto domēnu sarakstu</strong> ar līdz <strong>%{count} domēniem</strong> no <strong>%{filename}</strong>.
zero: Tu gatavojies <strong>aizstāt savu liegto domēnu sarakstu</strong> ar līdz <strong>%{count} domēniem</strong> no <strong>%{filename}</strong>.
following_html:
one: Tu gatavojies <strong>sekot</strong> līdz <strong>%{count} kontam</strong> no <strong>%{filename}</strong> un <strong>pārtrauksi sekot citiem</strong>.
other: Tu gatavojies <strong>sekot</strong> līdz <strong>%{count} kontiem</strong> no <strong>%{filename}</strong> un <strong>pārtrauksi sekot citiem</strong>.
zero: Tu gatavojies <strong>sekot</strong> līdz <strong>%{count} kontiem</strong> no <strong>%{filename}</strong> un <strong>pārtrauksi sekot citiem</strong>.
lists_html:
one: Tu gatavojies <strong>aizstāt savus sarakstus</strong> ar <strong>%{filename}</strong> saturu. Līdz <strong>%{count} kontam</strong> tiks pievienoti jaunajos sarakstos.
other: Tu gatavojies <strong>aizstāt savus sarakstus</strong> ar <strong>%{filename}</strong> saturu. Līdz <strong>%{count} kontiem</strong> tiks pievienoti jaunajos sarakstos.
zero: Tu gatavojies <strong>aizstāt savus sarakstus</strong> ar <strong>%{filename}</strong> saturu. Līdz <strong>%{count} kontiem</strong> tiks pievienoti jaunajos sarakstos.
muting_html:
one: Tu gatavojies <strong>aizstāt savu apklusināto kontu sarakstu</strong> ar līdz <strong>%{count} kontam</strong> no <strong>%{filename}</strong>.
other: Tu gatavojies <strong>aizstāt savu apklusināto kontu sarakstu</strong> ar līdz <strong>%{count} kontiem</strong> no <strong>%{filename}</strong>.
zero: Tu gatavojies <strong>aizstāt savu apklusināto kontu sarakstu</strong> ar līdz <strong>%{count} kontiem</strong> no <strong>%{filename}</strong>.
preambles:
blocking_html:
one: Tu gatavojies <strong>liegt</strong> līdz <strong>%{count} kontam</strong> no <strong>%{filename}</strong>.
other: Tu gatavojies <strong>liegt</strong> līdz <strong>%{count} kontiem</strong> no <strong>%{filename}</strong>.
zero: Tu gatavojies <strong>liegt</strong> līdz <strong>%{count} kontiem</strong> no <strong>%{filename}</strong>.
bookmarks_html:
one: Tu gatavojies pievienot līdz <strong>%{count} ierakstam</strong> no <strong>%{filename}</strong> savām <strong>grāmatzīmēm</strong>.
other: Tu gatavojies pievienot līdz <strong>%{count} ierakstiem</strong> no <strong>%{filename}</strong> savām <strong>grāmatzīmēm</strong>.
zero: Tu gatavojies pievienot līdz <strong>%{count} ierakstiem</strong> no <strong>%{filename}</strong> savām <strong>grāmatzīmēm</strong>.
domain_blocking_html:
one: Tu gatavojies <strong>liegt</strong> līdz <strong>%{count} domēnam</strong> no <strong>%{filename}</strong>.
other: Tu gatavojies <strong>liegt</strong> līdz <strong>%{count} domēniem</strong> no <strong>%{filename}</strong>.
zero: Tu gatavojies <strong>liegt</strong> līdz <strong>%{count} domēniem</strong> no <strong>%{filename}</strong>.
following_html:
one: Tu gatavojies <strong>sekot</strong> līdz <strong>%{count} kontam</strong> no <strong>%{filename}</strong>.
other: Tu gatavojies <strong>sekot</strong> līdz <strong>%{count} kontiem</strong> no <strong>%{filename}</strong>.
zero: Tu gatavojies <strong>sekot</strong> līdz <strong>%{count} kontiem</strong> no <strong>%{filename}</strong>.
preface: Tu vari ievietot datus, kurus esi izguvis no cita servera, kā, piemēram, cilvēku sarakstu, kuriem Tu seko vai kurus bloķē.
recent_imports: Nesen importēts
states:

View file

@ -84,7 +84,7 @@ de:
backups_retention_period: Nutzer*innen haben die Möglichkeit, Archive ihrer Beiträge zu erstellen, die sie später herunterladen können. Wenn ein positiver Wert gesetzt ist, werden diese Archive nach der festgelegten Anzahl von Tagen automatisch aus deinem Speicher gelöscht.
bootstrap_timeline_accounts: Diese Konten werden bei den Follower-Empfehlungen für neu registrierte Nutzer*innen oben angeheftet.
closed_registrations_message: Wird angezeigt, wenn Registrierungen deaktiviert sind
content_cache_retention_period: Sämtliche Beiträge von anderen Servern (einschließlich geteilte Beiträge und Antworten) werden, unabhängig von der Interaktion der lokalen Nutzer*innen mit diesen Beiträgen, nach der festgelegten Anzahl von Tagen gelöscht. Das betrifft auch Beiträge, die von lokalen Nutzer*innen favorisiert oder als Lesezeichen gespeichert wurden. Private Erwähnungen zwischen Nutzer*innen von verschiedenen Servern werden ebenfalls verloren gehen und können nicht wiederhergestellt werden. Das Verwenden dieser Option richtet sich ausschließlich an Server für spezielle Zwecke und wird die allgemeine Nutzungserfahrung beeinträchtigen, wenn sie für den allgemeinen Gebrauch aktiviert ist.
content_cache_retention_period: Sämtliche Beiträge von anderen Servern (einschließlich geteilte Beiträge und Antworten) werden, unabhängig von der Interaktion der lokalen Nutzer*innen mit diesen Beiträgen, nach der festgelegten Anzahl von Tagen gelöscht. Das betrifft auch Beiträge, die von lokalen Nutzer*innen favorisiert oder als Lesezeichen gespeichert wurden. Private Erwähnungen zwischen Nutzer*innen von verschiedenen Servern werden ebenfalls verloren gehen und können nicht wiederhergestellt werden. Diese Option richtet sich ausschließlich an Server mit speziellen Zwecken und wird die allgemeine Nutzungserfahrung beeinträchtigen, wenn sie für den allgemeinen Gebrauch aktiviert ist.
custom_css: Du kannst benutzerdefinierte Stile auf die Web-Version von Mastodon anwenden.
favicon: WEBP, PNG, GIF oder JPG. Überschreibt das Standard-Mastodon-Favicon mit einem eigenen Symbol.
mascot: Überschreibt die Abbildung in der erweiterten Weboberfläche.

View file

@ -75,7 +75,7 @@ es-MX:
filters:
action: Elegir qué acción realizar cuando una publicación coincide con el filtro
actions:
blur: Ocultar contenido multimedia detrás de una advertencia, sin ocultar el texto en sí
blur: Ocultar contenido multimedia detrás de una advertencia, sin ocultar el propio texto
hide: Ocultar completamente el contenido filtrado, comportándose como si no existiera
warn: Ocultar el contenido filtrado detrás de una advertencia mencionando el título del filtro
form_admin_settings:
@ -89,7 +89,7 @@ es-MX:
favicon: WEBP, PNG, GIF o JPG. Reemplaza el icono predeterminado de Mastodon con un icono personalizado.
mascot: Reemplaza la ilustración en la interfaz web avanzada.
media_cache_retention_period: Los archivos multimedia de las publicaciones realizadas por usuarios remotos se almacenan en caché en su servidor. Si se establece en un valor positivo, los archivos multimedia se eliminarán tras el número de días especificado. Si los datos multimedia se solicitan después de haber sido eliminados, se volverán a descargar, si el contenido de origen sigue estando disponible. Debido a las restricciones sobre la frecuencia con la que las tarjetas de previsualización de enlaces sondean sitios de terceros, se recomienda establecer este valor en al menos 14 días, o las tarjetas de previsualización de enlaces no se actualizarán bajo demanda antes de ese tiempo.
min_age: Se pedirá a los usuarios que confirmen su fecha de nacimiento durante el registro
min_age: Se pedirá a los usuarios que confirmen su fecha de nacimiento al registrarse
peers_api_enabled: Una lista de nombres de dominio que este servidor ha encontrado en el fediverso. Aquí no se incluye ningún dato sobre si usted federa con un servidor determinado, sólo que su servidor lo sabe. Esto es utilizado por los servicios que recopilan estadísticas sobre la federación en un sentido general.
profile_directory: El directorio de perfiles lista a todos los usuarios que han optado por que su cuenta pueda ser descubierta.
require_invite_text: Cuando los registros requieren aprobación manual, hace obligatoria la entrada de texto "¿Por qué quieres unirte?" en lugar de opcional
@ -145,10 +145,10 @@ es-MX:
dmca_email: Puede ser el mismo correo electrónico utilizado para "Dirección de correo electrónico para avisos legales" de arriba.
domain: Identificación única del servicio en línea que presta.
jurisdiction: Indique el país de residencia de quien paga las facturas. Si se trata de una empresa u otra entidad, indique el país en el que está constituida y la ciudad, región, territorio o estado, según proceda.
min_age: No debería estar por debajo de la edad mínima requerida por las leyes de su jurisdicción.
min_age: No debe ser menor de la edad mínima exigida por las leyes de su jurisdicción.
user:
chosen_languages: Cuando se marca, solo se mostrarán las publicaciones en los idiomas seleccionados en las líneas de tiempo públicas
date_of_birth: Tenemos que asegurarnos de que al menos tienes %{age} años para usar Mastodon. No almacenaremos esta información.
date_of_birth: Tenemos que asegurarnos de que tienes al menos %{age} para usar Mastodon. No almacenaremos esto.
role: El rol controla qué permisos tiene el usuario.
user_role:
color: Color que se usará para el rol en toda la interfaz de usuario, como RGB en formato hexadecimal

View file

@ -480,6 +480,34 @@ tr:
title: Domain bloklarını içe aktar
no_file: Dosya seçilmedi
fasp:
debug:
callbacks:
created_at: Oluşturulma tarihi
delete: Sil
ip: IP adresi
request_body: İstek gövdesi
title: Hata ayıklama geri çağrıları
providers:
active: Etkin
base_url: Temel URL
callback: Geri çağırma
delete: Sil
edit: Sağlayıcıyı Düzenle
finish_registration: Kaydı tamamla
name: Ad
providers: Sağlayıcılar
public_key_fingerprint: ık anahtar parmak izi
registration_requested: Kayıt istendi
registrations:
confirm: Onayla
description: FASP'tan bir kayıt aldınız. Eğer bunu siz başlatmadıysanız reddedin. Eğer siz başlattıysanız, kaydı onaylamadan önce ad ve anahtar parmak izini dikkatlice karşılaştırın.
reject: Reddet
title: FASP Kaydını Onayla
save: Kaydet
select_capabilities: Yetenekleri Seç
sign_in: Oturum Aç
status: Durum
title: Fediverse Yardımcı Hizmet Sağlayıcıları (FASP)
title: FASP
follow_recommendations:
description_html: "<strong>Takip önerileri yeni kullanıcıların hızlı bir şekilde ilginç içerik bulmalarını sağlar</strong>. Eğer bir kullanıcı, kişisel takip önerileri almaya yetecek kadar başkalarıyla etkileşime girmediğinde, onun yerine bu hesaplar önerilir. Bu öneriler, verili bir dil için en yüksek takipçi sayısına ve en yüksek güncel meşguliyete sahip hesapların bir karışımdan günlük olarak hesaplanıyorlar."

View file

@ -12,6 +12,7 @@ module Mastodon
class RateLimitExceededError < Error; end
class SyntaxError < Error; end
class InvalidParameterError < Error; end
class SignatureVerificationError < Error; end
class UnexpectedResponseError < Error
attr_reader :response

View file

@ -1,7 +1,7 @@
{
"name": "@mastodon/mastodon",
"license": "AGPL-3.0-or-later",
"packageManager": "yarn@4.7.0",
"packageManager": "yarn@4.8.1",
"engines": {
"node": ">=18"
},
@ -151,7 +151,7 @@
"@testing-library/jest-dom": "^6.0.0",
"@testing-library/react": "^16.0.0",
"@types/babel__core": "^7.20.1",
"@types/emoji-mart": "^3.0.9",
"@types/emoji-mart": "3.0.14",
"@types/escape-html": "^1.0.2",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/http-link-header": "^1.0.3",
@ -197,7 +197,7 @@
"stylelint": "^16.11.0",
"stylelint-config-prettier-scss": "^1.0.0",
"stylelint-config-standard-scss": "^14.0.0",
"typescript": "^5.0.4",
"typescript": "~5.7.3",
"typescript-eslint": "^8.28.0",
"webpack-dev-server": "^3.11.3"
},

View file

@ -1,52 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Settings::PicturesController do
render_views
let!(:user) { Fabricate(:user) }
before do
sign_in user, scope: :user
end
describe 'DELETE #destroy' do
context 'with invalid picture id' do
it 'returns http bad request' do
delete :destroy, params: { id: 'invalid' }
expect(response).to have_http_status(400)
end
end
context 'with valid picture id' do
context 'when account updates correctly' do
let(:service) { instance_double(UpdateAccountService, call: true) }
before do
allow(UpdateAccountService).to receive(:new).and_return(service)
end
it 'updates the account' do
delete :destroy, params: { id: 'avatar' }
expect(response).to redirect_to(settings_profile_path)
expect(response).to have_http_status(303)
expect(service).to have_received(:call).with(user.account, { 'avatar' => nil, 'avatar_remote_url' => '' })
end
end
context 'when account cannot update' do
let(:service) { instance_double(UpdateAccountService, call: false) }
before do
allow(UpdateAccountService).to receive(:new).and_return(service)
end
it 'redirects to profile' do
delete :destroy, params: { id: 'avatar' }
expect(response).to redirect_to(settings_profile_path)
end
end
end
end
end

View file

@ -28,6 +28,19 @@ RSpec.describe Admin::Trends::StatusesHelper do
end
end
context 'with a remote status that has excessive attributes' do
let(:attr_limit) { Nokogiri::Gumbo::DEFAULT_MAX_ATTRIBUTES * 2 }
let(:html) { "<html><body #{(1..attr_limit).map { |x| "attr-#{x}" }.join(' ')}><p>text</p></body></html>" }
let(:status) { Fabricate.build(:status, uri: 'https://host.example', text: html) }
it 'renders a correct preview text' do
result = helper.one_line_preview(status)
expect(result).to eq ''
end
end
context 'with a status that has empty text' do
let(:status) { Fabricate.build(:status, text: '') }

View file

@ -187,6 +187,23 @@ RSpec.describe ActivityPub::TagManager do
end
end
describe '#uris_to_local_accounts' do
it 'returns the expected local accounts' do
account = Fabricate(:account)
expect(subject.uris_to_local_accounts([subject.uri_for(account), instance_actor_url])).to contain_exactly(account, Account.representative)
end
it 'does not return remote accounts' do
account = Fabricate(:account, uri: 'https://example.com/123', domain: 'example.com')
expect(subject.uris_to_local_accounts([subject.uri_for(account)])).to be_empty
end
it 'does not return an account for a local post' do
status = Fabricate(:status)
expect(subject.uris_to_local_accounts([subject.uri_for(status)])).to be_empty
end
end
describe '#uri_to_resource' do
it 'returns the local account' do
account = Fabricate(:account)

View file

@ -38,7 +38,7 @@ RSpec.describe Fasp::Request do
it 'raises an error' do
expect do
subject.send(method, '/test_path')
end.to raise_error(SignatureVerification::SignatureVerificationError)
end.to raise_error(Mastodon::SignatureVerificationError)
end
end
end

View file

@ -0,0 +1,55 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Settings Pictures' do
let!(:user) { Fabricate(:user) }
before { sign_in user }
describe 'DELETE /settings/profile/pictures/:id' do
context 'with invalid picture id' do
it 'returns http bad request' do
delete settings_profile_picture_path(id: 'invalid')
expect(response)
.to have_http_status(400)
end
end
context 'with valid picture id' do
before { stub_service }
context 'when account updates correctly' do
let(:service) { instance_double(UpdateAccountService, call: true) }
it 'updates the account' do
delete settings_profile_picture_path(id: 'avatar')
expect(response)
.to redirect_to(settings_profile_path)
.and have_http_status(303)
expect(service)
.to have_received(:call).with(user.account, { 'avatar' => nil, 'avatar_remote_url' => '' })
end
end
context 'when account cannot update' do
let(:service) { instance_double(UpdateAccountService, call: false) }
it 'redirects to profile' do
delete settings_profile_picture_path(id: 'avatar')
expect(response)
.to redirect_to(settings_profile_path)
end
end
def stub_service
allow(UpdateAccountService)
.to receive(:new)
.and_return(service)
end
end
end
end

View file

@ -1,7 +1,7 @@
{
"name": "@mastodon/streaming",
"license": "AGPL-3.0-or-later",
"packageManager": "yarn@4.7.0",
"packageManager": "yarn@4.8.1",
"engines": {
"node": ">=18"
},
@ -39,7 +39,7 @@
"@types/ws": "^8.5.9",
"globals": "^16.0.0",
"pino-pretty": "^13.0.0",
"typescript": "^5.0.4",
"typescript": "~5.7.3",
"typescript-eslint": "^8.28.0"
},
"optionalDependencies": {

147
yarn.lock
View file

@ -2190,14 +2190,7 @@ __metadata:
languageName: node
linkType: hard
"@eslint-community/regexpp@npm:^4.10.0":
version: 4.10.0
resolution: "@eslint-community/regexpp@npm:4.10.0"
checksum: 10c0/c5f60ef1f1ea7649fa7af0e80a5a79f64b55a8a8fa5086de4727eb4c86c652aedee407a9c143b8995d2c0b2d75c1222bec9ba5d73dbfc1f314550554f0979ef4
languageName: node
linkType: hard
"@eslint-community/regexpp@npm:^4.12.1":
"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.12.1":
version: 4.12.1
resolution: "@eslint-community/regexpp@npm:4.12.1"
checksum: 10c0/a03d98c246bcb9109aec2c08e4d10c8d010256538dcb3f56610191607214523d4fb1b00aa81df830b6dffb74c5fa0be03642513a289c567949d3e550ca11cdf6
@ -2848,7 +2841,7 @@ __metadata:
"@testing-library/jest-dom": "npm:^6.0.0"
"@testing-library/react": "npm:^16.0.0"
"@types/babel__core": "npm:^7.20.1"
"@types/emoji-mart": "npm:^3.0.9"
"@types/emoji-mart": "npm:3.0.14"
"@types/escape-html": "npm:^1.0.2"
"@types/hoist-non-react-statics": "npm:^3.3.1"
"@types/http-link-header": "npm:^1.0.3"
@ -2970,7 +2963,7 @@ __metadata:
tesseract.js: "npm:^6.0.0"
tiny-queue: "npm:^0.2.1"
twitter-text: "npm:3.1.0"
typescript: "npm:^5.0.4"
typescript: "npm:~5.7.3"
typescript-eslint: "npm:^8.28.0"
use-debounce: "npm:^10.0.0"
webpack: "npm:^4.47.0"
@ -3019,7 +3012,7 @@ __metadata:
pino-http: "npm:^10.0.0"
pino-pretty: "npm:^13.0.0"
prom-client: "npm:^15.0.0"
typescript: "npm:^5.0.4"
typescript: "npm:~5.7.3"
typescript-eslint: "npm:^8.28.0"
utf-8-validate: "npm:^6.0.3"
uuid: "npm:^11.0.0"
@ -3822,7 +3815,7 @@ __metadata:
languageName: node
linkType: hard
"@types/emoji-mart@npm:^3.0.9":
"@types/emoji-mart@npm:3.0.14":
version: 3.0.14
resolution: "@types/emoji-mart@npm:3.0.14"
dependencies:
@ -3848,10 +3841,10 @@ __metadata:
languageName: node
linkType: hard
"@types/estree@npm:*, @types/estree@npm:^1.0.0":
version: 1.0.5
resolution: "@types/estree@npm:1.0.5"
checksum: 10c0/b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d
"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.6":
version: 1.0.7
resolution: "@types/estree@npm:1.0.7"
checksum: 10c0/be815254316882f7c40847336cd484c3bc1c3e34f710d197160d455dc9d6d050ffbf4c3bc76585dba86f737f020ab20bdb137ebe0e9116b0c86c7c0342221b8c
languageName: node
linkType: hard
@ -3862,13 +3855,6 @@ __metadata:
languageName: node
linkType: hard
"@types/estree@npm:^1.0.6":
version: 1.0.7
resolution: "@types/estree@npm:1.0.7"
checksum: 10c0/be815254316882f7c40847336cd484c3bc1c3e34f710d197160d455dc9d6d050ffbf4c3bc76585dba86f737f020ab20bdb137ebe0e9116b0c86c7c0342221b8c
languageName: node
linkType: hard
"@types/express-serve-static-core@npm:^4.17.33":
version: 4.17.41
resolution: "@types/express-serve-static-core@npm:4.17.41"
@ -4054,16 +4040,7 @@ __metadata:
languageName: node
linkType: hard
"@types/node@npm:*":
version: 22.8.6
resolution: "@types/node@npm:22.8.6"
dependencies:
undici-types: "npm:~6.19.8"
checksum: 10c0/d3a11f2549234a91a4c5d0ff35ab4bdcb7ba34db4d3f1d189be39b8bd41c19aac98d117150a95a9c5a9d45b1014135477ea240b2b8317c86ae3d3cf1c3b3f8f4
languageName: node
linkType: hard
"@types/node@npm:^22.0.0":
"@types/node@npm:*, @types/node@npm:^22.0.0":
version: 22.13.14
resolution: "@types/node@npm:22.13.14"
dependencies:
@ -4908,16 +4885,7 @@ __metadata:
languageName: node
linkType: hard
"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.12.0, acorn@npm:^8.8.1, acorn@npm:^8.8.2":
version: 8.12.1
resolution: "acorn@npm:8.12.1"
bin:
acorn: bin/acorn
checksum: 10c0/51fb26cd678f914e13287e886da2d7021f8c2bc0ccc95e03d3e0447ee278dd3b40b9c57dc222acd5881adcf26f3edc40901a4953403232129e3876793cd17386
languageName: node
linkType: hard
"acorn@npm:^8.14.0":
"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.14.0, acorn@npm:^8.8.1, acorn@npm:^8.8.2":
version: 8.14.1
resolution: "acorn@npm:8.14.1"
bin:
@ -6860,18 +6828,7 @@ __metadata:
languageName: node
linkType: hard
"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.3":
version: 7.0.3
resolution: "cross-spawn@npm:7.0.3"
dependencies:
path-key: "npm:^3.1.0"
shebang-command: "npm:^2.0.0"
which: "npm:^2.0.1"
checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750
languageName: node
linkType: hard
"cross-spawn@npm:^7.0.6":
"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6":
version: 7.0.6
resolution: "cross-spawn@npm:7.0.6"
dependencies:
@ -8384,7 +8341,7 @@ __metadata:
languageName: node
linkType: hard
"eslint-visitor-keys@npm:^4.0.0, eslint-visitor-keys@npm:^4.2.0":
"eslint-visitor-keys@npm:^4.2.0":
version: 4.2.0
resolution: "eslint-visitor-keys@npm:4.2.0"
checksum: 10c0/2ed81c663b147ca6f578312919483eb040295bbab759e5a371953456c636c5b49a559883e2677112453728d66293c0a4c90ab11cab3428cf02a0236d2e738269
@ -8441,7 +8398,7 @@ __metadata:
languageName: node
linkType: hard
"espree@npm:^10.0.1, espree@npm:^10.3.0":
"espree@npm:^10.0.1, espree@npm:^10.1.0, espree@npm:^10.3.0":
version: 10.3.0
resolution: "espree@npm:10.3.0"
dependencies:
@ -8452,17 +8409,6 @@ __metadata:
languageName: node
linkType: hard
"espree@npm:^10.1.0":
version: 10.1.0
resolution: "espree@npm:10.1.0"
dependencies:
acorn: "npm:^8.12.0"
acorn-jsx: "npm:^5.3.2"
eslint-visitor-keys: "npm:^4.0.0"
checksum: 10c0/52e6feaa77a31a6038f0c0e3fce93010a4625701925b0715cd54a2ae190b3275053a0717db698697b32653788ac04845e489d6773b508d6c2e8752f3c57470a0
languageName: node
linkType: hard
"esprima@npm:^4.0.0, esprima@npm:^4.0.1":
version: 4.0.1
resolution: "esprima@npm:4.0.1"
@ -15133,15 +15079,15 @@ __metadata:
linkType: hard
"react-textarea-autosize@npm:^8.4.1":
version: 8.5.8
resolution: "react-textarea-autosize@npm:8.5.8"
version: 8.5.9
resolution: "react-textarea-autosize@npm:8.5.9"
dependencies:
"@babel/runtime": "npm:^7.20.13"
use-composed-ref: "npm:^1.3.0"
use-latest: "npm:^1.2.1"
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
checksum: 10c0/3d7add9773fd3dc189a6668efb82c1d2d5238ee5b7e933204f5f7da9df8daef81df50b36ca573a57beaa31b2727c6176ea806422790ad23be6cf7f5a5f71bbb9
checksum: 10c0/3a924db59259a6e3b834dcddc12a8661b43dcdaa1b43c41c732e0548bb2761e9a53dbc6db4e0d9e237728b4869e42c25e5417408b0391aec290c90874733a09f
languageName: node
linkType: hard
@ -15816,8 +15762,8 @@ __metadata:
linkType: hard
"sass@npm:^1.62.1":
version: 1.86.0
resolution: "sass@npm:1.86.0"
version: 1.86.3
resolution: "sass@npm:1.86.3"
dependencies:
"@parcel/watcher": "npm:^2.4.1"
chokidar: "npm:^4.0.0"
@ -15828,7 +15774,7 @@ __metadata:
optional: true
bin:
sass: sass.js
checksum: 10c0/921caea1fd8a450d4a986e5570ce13c4ca7b2a57da390811add3d2087ad8f46f53b34652ddcb237d8bdaad49c560b8d6eee130c733c787d058bc5a71a914c139
checksum: 10c0/ba819a0828f732adf7a94cd8ca017bce92bc299ffb878836ed1da80a30612bfbbf56a5e42d6dff3ad80d919c2025afb42948fc7b54a7bc61a9a2d58e1e0c558a
languageName: node
linkType: hard
@ -15941,16 +15887,7 @@ __metadata:
languageName: node
linkType: hard
"semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3":
version: 7.6.3
resolution: "semver@npm:7.6.3"
bin:
semver: bin/semver.js
checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf
languageName: node
linkType: hard
"semver@npm:^7.7.1":
"semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3, semver@npm:^7.7.1":
version: 7.7.1
resolution: "semver@npm:7.7.1"
bin:
@ -17604,14 +17541,7 @@ __metadata:
languageName: node
linkType: hard
"tslib@npm:^2.0.0, tslib@npm:^2.4.0, tslib@npm:^2.6.2":
version: 2.8.0
resolution: "tslib@npm:2.8.0"
checksum: 10c0/31e4d14dc1355e9b89e4d3c893a18abb7f90b6886b089c2da91224d0a7752c79f3ddc41bc1aa0a588ac895bd97bb99c5bc2bfdb2f86de849f31caeb3ba79bbe5
languageName: node
linkType: hard
"tslib@npm:^2.8.0":
"tslib@npm:^2.0.0, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.8.0":
version: 2.8.1
resolution: "tslib@npm:2.8.1"
checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62
@ -17751,16 +17681,6 @@ __metadata:
languageName: node
linkType: hard
"typescript@npm:^5.0.4":
version: 5.7.3
resolution: "typescript@npm:5.7.3"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/b7580d716cf1824736cc6e628ab4cd8b51877408ba2be0869d2866da35ef8366dd6ae9eb9d0851470a39be17cbd61df1126f9e211d8799d764ea7431d5435afa
languageName: node
linkType: hard
"typescript@npm:^5.6.0":
version: 5.8.2
resolution: "typescript@npm:5.8.2"
@ -17771,13 +17691,13 @@ __metadata:
languageName: node
linkType: hard
"typescript@patch:typescript@npm%3A^5.0.4#optional!builtin<compat/typescript>":
"typescript@npm:~5.7.3":
version: 5.7.3
resolution: "typescript@patch:typescript@npm%3A5.7.3#optional!builtin<compat/typescript>::version=5.7.3&hash=5786d5"
resolution: "typescript@npm:5.7.3"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/6fd7e0ed3bf23a81246878c613423730c40e8bdbfec4c6e4d7bf1b847cbb39076e56ad5f50aa9d7ebd89877999abaee216002d3f2818885e41c907caaa192cc4
checksum: 10c0/b7580d716cf1824736cc6e628ab4cd8b51877408ba2be0869d2866da35ef8366dd6ae9eb9d0851470a39be17cbd61df1126f9e211d8799d764ea7431d5435afa
languageName: node
linkType: hard
@ -17791,6 +17711,16 @@ __metadata:
languageName: node
linkType: hard
"typescript@patch:typescript@npm%3A~5.7.3#optional!builtin<compat/typescript>":
version: 5.7.3
resolution: "typescript@patch:typescript@npm%3A5.7.3#optional!builtin<compat/typescript>::version=5.7.3&hash=5786d5"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/6fd7e0ed3bf23a81246878c613423730c40e8bdbfec4c6e4d7bf1b847cbb39076e56ad5f50aa9d7ebd89877999abaee216002d3f2818885e41c907caaa192cc4
languageName: node
linkType: hard
"unbox-primitive@npm:^1.1.0":
version: 1.1.0
resolution: "unbox-primitive@npm:1.1.0"
@ -17817,13 +17747,6 @@ __metadata:
languageName: node
linkType: hard
"undici-types@npm:~6.19.8":
version: 6.19.8
resolution: "undici-types@npm:6.19.8"
checksum: 10c0/078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344
languageName: node
linkType: hard
"undici-types@npm:~6.20.0":
version: 6.20.0
resolution: "undici-types@npm:6.20.0"