Merge remote-tracking branch 'parent/main' into upstream-20241209
This commit is contained in:
commit
6b6f145633
28 changed files with 571 additions and 324 deletions
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
|||
22.11
|
||||
22.12
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
import api, { getLinks } from '../api';
|
||||
|
||||
export const HASHTAG_FETCH_REQUEST = 'HASHTAG_FETCH_REQUEST';
|
||||
export const HASHTAG_FETCH_SUCCESS = 'HASHTAG_FETCH_SUCCESS';
|
||||
export const HASHTAG_FETCH_FAIL = 'HASHTAG_FETCH_FAIL';
|
||||
|
||||
export const FOLLOWED_HASHTAGS_FETCH_REQUEST = 'FOLLOWED_HASHTAGS_FETCH_REQUEST';
|
||||
export const FOLLOWED_HASHTAGS_FETCH_SUCCESS = 'FOLLOWED_HASHTAGS_FETCH_SUCCESS';
|
||||
export const FOLLOWED_HASHTAGS_FETCH_FAIL = 'FOLLOWED_HASHTAGS_FETCH_FAIL';
|
||||
|
@ -12,39 +8,6 @@ export const FOLLOWED_HASHTAGS_EXPAND_REQUEST = 'FOLLOWED_HASHTAGS_EXPAND_REQUES
|
|||
export const FOLLOWED_HASHTAGS_EXPAND_SUCCESS = 'FOLLOWED_HASHTAGS_EXPAND_SUCCESS';
|
||||
export const FOLLOWED_HASHTAGS_EXPAND_FAIL = 'FOLLOWED_HASHTAGS_EXPAND_FAIL';
|
||||
|
||||
export const HASHTAG_FOLLOW_REQUEST = 'HASHTAG_FOLLOW_REQUEST';
|
||||
export const HASHTAG_FOLLOW_SUCCESS = 'HASHTAG_FOLLOW_SUCCESS';
|
||||
export const HASHTAG_FOLLOW_FAIL = 'HASHTAG_FOLLOW_FAIL';
|
||||
|
||||
export const HASHTAG_UNFOLLOW_REQUEST = 'HASHTAG_UNFOLLOW_REQUEST';
|
||||
export const HASHTAG_UNFOLLOW_SUCCESS = 'HASHTAG_UNFOLLOW_SUCCESS';
|
||||
export const HASHTAG_UNFOLLOW_FAIL = 'HASHTAG_UNFOLLOW_FAIL';
|
||||
|
||||
export const fetchHashtag = name => (dispatch) => {
|
||||
dispatch(fetchHashtagRequest());
|
||||
|
||||
api().get(`/api/v1/tags/${name}`).then(({ data }) => {
|
||||
dispatch(fetchHashtagSuccess(name, data));
|
||||
}).catch(err => {
|
||||
dispatch(fetchHashtagFail(err));
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchHashtagRequest = () => ({
|
||||
type: HASHTAG_FETCH_REQUEST,
|
||||
});
|
||||
|
||||
export const fetchHashtagSuccess = (name, tag) => ({
|
||||
type: HASHTAG_FETCH_SUCCESS,
|
||||
name,
|
||||
tag,
|
||||
});
|
||||
|
||||
export const fetchHashtagFail = error => ({
|
||||
type: HASHTAG_FETCH_FAIL,
|
||||
error,
|
||||
});
|
||||
|
||||
export const fetchFollowedHashtags = () => (dispatch) => {
|
||||
dispatch(fetchFollowedHashtagsRequest());
|
||||
|
||||
|
@ -116,57 +79,3 @@ export function expandFollowedHashtagsFail(error) {
|
|||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export const followHashtag = name => (dispatch) => {
|
||||
dispatch(followHashtagRequest(name));
|
||||
|
||||
api().post(`/api/v1/tags/${name}/follow`).then(({ data }) => {
|
||||
dispatch(followHashtagSuccess(name, data));
|
||||
}).catch(err => {
|
||||
dispatch(followHashtagFail(name, err));
|
||||
});
|
||||
};
|
||||
|
||||
export const followHashtagRequest = name => ({
|
||||
type: HASHTAG_FOLLOW_REQUEST,
|
||||
name,
|
||||
});
|
||||
|
||||
export const followHashtagSuccess = (name, tag) => ({
|
||||
type: HASHTAG_FOLLOW_SUCCESS,
|
||||
name,
|
||||
tag,
|
||||
});
|
||||
|
||||
export const followHashtagFail = (name, error) => ({
|
||||
type: HASHTAG_FOLLOW_FAIL,
|
||||
name,
|
||||
error,
|
||||
});
|
||||
|
||||
export const unfollowHashtag = name => (dispatch) => {
|
||||
dispatch(unfollowHashtagRequest(name));
|
||||
|
||||
api().post(`/api/v1/tags/${name}/unfollow`).then(({ data }) => {
|
||||
dispatch(unfollowHashtagSuccess(name, data));
|
||||
}).catch(err => {
|
||||
dispatch(unfollowHashtagFail(name, err));
|
||||
});
|
||||
};
|
||||
|
||||
export const unfollowHashtagRequest = name => ({
|
||||
type: HASHTAG_UNFOLLOW_REQUEST,
|
||||
name,
|
||||
});
|
||||
|
||||
export const unfollowHashtagSuccess = (name, tag) => ({
|
||||
type: HASHTAG_UNFOLLOW_SUCCESS,
|
||||
name,
|
||||
tag,
|
||||
});
|
||||
|
||||
export const unfollowHashtagFail = (name, error) => ({
|
||||
type: HASHTAG_UNFOLLOW_FAIL,
|
||||
name,
|
||||
error,
|
||||
});
|
||||
|
|
17
app/javascript/mastodon/actions/tags_typed.ts
Normal file
17
app/javascript/mastodon/actions/tags_typed.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { apiGetTag, apiFollowTag, apiUnfollowTag } from 'mastodon/api/tags';
|
||||
import { createDataLoadingThunk } from 'mastodon/store/typed_functions';
|
||||
|
||||
export const fetchHashtag = createDataLoadingThunk(
|
||||
'tags/fetch',
|
||||
({ tagId }: { tagId: string }) => apiGetTag(tagId),
|
||||
);
|
||||
|
||||
export const followHashtag = createDataLoadingThunk(
|
||||
'tags/follow',
|
||||
({ tagId }: { tagId: string }) => apiFollowTag(tagId),
|
||||
);
|
||||
|
||||
export const unfollowHashtag = createDataLoadingThunk(
|
||||
'tags/unfollow',
|
||||
({ tagId }: { tagId: string }) => apiUnfollowTag(tagId),
|
||||
);
|
11
app/javascript/mastodon/api/tags.ts
Normal file
11
app/javascript/mastodon/api/tags.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { apiRequestPost, apiRequestGet } from 'mastodon/api';
|
||||
import type { ApiHashtagJSON } from 'mastodon/api_types/tags';
|
||||
|
||||
export const apiGetTag = (tagId: string) =>
|
||||
apiRequestGet<ApiHashtagJSON>(`v1/tags/${tagId}`);
|
||||
|
||||
export const apiFollowTag = (tagId: string) =>
|
||||
apiRequestPost<ApiHashtagJSON>(`v1/tags/${tagId}/follow`);
|
||||
|
||||
export const apiUnfollowTag = (tagId: string) =>
|
||||
apiRequestPost<ApiHashtagJSON>(`v1/tags/${tagId}/unfollow`);
|
13
app/javascript/mastodon/api_types/tags.ts
Normal file
13
app/javascript/mastodon/api_types/tags.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
interface ApiHistoryJSON {
|
||||
day: string;
|
||||
accounts: string;
|
||||
uses: string;
|
||||
}
|
||||
|
||||
export interface ApiHashtagJSON {
|
||||
id: string;
|
||||
name: string;
|
||||
url: string;
|
||||
history: [ApiHistoryJSON, ...ApiHistoryJSON[]];
|
||||
following?: boolean;
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
|
||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||
import { Button } from 'mastodon/components/button';
|
||||
import { ShortNumber } from 'mastodon/components/short_number';
|
||||
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
||||
import { withIdentity } from 'mastodon/identity_context';
|
||||
import { PERMISSION_MANAGE_TAXONOMIES } from 'mastodon/permissions';
|
||||
|
||||
const messages = defineMessages({
|
||||
followHashtag: { id: 'hashtag.follow', defaultMessage: 'Follow hashtag' },
|
||||
unfollowHashtag: { id: 'hashtag.unfollow', defaultMessage: 'Unfollow hashtag' },
|
||||
adminModeration: { id: 'hashtag.admin_moderation', defaultMessage: 'Open moderation interface for #{name}' },
|
||||
});
|
||||
|
||||
const usesRenderer = (displayNumber, pluralReady) => (
|
||||
<FormattedMessage
|
||||
id='hashtag.counter_by_uses'
|
||||
defaultMessage='{count, plural, one {{counter} post} other {{counter} posts}}'
|
||||
values={{
|
||||
count: pluralReady,
|
||||
counter: <strong>{displayNumber}</strong>,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const peopleRenderer = (displayNumber, pluralReady) => (
|
||||
<FormattedMessage
|
||||
id='hashtag.counter_by_accounts'
|
||||
defaultMessage='{count, plural, one {{counter} participant} other {{counter} participants}}'
|
||||
values={{
|
||||
count: pluralReady,
|
||||
counter: <strong>{displayNumber}</strong>,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const usesTodayRenderer = (displayNumber, pluralReady) => (
|
||||
<FormattedMessage
|
||||
id='hashtag.counter_by_uses_today'
|
||||
defaultMessage='{count, plural, one {{counter} post} other {{counter} posts}} today'
|
||||
values={{
|
||||
count: pluralReady,
|
||||
counter: <strong>{displayNumber}</strong>,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
export const HashtagHeader = withIdentity(injectIntl(({ tag, intl, disabled, onClick, identity }) => {
|
||||
if (!tag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { signedIn, permissions } = identity;
|
||||
const menu = [];
|
||||
|
||||
if (signedIn && (permissions & PERMISSION_MANAGE_TAXONOMIES) === PERMISSION_MANAGE_TAXONOMIES ) {
|
||||
menu.push({ text: intl.formatMessage(messages.adminModeration, { name: tag.get("name") }), href: `/admin/tags/${tag.get('id')}` });
|
||||
}
|
||||
|
||||
const [uses, people] = tag.get('history').reduce((arr, day) => [arr[0] + day.get('uses') * 1, arr[1] + day.get('accounts') * 1], [0, 0]);
|
||||
const dividingCircle = <span aria-hidden>{' · '}</span>;
|
||||
|
||||
return (
|
||||
<div className='hashtag-header'>
|
||||
<div className='hashtag-header__header'>
|
||||
<h1>#{tag.get('name')}</h1>
|
||||
<div className='hashtag-header__header__buttons'>
|
||||
{ menu.length > 0 && <DropdownMenuContainer disabled={menu.length === 0} items={menu} icon='ellipsis-v' iconComponent={MoreHorizIcon} size={24} direction='right' /> }
|
||||
<Button onClick={onClick} text={intl.formatMessage(tag.get('following') ? messages.unfollowHashtag : messages.followHashtag)} disabled={disabled} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ShortNumber value={uses} renderer={usesRenderer} />
|
||||
{dividingCircle}
|
||||
<ShortNumber value={people} renderer={peopleRenderer} />
|
||||
{dividingCircle}
|
||||
<ShortNumber value={tag.getIn(['history', 0, 'uses']) * 1} renderer={usesTodayRenderer} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}));
|
||||
|
||||
HashtagHeader.propTypes = {
|
||||
tag: ImmutablePropTypes.map,
|
||||
disabled: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
intl: PropTypes.object,
|
||||
};
|
|
@ -0,0 +1,188 @@
|
|||
import { useCallback, useMemo, useState, useEffect } from 'react';
|
||||
|
||||
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||
|
||||
import { isFulfilled } from '@reduxjs/toolkit';
|
||||
|
||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||
import {
|
||||
fetchHashtag,
|
||||
followHashtag,
|
||||
unfollowHashtag,
|
||||
} from 'mastodon/actions/tags_typed';
|
||||
import type { ApiHashtagJSON } from 'mastodon/api_types/tags';
|
||||
import { Button } from 'mastodon/components/button';
|
||||
import { ShortNumber } from 'mastodon/components/short_number';
|
||||
import DropdownMenu from 'mastodon/containers/dropdown_menu_container';
|
||||
import { useIdentity } from 'mastodon/identity_context';
|
||||
import { PERMISSION_MANAGE_TAXONOMIES } from 'mastodon/permissions';
|
||||
import { useAppDispatch } from 'mastodon/store';
|
||||
|
||||
const messages = defineMessages({
|
||||
followHashtag: { id: 'hashtag.follow', defaultMessage: 'Follow hashtag' },
|
||||
unfollowHashtag: {
|
||||
id: 'hashtag.unfollow',
|
||||
defaultMessage: 'Unfollow hashtag',
|
||||
},
|
||||
adminModeration: {
|
||||
id: 'hashtag.admin_moderation',
|
||||
defaultMessage: 'Open moderation interface for #{name}',
|
||||
},
|
||||
});
|
||||
|
||||
const usesRenderer = (displayNumber: React.ReactNode, pluralReady: number) => (
|
||||
<FormattedMessage
|
||||
id='hashtag.counter_by_uses'
|
||||
defaultMessage='{count, plural, one {{counter} post} other {{counter} posts}}'
|
||||
values={{
|
||||
count: pluralReady,
|
||||
counter: <strong>{displayNumber}</strong>,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const peopleRenderer = (
|
||||
displayNumber: React.ReactNode,
|
||||
pluralReady: number,
|
||||
) => (
|
||||
<FormattedMessage
|
||||
id='hashtag.counter_by_accounts'
|
||||
defaultMessage='{count, plural, one {{counter} participant} other {{counter} participants}}'
|
||||
values={{
|
||||
count: pluralReady,
|
||||
counter: <strong>{displayNumber}</strong>,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const usesTodayRenderer = (
|
||||
displayNumber: React.ReactNode,
|
||||
pluralReady: number,
|
||||
) => (
|
||||
<FormattedMessage
|
||||
id='hashtag.counter_by_uses_today'
|
||||
defaultMessage='{count, plural, one {{counter} post} other {{counter} posts}} today'
|
||||
values={{
|
||||
count: pluralReady,
|
||||
counter: <strong>{displayNumber}</strong>,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
export const HashtagHeader: React.FC<{
|
||||
tagId: string;
|
||||
}> = ({ tagId }) => {
|
||||
const intl = useIntl();
|
||||
const { signedIn, permissions } = useIdentity();
|
||||
const dispatch = useAppDispatch();
|
||||
const [tag, setTag] = useState<ApiHashtagJSON>();
|
||||
|
||||
useEffect(() => {
|
||||
void dispatch(fetchHashtag({ tagId })).then((result) => {
|
||||
if (isFulfilled(result)) {
|
||||
setTag(result.payload);
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
}, [dispatch, tagId, setTag]);
|
||||
|
||||
const menu = useMemo(() => {
|
||||
const tmp = [];
|
||||
|
||||
if (
|
||||
tag &&
|
||||
signedIn &&
|
||||
(permissions & PERMISSION_MANAGE_TAXONOMIES) ===
|
||||
PERMISSION_MANAGE_TAXONOMIES
|
||||
) {
|
||||
tmp.push({
|
||||
text: intl.formatMessage(messages.adminModeration, { name: tag.id }),
|
||||
href: `/admin/tags/${tag.id}`,
|
||||
});
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}, [signedIn, permissions, intl, tag]);
|
||||
|
||||
const handleFollow = useCallback(() => {
|
||||
if (!signedIn || !tag) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tag.following) {
|
||||
setTag((hashtag) => hashtag && { ...hashtag, following: false });
|
||||
|
||||
void dispatch(unfollowHashtag({ tagId })).then((result) => {
|
||||
if (isFulfilled(result)) {
|
||||
setTag(result.payload);
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
} else {
|
||||
setTag((hashtag) => hashtag && { ...hashtag, following: true });
|
||||
|
||||
void dispatch(followHashtag({ tagId })).then((result) => {
|
||||
if (isFulfilled(result)) {
|
||||
setTag(result.payload);
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
}
|
||||
}, [dispatch, setTag, signedIn, tag, tagId]);
|
||||
|
||||
if (!tag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [uses, people] = tag.history.reduce(
|
||||
(arr, day) => [
|
||||
arr[0] + parseInt(day.uses),
|
||||
arr[1] + parseInt(day.accounts),
|
||||
],
|
||||
[0, 0],
|
||||
);
|
||||
const dividingCircle = <span aria-hidden>{' · '}</span>;
|
||||
|
||||
return (
|
||||
<div className='hashtag-header'>
|
||||
<div className='hashtag-header__header'>
|
||||
<h1>#{tag.name}</h1>
|
||||
|
||||
<div className='hashtag-header__header__buttons'>
|
||||
{menu.length > 0 && (
|
||||
<DropdownMenu
|
||||
disabled={menu.length === 0}
|
||||
items={menu}
|
||||
icon='ellipsis-v'
|
||||
iconComponent={MoreHorizIcon}
|
||||
size={24}
|
||||
direction='right'
|
||||
/>
|
||||
)}
|
||||
|
||||
<Button
|
||||
onClick={handleFollow}
|
||||
text={intl.formatMessage(
|
||||
tag.following ? messages.unfollowHashtag : messages.followHashtag,
|
||||
)}
|
||||
disabled={!signedIn}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ShortNumber value={uses} renderer={usesRenderer} />
|
||||
{dividingCircle}
|
||||
<ShortNumber value={people} renderer={peopleRenderer} />
|
||||
{dividingCircle}
|
||||
<ShortNumber
|
||||
value={parseInt(tag.history[0].uses)}
|
||||
renderer={usesTodayRenderer}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -5,7 +5,6 @@ import { FormattedMessage } from 'react-intl';
|
|||
|
||||
import { Helmet } from 'react-helmet';
|
||||
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { isEqual } from 'lodash';
|
||||
|
@ -13,7 +12,6 @@ import { isEqual } from 'lodash';
|
|||
import TagIcon from '@/material-icons/400-24px/tag.svg?react';
|
||||
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
|
||||
import { connectHashtagStream } from 'mastodon/actions/streaming';
|
||||
import { fetchHashtag, followHashtag, unfollowHashtag } from 'mastodon/actions/tags';
|
||||
import { expandHashtagTimeline, clearTimeline } from 'mastodon/actions/timelines';
|
||||
import Column from 'mastodon/components/column';
|
||||
import ColumnHeader from 'mastodon/components/column_header';
|
||||
|
@ -26,7 +24,6 @@ import ColumnSettingsContainer from './containers/column_settings_container';
|
|||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}${props.params.local ? ':local' : ''}`, 'unread']) > 0,
|
||||
tag: state.getIn(['tags', props.params.id]),
|
||||
});
|
||||
|
||||
class HashtagTimeline extends PureComponent {
|
||||
|
@ -38,7 +35,6 @@ class HashtagTimeline extends PureComponent {
|
|||
columnId: PropTypes.string,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
hasUnread: PropTypes.bool,
|
||||
tag: ImmutablePropTypes.map,
|
||||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
|
@ -130,7 +126,6 @@ class HashtagTimeline extends PureComponent {
|
|||
|
||||
this._subscribe(dispatch, id, tags, local);
|
||||
dispatch(expandHashtagTimeline(id, { tags, local }));
|
||||
dispatch(fetchHashtag(id));
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
|
@ -162,27 +157,10 @@ class HashtagTimeline extends PureComponent {
|
|||
dispatch(expandHashtagTimeline(id, { maxId, tags, local }));
|
||||
};
|
||||
|
||||
handleFollow = () => {
|
||||
const { dispatch, params, tag } = this.props;
|
||||
const { id } = params;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
if (!signedIn) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tag.get('following')) {
|
||||
dispatch(unfollowHashtag(id));
|
||||
} else {
|
||||
dispatch(followHashtag(id));
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
const { hasUnread, columnId, multiColumn, tag } = this.props;
|
||||
const { hasUnread, columnId, multiColumn } = this.props;
|
||||
const { id, local } = this.props.params;
|
||||
const pinned = !!columnId;
|
||||
const { signedIn } = this.props.identity;
|
||||
|
||||
return (
|
||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={`#${id}`}>
|
||||
|
@ -202,7 +180,7 @@ class HashtagTimeline extends PureComponent {
|
|||
</ColumnHeader>
|
||||
|
||||
<StatusListContainer
|
||||
prepend={pinned ? null : <HashtagHeader tag={tag} disabled={!signedIn} onClick={this.handleFollow} />}
|
||||
prepend={pinned ? null : <HashtagHeader tagId={id} />}
|
||||
alwaysPrepend
|
||||
trackScroll={!pinned}
|
||||
scrollKey={`hashtag_timeline-${columnId}`}
|
||||
|
|
|
@ -546,8 +546,8 @@
|
|||
"notification.admin.report_statuses_other": "{name} denunciou a {target}",
|
||||
"notification.admin.sign_up": "{name} rexistrouse",
|
||||
"notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {# máis} other {# máis}} crearon unha conta",
|
||||
"notification.annual_report.message": "A #VidaEnMastodon de {year} agarda por ti! Desvela os momentos máis destacados e historias reseñables en Mastodon!",
|
||||
"notification.annual_report.view": "Ver #VidaEnMastodon",
|
||||
"notification.annual_report.message": "#Wrapstodon de {year} agarda por ti! Desvela os momentos máis destacados e historias reseñables en Mastodon!",
|
||||
"notification.annual_report.view": "Ver #Wrapstodon",
|
||||
"notification.favourite": "{name} marcou como favorita a túa publicación",
|
||||
"notification.favourite.name_and_others_with_link": "{name} e <a>{count, plural, one {# máis} other {# máis}}</a> favoreceron a túa publicación",
|
||||
"notification.follow": "{name} comezou a seguirte",
|
||||
|
|
|
@ -20,10 +20,13 @@
|
|||
"account.block_short": "封鎖",
|
||||
"account.blocked": "Hőng封鎖",
|
||||
"account.cancel_follow_request": "取消跟tuè",
|
||||
"account.copy": "Khóo-pih kàu個人資料ê連結",
|
||||
"account.direct": "私人提起 @{name}",
|
||||
"account.follow_back": "Tuè tńg去",
|
||||
"annual_report.summary.percentile.text": "<topLabel>Tse 予lí變做 {domain} ê用戶ê </topLabel><percentage></percentage><bottomLabel></bottomLabel>",
|
||||
"block_modal.show_less": "看khah少",
|
||||
"compose.language.change": "換語言",
|
||||
"confirmations.follow_to_list.confirm": "跟tuè,加入kàu列單",
|
||||
"search_popout.language_code": "ISO語言代碼"
|
||||
"search_popout.language_code": "ISO語言代碼",
|
||||
"status.translated_from_with": "用 {provider} 翻譯 {lang}"
|
||||
}
|
||||
|
|
7
app/javascript/mastodon/models/tags.ts
Normal file
7
app/javascript/mastodon/models/tags.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import type { ApiHashtagJSON } from 'mastodon/api_types/tags';
|
||||
|
||||
export type Hashtag = ApiHashtagJSON;
|
||||
|
||||
export const createHashtag = (serverJSON: ApiHashtagJSON): Hashtag => ({
|
||||
...serverJSON,
|
||||
});
|
|
@ -40,7 +40,6 @@ import settings from './settings';
|
|||
import status_lists from './status_lists';
|
||||
import statuses from './statuses';
|
||||
import { suggestionsReducer } from './suggestions';
|
||||
import tags from './tags';
|
||||
import timelines from './timelines';
|
||||
import trends from './trends';
|
||||
import user_lists from './user_lists';
|
||||
|
@ -83,7 +82,6 @@ const reducers = {
|
|||
markers: markersReducer,
|
||||
picture_in_picture: pictureInPictureReducer,
|
||||
history,
|
||||
tags,
|
||||
followed_tags,
|
||||
reaction_deck,
|
||||
notificationPolicy: notificationPolicyReducer,
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
|
||||
import {
|
||||
HASHTAG_FETCH_SUCCESS,
|
||||
HASHTAG_FOLLOW_REQUEST,
|
||||
HASHTAG_FOLLOW_FAIL,
|
||||
HASHTAG_UNFOLLOW_REQUEST,
|
||||
HASHTAG_UNFOLLOW_FAIL,
|
||||
} from 'mastodon/actions/tags';
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
||||
export default function tags(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case HASHTAG_FETCH_SUCCESS:
|
||||
return state.set(action.name, fromJS(action.tag));
|
||||
case HASHTAG_FOLLOW_REQUEST:
|
||||
case HASHTAG_UNFOLLOW_FAIL:
|
||||
return state.setIn([action.name, 'following'], true);
|
||||
case HASHTAG_FOLLOW_FAIL:
|
||||
case HASHTAG_UNFOLLOW_REQUEST:
|
||||
return state.setIn([action.name, 'following'], false);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -192,9 +192,11 @@ bg:
|
|||
create_user_role: Създаване на роля
|
||||
demote_user: Понижаване на потребител
|
||||
destroy_announcement: Изтриване на оповестяване
|
||||
destroy_canonical_email_block: Изтриване на блокиране за е-поща
|
||||
destroy_custom_emoji: Изтриване на персонализирано емоджи
|
||||
destroy_domain_allow: Изтриване на позволението за домейн
|
||||
destroy_domain_block: Изтриване на блокирането за домейна
|
||||
destroy_email_domain_block: Изтриване на блокиране на домейн на е-поща
|
||||
destroy_instance: Чистка на домейна
|
||||
destroy_ip_block: Изтриване на правило за IP
|
||||
destroy_status: Изтриване на публикация
|
||||
|
|
|
@ -455,6 +455,7 @@ eo:
|
|||
title: Bloki novan retpoŝtan domajnon
|
||||
no_email_domain_block_selected: Neniuj domajn blokoj ŝanĝiĝis ĉar nenio estis elektita
|
||||
not_permitted: Ne permesita
|
||||
resolved_dns_records_hint_html: La nomo de la domajno almontras la sekvajn MX-domajnojn, kiuj estas fine responsaj por akcepti retpoŝton. Blokas MX-domajnon blokus enskribadojn el retpoŝtadreso ajn, kiu uzas la saman MX-domajnon, eĉ se la videbla domajnnomo estas malsama. <strong> Gardemu ne bloki maĵorajn provizistojn de retpoŝto.</strong>
|
||||
resolved_through_html: Solvis tra %{domain}
|
||||
title: Blokis retpoŝtajn domajnojn
|
||||
export_domain_allows:
|
||||
|
@ -483,6 +484,7 @@ eo:
|
|||
instances:
|
||||
audit_log:
|
||||
title: Novaj Protokoloj Pri Ekzamenoj
|
||||
view_all: Vidu la tutan protokolon de revizio
|
||||
availability:
|
||||
description_html:
|
||||
one: Se sendo la domajno malsukcesis por <strong>%{count} dio</strong>, ne estas sendprovo plu escepte <em>de</em> la dojmano.
|
||||
|
@ -609,6 +611,7 @@ eo:
|
|||
resolve_description_html: Nenio okazotas al la raportita konto kaj la raporto fermotas.
|
||||
silence_description_html: La konto estos videbla al nur personoj kiu jam sekvis ĝin au permane serĉo ĝin, ege limigante ĝian atingon. Malfermi ciujn raportojn kontra ĉi tiun konton.
|
||||
suspend_description_html: La konto kaj ciuj ĝiaj enhavoj estos neatingebla kaj poŝte forigitas, kaj interagi per ĝi estos neebla. Malfermi ciujn raportojn kontra ĉi tiu konto.
|
||||
actions_description_html: Elektu kiun agon fari por ripari ĉi tiun raporton. Se vi punus la raportitan uzanton, sciigon de retpoŝto sendos al ri, krom kiam la <strong>Spamo</strong> kategorio estas elektita.
|
||||
actions_description_remote_html: Decidu kiun klopodon por solvi ĉi tiun raporton. Ĉi tiu efikas kiel nur <strong>via</strong> servilo komuniki per ĉi tiu fora konto kaj trakti ĝian enhavon.
|
||||
actions_no_posts: Ĉi tiu raporto havas neniujn rilatajn afiŝojn por forigi
|
||||
add_to_report: Aldoni pli al raporto
|
||||
|
@ -630,6 +633,7 @@ eo:
|
|||
created_at: Signalita
|
||||
delete_and_resolve: Forigi afiŝojn
|
||||
forwarded: Plusendita
|
||||
forwarded_replies_explanation: Ĉi tiu raporto estas de malproksima uzanto kaj estas pri malproksima enhavo. Ĝi plusendis al vi ĉar la raportita enhavo estas rediraĵo je unu el viaj uzantoj.
|
||||
forwarded_to: Plusendita al %{domain}
|
||||
mark_as_resolved: Marki solvita
|
||||
mark_as_sensitive: Marki kiel tiklan
|
||||
|
@ -673,6 +677,7 @@ eo:
|
|||
delete_data_html: Forigi profilon kaj enhavojn de <strong>@%{acct}</strong> post 30 tagoj se ili ne malsuspenditas dum la dauro
|
||||
preview_preamble_html: "<strong>@%{acct}</strong> akiros averton kun ĉi tiuj enhavoj:"
|
||||
record_strike_html: Rekordu admonon kontra <strong>@%{acct}</strong> por helpi vi plikontroli estontajn malobservojn de ĉi tiu konto
|
||||
send_email_html: Sendu <strong>@%{acct}</strong> retpoŝto de averto
|
||||
warning_placeholder: Nedeviga aldona kialo por la moderigadago.
|
||||
target_origin: Origino de raportita konto
|
||||
title: Signaloj
|
||||
|
@ -712,6 +717,7 @@ eo:
|
|||
manage_appeals: Administri Apelaciojn
|
||||
manage_appeals_description: Rajtigas al uzantoj kontroli apelaciojn kontraǔ kontrolaj agoj
|
||||
manage_blocks: Administri Blokojn
|
||||
manage_blocks_description: Permesas uzantojn bloki provizistojn de retpoŝto kaj IP adresojn
|
||||
manage_custom_emojis: Administri propajn emoĝiojn
|
||||
manage_custom_emojis_description: Permesi uzantojn administri propajn emoĝiojn ĉe la servilo
|
||||
manage_federation: Administri Federacion
|
||||
|
@ -729,6 +735,7 @@ eo:
|
|||
manage_taxonomies: Administri kategoriarojn
|
||||
manage_taxonomies_description: Permesi uzantojn kontroli popularan enhavon kaj ĝisdatigi kradvortopciojn
|
||||
manage_user_access: Administri uzantoaliron
|
||||
manage_user_access_description: Permesas uzantojn invalidi la du-faktoran aŭtentigon de aliaj uzantoj, ŝanĝi siajn retpoŝtadresojn, kaj restarigi siajn pasvorton
|
||||
manage_users: Administri uzantojn
|
||||
manage_users_description: Permesi uzantaojn vidi detalojn de aliaj uzantoj kaj administri ilin
|
||||
manage_webhooks: Administri rethokojn
|
||||
|
@ -791,15 +798,19 @@ eo:
|
|||
approved: Bezonas aprobi por aliĝi
|
||||
none: Neniu povas aliĝi
|
||||
open: Iu povas aliĝi
|
||||
warning_hint: Ni rekomendas uzi "Konsento neprigas por enskribiĝi" krom se vi memcertas, ke via teamo de moderistoj povas ellabori spamon kaj malignajn registradojn rapide.
|
||||
security:
|
||||
authorized_fetch: Devigi aŭtentigon de frataraj serviloj
|
||||
authorized_fetch_hint: Neprigante aŭtentigon por federataj serviloj permesas pli striktan devigon de ambaŭ uzanto-nivelaj kaj servilo-nivelaj blokoj. Tamen, ĉi tiu uzas pli risurcojn, reduktas la ĝisiradon de viaj respondoj, kaj povas enkonduki aferoj, pri kongruoj. Plu, ĉi tiu ne preventos homojn el alporti viajn afiŝojn kaj uzantojn.
|
||||
authorized_fetch_overridden_hint: Vi nuntempe ne povas ŝanĝi ĉi tiun agordon ĉar ĝi estas anstataŭita de mediovariablo.
|
||||
federation_authentication: Devigado de la aŭtentigo de la federacio
|
||||
title: Agordoj de la servilo
|
||||
site_uploads:
|
||||
delete: Forigi elŝutitan dosieron
|
||||
destroyed_msg: Reteja alŝuto sukcese forigita!
|
||||
software_updates:
|
||||
critical_update: Kritika — bonvolu ĝisdatiĝi rapide
|
||||
description: Ni rekomendas ĝisdatigadi vian instalaĵon de Mastodon por deutili la plej ĵusajn riparojn kaj trajtojn. Plu, estas kelkajfoje grava ĝisdati Mastodon rapide por eviti problemojn pri sekureco. Tial, Mastodon kontrolas por ĝisdataĵoj ĉiuj 30 minutoj, kaj sciigos vin laŭ viaj agordoj pri retpoŝtaj sciigoj.
|
||||
documentation_link: Lerni pli
|
||||
release_notes: Eldono-notoj
|
||||
title: Disponeblaj ĝisdatigoj
|
||||
|
@ -815,6 +826,7 @@ eo:
|
|||
back_to_account: Reveni al konta paĝo
|
||||
back_to_report: Reveni al raportpaĝo
|
||||
batch:
|
||||
add_to_report: 'Aldoni al raporto #%{id}'
|
||||
remove_from_report: Forigi de raporto
|
||||
report: Raporti
|
||||
contents: Enhavoj
|
||||
|
@ -833,6 +845,7 @@ eo:
|
|||
reblogs: Reblogaĵoj
|
||||
replied_to_html: Respondis al %{acct_link}
|
||||
status_changed: Afiŝo ŝanĝiĝis
|
||||
status_title: Afiŝo de @%{name}
|
||||
title: Afiŝoj de konto - @%{name}
|
||||
trending: Popularaĵoj
|
||||
view_publicly: Vidu publike
|
||||
|
@ -853,10 +866,20 @@ eo:
|
|||
system_checks:
|
||||
database_schema_check:
|
||||
message_html: Estas pritraktataj datumbazaj migradoj. Bonvolu ekzekuti ilin por certigi, ke la apliko kondutas kiel atendite
|
||||
elasticsearch_health_red:
|
||||
message_html: Elasticsearch peniko estas malsana (ruĝa statuso), trajtoj de serĉo malhaveblas
|
||||
elasticsearch_health_yellow:
|
||||
message_html: Peniko de Elasticsearch malsana (flava status), vi eble povas enketi la kialon
|
||||
elasticsearch_index_mismatch:
|
||||
message_html: Bildigoj de enhavtabelo de Elasticsearch posttempas. Bonvolu, rulu <code>tootctl search deploy --only=%{value}</code>
|
||||
elasticsearch_preset:
|
||||
action: Legi dokumentaron
|
||||
message_html: Via peniko de Elasticsearch havas pli ol unu verticon, sed Mastodon ne estas agordita uzi ilin.
|
||||
elasticsearch_preset_single_node:
|
||||
action: Vidi dokumentadon
|
||||
message_html: Via peniko de Elasticsearch havas nur unu verticon, <code>ES_PRESET</code> devus munti al <code>single_node_cluster</code>.
|
||||
elasticsearch_reset_chewy:
|
||||
message_html: Via enhavtabelo de la sistemo de Elasticsearch posttempas pro ŝanĝo de agordoj. Bonvolu, rulu <code>tootctl search deploy --reset-chewy</code> por ĝisdatigi ĝin.
|
||||
elasticsearch_running_check:
|
||||
message_html: Ne eblas konekti Elasticsearch. Bonvolu kontroli ke ĝi funkcias, aǔ malŝaltu plentekstan serĉon
|
||||
elasticsearch_version_check:
|
||||
|
@ -875,6 +898,7 @@ eo:
|
|||
message_html: Grava ĝisdatigo de Mastodon disponeblas, bonvolu ĝisdatigi kiel eble plej rapide.
|
||||
software_version_patch_check:
|
||||
action: Vidi disponeblajn ĝisdatigojn
|
||||
message_html: Ĝisdataĵo de Mastodon pri cimriparo haveblas.
|
||||
upload_check_privacy_error:
|
||||
action: Klaku ĉi tie por pliaj informoj
|
||||
message_html: "<strong>Via retservilo estas misagordita. La privateco de viaj uzantoj estas en risko.</strong>"
|
||||
|
@ -883,10 +907,13 @@ eo:
|
|||
message_html: "<strong>Via objektostokado estas misagordita. La privateco de viaj uzantoj estas en risko.</strong>"
|
||||
tags:
|
||||
moderation:
|
||||
not_trendable: Ne modebla
|
||||
not_usable: Ne uzebla
|
||||
pending_review: Pendata superrigardo
|
||||
review_requested: Revizio petita
|
||||
reviewed: Reviziita
|
||||
title: Stato
|
||||
trendable: Modebla
|
||||
unreviewed: Nereviziita
|
||||
usable: Uzebla
|
||||
name: Nomo
|
||||
|
@ -935,7 +962,9 @@ eo:
|
|||
statuses:
|
||||
allow: Permesi afiŝon
|
||||
allow_account: Permesi aŭtoron
|
||||
confirm_allow: Ĉu vi certas, ke vi volas permesi elektitajn statusojn?
|
||||
confirm_allow_account: Ĉu vi certas, ke vi volas permesi elektitajn kontojn?
|
||||
confirm_disallow: Ĉu vi certas, ke vi volas malpermesi elektitajn statusojn?
|
||||
confirm_disallow_account: Ĉu vi certas, ke vi volas malpermesi elektitajn kontojn?
|
||||
description_html: Oni multe diskonigas kaj stelumas ĉi tiujn mesaĝojn nuntempe laŭ via servilo. Tio povas helpi novajn kaj revenantajn uzantojn trovi pli da homoj por sekvi. Mesaĝo estas montrita publike nur se vi aprobis la aŭtoron kaj se la aŭtoro aprobis ke ties konto estu proponita al aliaj. Vi ankaŭ povas permesi aŭ malakcepti specifajn mesaĝojn.
|
||||
disallow: Malpermesi afiŝon
|
||||
|
@ -976,6 +1005,7 @@ eo:
|
|||
delete: Forigi
|
||||
edit_preset: Redakti avertan antaŭagordon
|
||||
empty: Vi ankoraŭ ne difinis iun ajn antaŭagordon de averto.
|
||||
title: Antaŭdifinoj de averto
|
||||
webhooks:
|
||||
add_new: Aldoni finpunkton
|
||||
delete: Forigi
|
||||
|
@ -997,6 +1027,9 @@ eo:
|
|||
title: Rethokoj
|
||||
webhook: Rethoko
|
||||
admin_mailer:
|
||||
auto_close_registrations:
|
||||
body: Pro seneco de ĵusaj aktivaĵoj de moderistoj, enskribadojn en %{instance} aŭtomate ŝanĝis al mana superrigardo, por eviti %{instance} estas uzita por eblaj fiuloj. Vi povas reŝanĝi ĝin al malfermaj enskribadoj iam ajn.
|
||||
subject: Enskribadoj por %{instance} aŭtomate ŝanĝis al mana konsento
|
||||
new_appeal:
|
||||
actions:
|
||||
delete_statuses: por forigi iliajn afiŝojn
|
||||
|
@ -1011,6 +1044,7 @@ eo:
|
|||
subject: "%{username} apelacias kontroldecidon ĉe %{instance}"
|
||||
new_critical_software_updates:
|
||||
body: Novaj gravaj versioj de Mastodon estis publikigitaj, vi eble volas ĝisdatigi kiel eble plej baldaŭ!
|
||||
subject: Sojlaj ĝisdataĵoj de Mastodon haveblas por %{instance}!
|
||||
new_pending_account:
|
||||
body: La detaloj de la nova konto estas ĉi-sube. Vi povas akcepti aŭ malakcepti tiun aliĝilon.
|
||||
subject: Nova konto atendas por recenzo en %{instance} (%{username})
|
||||
|
@ -1071,10 +1105,12 @@ eo:
|
|||
hint_html: Nur unu plia afero! Ni devas konfirmi, ke vi estas homo (tio estas por ke ni povu konservi la spamon ekstere!). Solvu la CAPTCHA sube kaj alklaku "Daŭrigu".
|
||||
title: Sekureckontrolo
|
||||
confirmations:
|
||||
awaiting_review: Via retpoŝtadreso estas konfirmita! La teamo de %{domain} nun superrigardas vian enskribiĝon. Vi ricevos retpoŝton, se ili aprobos vian konton!
|
||||
awaiting_review_title: Via registriĝo estas reviziita
|
||||
clicking_this_link: alklakante ĉi tiun ligilon
|
||||
login_link: ensaluti
|
||||
proceed_to_login_html: Vi nun povas iri al %{login_link}.
|
||||
redirect_to_app_html: Vi devus sendigi al la <strong>%{app_name}</strong> aplikaĵo. Se tion ne okazis, provu %{clicking_this_link} aŭ mane reiras al la aplikaĵo.
|
||||
registration_complete: Via registriĝo sur %{domain} nun finiĝis!
|
||||
welcome_title: Bonvenon, %{name}!
|
||||
wrong_email_hint: Se tiu retadreso ne estas ĝusta, vi povas ŝanĝi ĝin en kontagordoj.
|
||||
|
@ -1120,6 +1156,8 @@ eo:
|
|||
security: Sekureco
|
||||
set_new_password: Elekti novan pasvorton
|
||||
setup:
|
||||
email_below_hint_html: Kontrolu vian spam-dosierujon aŭ petu novan. Se necese, vi povas korekti vian retadreson.
|
||||
email_settings_hint_html: Enklaku la ligilon, ke ni sendis al vi por kontroli %{email}. Ni estos tien.
|
||||
link_not_received: Ĉu vi ne ricevis ligilon?
|
||||
new_confirmation_instructions_sent: Vi ricevos novan retpoŝton kun la konfirma ligilo post kelkaj minutoj!
|
||||
title: Kontrolu vian retpoŝta enirkesto
|
||||
|
@ -1127,13 +1165,16 @@ eo:
|
|||
preamble_html: Ensalutu per via detaloj de <strong>%{domain}</strong>. Se via konto gastigantigas sur malsama servilo, vi ne povas ensaluti ĉi tie.
|
||||
title: Saluti en %{domain}
|
||||
sign_up:
|
||||
manual_review: Enskriboj en %{domain} havas manan superrigardon, farita de niaj moderistoj. Por helpi nin por procezi vian enskribon, skribu ion pri vi mem, kaj kial vi volas konton en %{domain}.
|
||||
preamble: Per konto ĉe ĉi tiu Mastodon-servilo, vi povas sekvi ajn personojn en la reto.
|
||||
title: Ni pretigu vin ĉe %{domain}.
|
||||
status:
|
||||
account_status: Statuso de la konto
|
||||
confirming: Atendante ke retpoŝta konfirmo estos kompletigita.
|
||||
functional: Via konto estas tute funkcia.
|
||||
pending: Via apliko estas superrigardata de niaj teamo. Ĉi tiu povas bezoni iom da tempo. Vi ricevos retpoŝton, se via apliko estas konsentita.
|
||||
redirecting_to: Via konto estas neaktiva ĉar ĝi nun alidirektas al %{acct}.
|
||||
self_destruct: Pro %{domain} ekfermas, vi povos nur havi malvastan atingon al via konto.
|
||||
view_strikes: Vidi antauaj admonoj kontra via konto
|
||||
too_fast: Formularo sendita tro rapide, klopodu denove.
|
||||
use_security_key: Uzi sekurecan ŝlosilon
|
||||
|
@ -1183,6 +1224,7 @@ eo:
|
|||
data_removal: Viaj afiŝoj kaj aliaj informoj estos forigita por eterne
|
||||
email_change_html: Vi povas <a href="%{path}">ŝanĝi vian retadreson</a> sen forigi vian konton
|
||||
email_contact_html: Se ĝi ankoraŭ ne alvenas, vi povas retpoŝti al <a href="mailto:%{email}">%{email}</a> por helpo
|
||||
email_reconfirmation_html: Se vi ne ricevas la konfirmretpoŝton, vi povas <a href="%{path}">denove peti</a>
|
||||
irreversible: Vi ne povas regajni au reaktivigi vian konton
|
||||
more_details_html: Por pli da detaloj, vidi la <a href="%{terms_path}">privatecan politikon</a>.
|
||||
username_available: Via uzantnomo iĝos denove disponebla
|
||||
|
@ -1219,6 +1261,7 @@ eo:
|
|||
your_appeal_rejected: Via apelacio malakceptitas
|
||||
edit_profile:
|
||||
basic_information: Baza informo
|
||||
hint_html: "<strong>Personigi, kion homoj vidi en via publika profilo kaj apud viaj afiŝoj. </strong> Aliaj homoj estas pli probable resekvi vin kaj interagi kun vi se vi havus finigitan profilon kaj profilan foton."
|
||||
other: Alia
|
||||
errors:
|
||||
'400': La peto kiun vi sendis estas nevalida au malformas.
|
||||
|
@ -1341,6 +1384,44 @@ eo:
|
|||
merge_long: Konservi ekzistajn registrojn kaj aldoni novajn
|
||||
overwrite: Anstataŭigi
|
||||
overwrite_long: Anstataŭigi la nunajn registrojn per la novaj
|
||||
overwrite_preambles:
|
||||
blocking_html:
|
||||
one: Vi tuj <strong>anstataŭas vian blokliston</strong>, kun ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
|
||||
other: Vi tuj <strong>anstataŭas vian blokliston</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
|
||||
bookmarks_html:
|
||||
one: Vi tuj <strong>anstataŭas viajn legosignojn</strong> kun ĝis <strong>%{count} afiŝoj</strong> de <strong>%{filename}</strong>.
|
||||
other: Vi tuj <strong>anstataŭas viajn legosignojn</strong> kun ĝis <strong>%{count} afiŝoj</strong> de <strong>%{filename}</strong>.
|
||||
domain_blocking_html:
|
||||
one: Vi tuj <strong>anstataŭas vian domajnan blokliston</strong> kun ĝis <strong>%{count} domajnoj</strong> de <strong>%{filename}</strong>.
|
||||
other: Vi tuj <strong>anstataŭas vian domajnan blokliston</strong> kun ĝis <strong>%{count} domajnoj</strong> de <strong>%{filename}</strong>.
|
||||
following_html:
|
||||
one: Vi tuj <strong>sekvos</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong> kaj <strong>ĉesos sekvi iun alian</strong>.
|
||||
other: Vi tuj <strong>sekvos</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong> kaj <strong>ĉesos sekvi iun alian</strong>.
|
||||
lists_html:
|
||||
one: Vi tuj <strong>anstataŭos viajn listojn</strong> kun enhavo de <strong>%{filename}</strong>. Ĝis <strong>%{count} kontoj</strong> estos aldonitaj al novaj listoj.
|
||||
other: Vi tuj <strong>anstataŭos viajn listojn</strong> kun enhavo de <strong>%{filename}</strong>. Ĝis <strong>%{count} kontoj</strong> estos aldonitaj al novaj listoj.
|
||||
muting_html:
|
||||
one: Vi tuj <strong>anstataŭas viajn listojn de silentigitaj kontoj</strong> kun ĝis<strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
|
||||
other: Vi tuj <strong>anstataŭas viajn listojn de silentigitaj kontoj</strong> kun ĝis<strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
|
||||
preambles:
|
||||
blocking_html:
|
||||
one: Vi tuj <strong>blokas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
|
||||
other: Vi tuj <strong>blokas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
|
||||
bookmarks_html:
|
||||
one: Vi tuj aldonas ĝis <strong>%{count} afiŝojn</strong> de <strong>%{filename}</strong> al viaj <strong>legosignoj</strong>.
|
||||
other: Vi tuj aldonas ĝis <strong>%{count} afiŝojn</strong> de <strong>%{filename}</strong> al viaj <strong>legosignoj</strong>.
|
||||
domain_blocking_html:
|
||||
one: Vi tuj <strong>blokas</strong> ĝis <strong>%{count} domajnoj</strong> de <strong>%{filename}</strong>.
|
||||
other: Vi tuj <strong>blokas</strong> ĝis <strong>%{count} domajnoj</strong> de <strong>%{filename}</strong>.
|
||||
following_html:
|
||||
one: Vi tuj <strong>sekvas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
|
||||
other: Vi tuj <strong>sekvas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
|
||||
lists_html:
|
||||
one: Vi tuj aldonas ĝis <strong>%{count} kontojn</strong> de <strong>%{filename}</strong> al viaj <strong>listoj</strong>. Novaj listoj estos kreitaj se ne estas listo por aldoni.
|
||||
other: Vi tuj aldonas ĝis <strong>%{count} kontojn</strong> de <strong>%{filename}</strong> al viaj <strong>listoj</strong>. Novaj listoj estos kreitaj se ne estas listo por aldoni.
|
||||
muting_html:
|
||||
one: Vi tuj<strong>silentas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
|
||||
other: Vi tuj<strong>silentas</strong> ĝis <strong>%{count} kontoj</strong> de <strong>%{filename}</strong>.
|
||||
preface: Vi povas importi datumojn, kiujn vi eksportis el alia servilo, kiel liston de homoj, kiujn vi sekvas aŭ blokas.
|
||||
recent_imports: Lastatempaj importoj
|
||||
states:
|
||||
|
@ -1352,6 +1433,9 @@ eo:
|
|||
success: Viaj datumoj estis sukcese alŝutitaj kaj estos traktitaj kiel planite
|
||||
time_started: Komencis je
|
||||
titles:
|
||||
blocking: Enportante blokitajn kontojn
|
||||
bookmarks: Enportante legosignojn
|
||||
domain_blocking: Enportante blokitajn domajnojn
|
||||
following: Importado de sekvaj kontoj
|
||||
lists: Importi listojn
|
||||
muting: Importado de silentigitaj kontoj
|
||||
|
@ -1408,13 +1492,21 @@ eo:
|
|||
unsubscribe:
|
||||
action: Jes, malabonu
|
||||
complete: Malabonita
|
||||
confirmation_html: Ĉu vi certas, ke vi volas malaboni je ricevi %{type} por Mastodon ĉe %{domain} al via retpoŝto ĉe %{email}? Vi ĉiam povas reaboni de viaj <a href="%{settings_path}">retpoŝtaj sciigaj agordoj</a>.
|
||||
emails:
|
||||
notification_emails:
|
||||
favourite: sciigoj retpoŝtaj de ŝatataj
|
||||
follow: sciigoj retpoŝtaj de sekvoj
|
||||
follow_request: retpoŝtajn petoj de sekvado
|
||||
mention: sciigoj retpoŝtaj de mencioj
|
||||
reblog: sciigoj retpoŝtaj de stimuloj
|
||||
resubscribe_html: Se vi malabonis erare, vi povas reaboni de viaj <a href="%{settings_path}">retpoŝtaj sciigaj agordoj</a>.
|
||||
success_html: Vi ne plu ricevos %{type} por Mastodon ĉe %{domain} al via retpoŝto ĉe %{email}.
|
||||
title: Malaboni
|
||||
media_attachments:
|
||||
validations:
|
||||
images_and_video: Aldoni videon al mesaĝo, kiu jam havas bildojn ne eblas
|
||||
not_found: Dosiero %{ids} ne trovis aŭ jam alteniĝis al alia afiŝo
|
||||
not_ready: Ne povas aldoni dosieron kiu ne finas procezitis.
|
||||
too_many: Aldoni pli ol 4 dosierojn ne eblas
|
||||
migrations:
|
||||
|
@ -1491,6 +1583,8 @@ eo:
|
|||
update:
|
||||
subject: "%{name} redaktis afiŝon"
|
||||
notifications:
|
||||
administration_emails: Sciigoj retpoŝtaj de administacio
|
||||
email_events: Eventoj por retpoŝtaj sciigoj
|
||||
email_events_hint: 'Elekti la eventojn pri kioj vi volas ricevi sciigojn:'
|
||||
number:
|
||||
human:
|
||||
|
@ -1584,6 +1678,7 @@ eo:
|
|||
scheduled_statuses:
|
||||
over_daily_limit: Vi transpasis la limigon al %{limit} samtage planitaj mesaĝoj
|
||||
over_total_limit: Vi transpasis la limigon al %{limit} planitaj mesaĝoj
|
||||
too_soon: dato devas esti en la futuro
|
||||
self_destruct:
|
||||
lead_html: Bedaŭrinde, <strong>%{domain}</strong> konstante fermiĝas. Se vi havis konton tie, vi ne povos daŭrigi uzi ĝin, sed vi ankoraŭ povas peti sekurkopion de viaj datumoj.
|
||||
title: Ĉi tiu servilo fermiĝas
|
||||
|
@ -1652,6 +1747,7 @@ eo:
|
|||
preferences: Preferoj
|
||||
profile: Profilo
|
||||
relationships: Sekvatoj kaj sekvantoj
|
||||
severed_relationships: Finitaj rilatoj
|
||||
statuses_cleanup: Automata mesaĝforigo
|
||||
strikes: Kontroladmonoj
|
||||
two_factor_authentication: Dufaktora aŭtentigo
|
||||
|
@ -1659,8 +1755,13 @@ eo:
|
|||
severed_relationships:
|
||||
download: Elŝuti (%{count})
|
||||
event_type:
|
||||
account_suspension: Suspendado de konto (%{target_name})
|
||||
domain_block: Suspendado de servilo (%{target_name})
|
||||
user_domain_block: Vi blokis %{target_name}
|
||||
lost_followers: Perditaj sekvantoj
|
||||
lost_follows: Perditaj sekvantoj
|
||||
preamble: Vi eble perdos sekvojn kaj sekvantojn, kiam vi blockus domajnon aŭ kiam viaj moderantoj elektus suspendi malproksiman servilon. Kiam tio okazas, vi povus elŝulti registrojn de finitaj rilatoj, por inspektiĝi kaj eble enporti en alia servilo.
|
||||
purged: Informo pri ĉi tiu servilo foriĝis de la administracio de via servilo.
|
||||
type: Evento
|
||||
statuses:
|
||||
attached:
|
||||
|
@ -1775,19 +1876,24 @@ eo:
|
|||
action: Konto-agordoj
|
||||
explanation: La apelacio de la admono kontra via konto je %{strike_date} pri sendodato %{appeal_date} aprobitas.
|
||||
subject: Via apelacio de %{date} aprobitas
|
||||
subtitle: Via konto estas denove bone.
|
||||
title: Apelacio estis aprobita
|
||||
appeal_rejected:
|
||||
explanation: La apelacio je %{strike_date} pri dato %{appeal_date} malakceptitas.
|
||||
subject: Via apelacio de %{date} estis malaprobita
|
||||
subtitle: Via revizio negiĝis.
|
||||
title: Apelacio estis malaprobita
|
||||
backup_ready:
|
||||
explanation: Vi petis por tuta rezervo de via Mastodon-a konto.
|
||||
extra: Estas nun preta por elŝuto!
|
||||
subject: Via arkivo estas preta por elŝutado
|
||||
title: Arkiva elŝuto
|
||||
failed_2fa:
|
||||
details: 'Jen detaloj de la provaĵo de ensaluti:'
|
||||
explanation: Iu provis ensaluti al via konto sed provizis nevalidan duan aŭtentikigfaktoron.
|
||||
further_actions_html: Se ĉi tio ne estis vi, ni rekomendas ke vi %{action} tuj ĉar ĝi povas esti endanĝerigita.
|
||||
subject: Malsukceso dum la dua aŭtentikigfaktoro
|
||||
title: Du-faktora aŭtentigo malsukcesis
|
||||
suspicious_sign_in:
|
||||
change_password: ŝanĝi vian pasvorton
|
||||
details: 'Ĉi-sube estas detaloj pri la saluto:'
|
||||
|
@ -1831,13 +1937,24 @@ eo:
|
|||
apps_ios_action: Elŝutu ĉe la App Store
|
||||
apps_step: Elŝutu niajn oficialajn aplikaĵojn.
|
||||
apps_title: Aplikaĵoj de Mastodon
|
||||
checklist_subtitle: 'Nin eku vin en ĉi tiu nova socia rando:'
|
||||
checklist_title: Bonvenan Markolisto
|
||||
edit_profile_action: Agordi
|
||||
edit_profile_step: Plibonigi viajn interagojn per havas finitan profilon.
|
||||
edit_profile_title: Agordi vian profilon
|
||||
explanation: Jen kelkaj konsiloj por helpi vin komenci
|
||||
feature_action: Lerni pli
|
||||
feature_audience: Mastodon provizas vin per unika eblo por administri vian sekvantaron sen perantoj. Mastodon disponigita en via propra infrastrukturo ebligas al vi sekvi kaj esti sekvita de alia ajn Mastodon-servilo kaj estas tute sub via kontrolo nure.
|
||||
feature_audience_title: Konstruu vian spektantaron memfide
|
||||
feature_control: Vi scias plej bone, kion vi volas vidi en via hejmtemplinio. Neniaj algoritmoj nek reklamoj por malŝpari vian tempon. Sekvu iun ajn trans Mastodon-servilo ajn el unu konto kaj ricevu iliajn afiŝojn kronologie, kaj igu vian ejon de reto iom pli kiel vi.
|
||||
feature_control_title: Havu la kontrolon de via propra templinio
|
||||
feature_creativity: Mastodon subtenas aŭdaj, videajn kaj bildajn afiŝojn, priskribojn alireblecajn, enketojn, avertojn pri enhavo, animitajn bildetojn, personajn emoĝiojn, stucan kontrolon de bildetoj, kaj pli, por helpi al vi esprimi vin rete. Ĉu vi publikigas vian arton, vian muzikon, aŭ viajn podkastojn, Mastodon estas por vi.
|
||||
feature_creativity_title: Senkompara kreemeco
|
||||
feature_moderation: Mastodon denove donas al vi decidpovon. Ĉiu servilo kreas siajn proprajn regulojn kaj gvidliniojn, kiuj estas devigitaj loke kaj ne desupre kiel en firmaaj sociaj retejoj, igante ĝin la plej agordebla respondante al la bezonoj de malsamaj aroj de homoj. Aliĝu servilon kun la reguloj, kun kiuj vi konsentas, aŭ gastigu vian propran.
|
||||
feature_moderation_title: Moderante kiel ĝi devus esti
|
||||
follow_action: Sekvi
|
||||
follow_step: Sekvi interesajn homojn estas pri kio Mastodon temas.
|
||||
follow_title: Personigu vian hejmtemplinion
|
||||
follows_subtitle: Sekvu konatajn kontojn
|
||||
follows_title: Kiun sekvi
|
||||
follows_view_more: Rigardu pli da homoj por sekvi
|
||||
|
@ -1862,6 +1979,7 @@ eo:
|
|||
invalid_otp_token: Nevalida kodo de dufaktora aŭtentigo
|
||||
otp_lost_help_html: Se vi perdas aliron al ambaŭ, vi povas kontakti %{email}
|
||||
rate_limited: Estas tro multaj aŭtentigaj provoj, reprovu poste.
|
||||
seamless_external_login: Vi estas ensalutinta per ekstera servo, do pasvortaj kaj retpoŝtaj agordoj ne estas disponeblaj.
|
||||
signed_in_as: 'Salutinta kiel:'
|
||||
verification:
|
||||
extra_instructions_html: <strong>Konsilo:</strong> La ligilo en via retejo povas esti nevidebla. La grava parto estas <code>rel="me"</code>, kiu evitas identoŝtelon en retejoj kun enhavo generita de uzantoj. Vi povas eĉ uzi <code>link</code>-etikedon en la <code>header</code> de la paĝo anstataŭ <code>a</code>, sed la HTML devas esti atingebla sen plenumado de JavaScript.
|
||||
|
|
|
@ -1069,11 +1069,11 @@ es-MX:
|
|||
created_msg: El nuevo alias se ha creado correctamente. Ahora puedes empezar el traslado desde la cuenta antigua.
|
||||
deleted_msg: Elimina el alias correctamente. El traslado de esa cuenta a esta ya no será posible.
|
||||
empty: No tienes ningún alias.
|
||||
hint_html: Si quieres migrar de otra cuenta a esta, aquí puedes crear un alias, es necesario proceder antes de empezar a mover seguidores de la cuenta anterior a esta. Esta acción por sí misma es <strong>inofensiva y reversible</strong>. <strong>La migración de la cuenta se inicia desde la cuenta antigua</strong>.
|
||||
hint_html: Si deseas migrar de otra cuenta a esta, aquí puedes crear un alias, que es necesario para poder mover seguidores de la cuenta anterior a esta. Esta acción por sí misma es <strong>inofensiva y reversible</strong>. <strong>La migración de la cuenta se inicia desde la cuenta anterior</strong>.
|
||||
remove: Desvincular alias
|
||||
appearance:
|
||||
advanced_web_interface: Interfaz web avanzada
|
||||
advanced_web_interface_hint: 'Si quieres aprovechar todo el ancho de tu pantalla, la interfaz web avanzada te permite configurar muchas columnas diferentes para ver toda la información que quieras al mismo tiempo: Inicio, notificaciones, cronología federada, cualquier número de listas y etiquetas.'
|
||||
advanced_web_interface_hint: 'Si deseas aprovechar todo el ancho de tu pantalla, la interfaz web avanzada te permite configurar muchas columnas diferentes para ver toda la información que quieras al mismo tiempo: inicio, notificaciones, cronología federada, cualquier número de listas y etiquetas.'
|
||||
animations_and_accessibility: Animaciones y accesibilidad
|
||||
confirmation_dialogs: Diálogos de confirmación
|
||||
discovery: Descubrir
|
||||
|
|
|
@ -1 +1,16 @@
|
|||
---
|
||||
nan:
|
||||
admin:
|
||||
instances:
|
||||
dashboard:
|
||||
instance_languages_dimension: Tsia̍p用ê語言
|
||||
statuses:
|
||||
language: 語言
|
||||
trends:
|
||||
tags:
|
||||
dashboard:
|
||||
tag_languages_dimension: Tsia̍p用ê語言
|
||||
scheduled_statuses:
|
||||
too_soon: Tio̍h用未來ê日期。
|
||||
statuses:
|
||||
default_language: Kap界面ê語言sio kâng
|
||||
|
|
|
@ -60,6 +60,7 @@ eo:
|
|||
setting_display_media_default: Kaŝi plurmediojn markitajn kiel tiklaj
|
||||
setting_display_media_hide_all: Ĉiam kaŝi la plurmediojn
|
||||
setting_display_media_show_all: Ĉiam montri la plurmediojn
|
||||
setting_system_scrollbars_ui: Aplikas nur por surtablaj retumiloj baziĝas de Safari kaj Chrome
|
||||
setting_use_blurhash: Transirojn estas bazita sur la koloroj de la kaŝitaj aŭdovidaĵoj sed ne montri iun ajn detalon
|
||||
setting_use_pending_items: Kaŝi tempoliniajn ĝisdatigojn malantaŭ klako anstataŭ aŭtomate rulumi la fluon
|
||||
username: Vi povas uzi literojn, ciferojn kaj substrekojn
|
||||
|
@ -223,6 +224,7 @@ eo:
|
|||
setting_hide_network: Kaŝi viajn sekvantojn kaj sekvatojn
|
||||
setting_reduce_motion: Redukti la movecojn de la animacioj
|
||||
setting_system_font_ui: Uzi la dekomencan tiparon de la sistemo
|
||||
setting_system_scrollbars_ui: Uzu la defaŭltan rulumilon de la sistemo
|
||||
setting_theme: Etoso de la retejo
|
||||
setting_trends: Montri hodiaŭajn furoraĵojn
|
||||
setting_unfollow_modal: Montri konfirman fenestron antaŭ ol ĉesi sekvi iun
|
||||
|
|
|
@ -16,43 +16,6 @@ def redirect_with_vary(path)
|
|||
end
|
||||
|
||||
Rails.application.routes.draw do
|
||||
# Paths of routes on the web app that to not require to be indexed or
|
||||
# have alternative format representations requiring separate controllers
|
||||
web_app_paths = %w(
|
||||
/getting-started
|
||||
/keyboard-shortcuts
|
||||
/home
|
||||
/public
|
||||
/public/local
|
||||
/public/local/fixed
|
||||
/public/remote
|
||||
/conversations
|
||||
/lists/(*any)
|
||||
/antennas/(*any)
|
||||
/circles/(*any)
|
||||
/links/(*any)
|
||||
/notifications/(*any)
|
||||
/notifications_v2/(*any)
|
||||
/favourites
|
||||
/emoji_reactions
|
||||
/bookmarks
|
||||
/bookmark_categories/(*any)
|
||||
/pinned
|
||||
/reaction_deck
|
||||
/start/(*any)
|
||||
/directory
|
||||
/explore/(*any)
|
||||
/search
|
||||
/publish
|
||||
/follow_requests
|
||||
/blocks
|
||||
/domain_blocks
|
||||
/mutes
|
||||
/followed_tags
|
||||
/statuses/(*any)
|
||||
/deck/(*any)
|
||||
).freeze
|
||||
|
||||
root 'home#index'
|
||||
|
||||
mount LetterOpenerWeb::Engine, at: 'letter_opener' if Rails.env.development?
|
||||
|
@ -236,9 +199,7 @@ Rails.application.routes.draw do
|
|||
|
||||
draw(:api)
|
||||
|
||||
web_app_paths.each do |path|
|
||||
get path, to: 'home#index'
|
||||
end
|
||||
draw(:web_app)
|
||||
|
||||
get '/web/(*any)', to: redirect('/%{any}', status: 302), as: :web, defaults: { any: '' }, format: false
|
||||
get '/about', to: 'about#show'
|
||||
|
|
40
config/routes/web_app.rb
Normal file
40
config/routes/web_app.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Paths handled by the React application, which do not:
|
||||
# - Require indexing
|
||||
# - Have alternative format representations
|
||||
|
||||
%w(
|
||||
/antennas/(*any)
|
||||
/blocks
|
||||
/bookmarks
|
||||
/bookmark_categories/(*any)
|
||||
/circles/(*any)
|
||||
/conversations
|
||||
/deck/(*any)
|
||||
/directory
|
||||
/domain_blocks
|
||||
/emoji_reactions
|
||||
/explore/(*any)
|
||||
/favourites
|
||||
/follow_requests
|
||||
/followed_tags
|
||||
/getting-started
|
||||
/home
|
||||
/keyboard-shortcuts
|
||||
/links/(*any)
|
||||
/lists/(*any)
|
||||
/mutes
|
||||
/notifications_v2/(*any)
|
||||
/notifications/(*any)
|
||||
/pinned
|
||||
/public
|
||||
/public/local
|
||||
/public/local/fixed
|
||||
/public/remote
|
||||
/publish
|
||||
/reaction_deck
|
||||
/search
|
||||
/start/(*any)
|
||||
/statuses/(*any)
|
||||
).each { |path| get path, to: 'home#index' }
|
|
@ -8,6 +8,22 @@ class RemoveLegacyUserSettingsData < ActiveRecord::Migration[7.2]
|
|||
thing_type IS NOT NULL
|
||||
AND thing_id IS NOT NULL
|
||||
SQL
|
||||
|
||||
# When running these migrations on mastodon.social, we saw 'notification_emails'
|
||||
# and 'interactions' records that were not associated to a user and caused a
|
||||
# migration issue.
|
||||
# While I have not been able to pinpoint the exact cause of the issue, it is likely
|
||||
# related to the settings system changes made in b11fdc3ae3f90731c01149a5a36dc64e065d4ea2.
|
||||
# So, delete a few user settings that should already have been deleted.
|
||||
connection.execute(<<~SQL.squish)
|
||||
DELETE FROM settings
|
||||
WHERE var IN (
|
||||
'notification_emails', 'interactions', 'boost_modal', 'auto_play_gif',
|
||||
'delete_modal', 'system_font_ui', 'default_sensitive', 'unfollow_modal',
|
||||
'reduce_motion', 'display_sensitive_media', 'hide_network', 'expand_spoilers',
|
||||
'display_media', 'aggregate_reblogs', 'show_application', 'advanced_layout',
|
||||
'use_blurhash', 'use_pending_items')
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddMissingDeleteCascadeWebauthnCredentials < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
safety_assured do
|
||||
execute <<~SQL.squish
|
||||
ALTER TABLE webauthn_credentials
|
||||
DROP CONSTRAINT fk_rails_a4355aef77,
|
||||
ADD CONSTRAINT fk_rails_a4355aef77
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES users(id)
|
||||
ON DELETE CASCADE
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
safety_assured do
|
||||
execute <<~SQL.squish
|
||||
ALTER TABLE webauthn_credentials
|
||||
DROP CONSTRAINT fk_rails_a4355aef77,
|
||||
ADD CONSTRAINT fk_rails_a4355aef77
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES users(id)
|
||||
SQL
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,45 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddMissingDeleteCascadeAccountModerationNotes < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
safety_assured do
|
||||
execute <<~SQL.squish
|
||||
ALTER TABLE account_moderation_notes
|
||||
DROP CONSTRAINT fk_rails_3f8b75089b,
|
||||
ADD CONSTRAINT fk_rails_3f8b75089b
|
||||
FOREIGN KEY (account_id)
|
||||
REFERENCES accounts(id)
|
||||
ON DELETE CASCADE
|
||||
SQL
|
||||
|
||||
execute <<~SQL.squish
|
||||
ALTER TABLE account_moderation_notes
|
||||
DROP CONSTRAINT fk_rails_dd62ed5ac3,
|
||||
ADD CONSTRAINT fk_rails_dd62ed5ac3
|
||||
FOREIGN KEY (target_account_id)
|
||||
REFERENCES accounts(id)
|
||||
ON DELETE CASCADE
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
safety_assured do
|
||||
execute <<~SQL.squish
|
||||
ALTER TABLE account_moderation_notes
|
||||
DROP CONSTRAINT fk_rails_3f8b75089b,
|
||||
ADD CONSTRAINT fk_rails_3f8b75089b
|
||||
FOREIGN KEY (account_id)
|
||||
REFERENCES accounts(id)
|
||||
SQL
|
||||
|
||||
execute <<~SQL.squish
|
||||
ALTER TABLE account_moderation_notes
|
||||
DROP CONSTRAINT fk_rails_dd62ed5ac3,
|
||||
ADD CONSTRAINT fk_rails_dd62ed5ac3
|
||||
FOREIGN KEY (target_account_id)
|
||||
REFERENCES accounts(id)
|
||||
SQL
|
||||
end
|
||||
end
|
||||
end
|
|
@ -15,6 +15,22 @@ class RemoveLegacyUserSettingsColumns < ActiveRecord::Migration[7.2]
|
|||
AND thing_id IS NOT NULL
|
||||
SQL
|
||||
|
||||
# When running these migrations on mastodon.social, we saw 'notification_emails'
|
||||
# and 'interactions' records that were not associated to a user and caused a
|
||||
# migration issue.
|
||||
# While I have not been able to pinpoint the exact cause of the issue, it is likely
|
||||
# related to the settings system changes made in b11fdc3ae3f90731c01149a5a36dc64e065d4ea2.
|
||||
# So, delete a few user settings that should already have been deleted.
|
||||
connection.execute(<<~SQL.squish)
|
||||
DELETE FROM settings
|
||||
WHERE var IN (
|
||||
'notification_emails', 'interactions', 'boost_modal', 'auto_play_gif',
|
||||
'delete_modal', 'system_font_ui', 'default_sensitive', 'unfollow_modal',
|
||||
'reduce_motion', 'display_sensitive_media', 'hide_network', 'expand_spoilers',
|
||||
'display_media', 'aggregate_reblogs', 'show_application', 'advanced_layout',
|
||||
'use_blurhash', 'use_pending_items')
|
||||
SQL
|
||||
|
||||
add_index :settings, :var, unique: true, algorithm: :concurrently
|
||||
remove_index :settings, [:thing_type, :thing_id, :var], name: :index_settings_on_thing_type_and_thing_id_and_var, unique: true
|
||||
|
||||
|
|
|
@ -1606,8 +1606,8 @@ ActiveRecord::Schema[7.2].define(version: 2024_12_08_232829) do
|
|||
add_foreign_key "account_domain_blocks", "accounts", name: "fk_206c6029bd", on_delete: :cascade
|
||||
add_foreign_key "account_migrations", "accounts", column: "target_account_id", on_delete: :nullify
|
||||
add_foreign_key "account_migrations", "accounts", on_delete: :cascade
|
||||
add_foreign_key "account_moderation_notes", "accounts"
|
||||
add_foreign_key "account_moderation_notes", "accounts", column: "target_account_id"
|
||||
add_foreign_key "account_moderation_notes", "accounts", column: "target_account_id", on_delete: :cascade
|
||||
add_foreign_key "account_moderation_notes", "accounts", on_delete: :cascade
|
||||
add_foreign_key "account_notes", "accounts", column: "target_account_id", on_delete: :cascade
|
||||
add_foreign_key "account_notes", "accounts", on_delete: :cascade
|
||||
add_foreign_key "account_pins", "accounts", column: "target_account_id", on_delete: :cascade
|
||||
|
@ -1764,7 +1764,7 @@ ActiveRecord::Schema[7.2].define(version: 2024_12_08_232829) do
|
|||
add_foreign_key "web_push_subscriptions", "oauth_access_tokens", column: "access_token_id", on_delete: :cascade
|
||||
add_foreign_key "web_push_subscriptions", "users", on_delete: :cascade
|
||||
add_foreign_key "web_settings", "users", name: "fk_11910667b2", on_delete: :cascade
|
||||
add_foreign_key "webauthn_credentials", "users"
|
||||
add_foreign_key "webauthn_credentials", "users", on_delete: :cascade
|
||||
|
||||
create_view "instances", materialized: true, sql_definition: <<-SQL
|
||||
WITH domain_counts(domain, accounts_count) AS (
|
||||
|
|
|
@ -10,8 +10,14 @@ RSpec.describe 'Custom CSS' do
|
|||
it 'returns empty stylesheet' do
|
||||
get '/custom.css'
|
||||
|
||||
expect(response.content_type).to include('text/css')
|
||||
expect(response.body.presence).to be_nil
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
.and have_cacheable_headers
|
||||
.and have_attributes(
|
||||
content_type: match('text/css')
|
||||
)
|
||||
expect(response.body.presence)
|
||||
.to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -23,8 +29,14 @@ RSpec.describe 'Custom CSS' do
|
|||
it 'returns stylesheet from settings' do
|
||||
get '/custom.css'
|
||||
|
||||
expect(response.content_type).to include('text/css')
|
||||
expect(response.body.strip).to eq(expected_css)
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
.and have_cacheable_headers
|
||||
.and have_attributes(
|
||||
content_type: match('text/css')
|
||||
)
|
||||
expect(response.body.strip)
|
||||
.to eq(expected_css)
|
||||
end
|
||||
|
||||
def expected_css
|
||||
|
@ -44,8 +56,14 @@ RSpec.describe 'Custom CSS' do
|
|||
it 'returns stylesheet from settings' do
|
||||
get '/custom.css'
|
||||
|
||||
expect(response.content_type).to include('text/css')
|
||||
expect(response.body.strip).to eq(expected_css)
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
.and have_cacheable_headers
|
||||
.and have_attributes(
|
||||
content_type: match('text/css')
|
||||
)
|
||||
expect(response.body.strip)
|
||||
.to eq(expected_css)
|
||||
end
|
||||
|
||||
def expected_css
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Custom stylesheets' do
|
||||
describe 'GET /custom.css' do
|
||||
before { get '/custom.css' }
|
||||
|
||||
it 'returns http success' do
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
.and have_cacheable_headers
|
||||
.and have_attributes(
|
||||
content_type: match('text/css')
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
28
yarn.lock
28
yarn.lock
|
@ -1372,8 +1372,8 @@ __metadata:
|
|||
linkType: hard
|
||||
|
||||
"@babel/preset-react@npm:^7.12.5, @babel/preset-react@npm:^7.22.3":
|
||||
version: 7.25.9
|
||||
resolution: "@babel/preset-react@npm:7.25.9"
|
||||
version: 7.26.3
|
||||
resolution: "@babel/preset-react@npm:7.26.3"
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils": "npm:^7.25.9"
|
||||
"@babel/helper-validator-option": "npm:^7.25.9"
|
||||
|
@ -1383,7 +1383,7 @@ __metadata:
|
|||
"@babel/plugin-transform-react-pure-annotations": "npm:^7.25.9"
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0-0
|
||||
checksum: 10c0/c294b475ee741f01f63ea0d828862811c453fabc6023f01814ce983bc316388e9d73290164d2b1384c2684db9c330803a3d4d2170285b105dcbacd483329eb93
|
||||
checksum: 10c0/b470dcba11032ef6c832066f4af5c75052eaed49feb0f445227231ef1b5c42aacd6e216988c0bd469fd5728cd27b6b059ca307c9ecaa80c6bb5da4bf1c833e12
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
@ -1972,8 +1972,8 @@ __metadata:
|
|||
linkType: hard
|
||||
|
||||
"@dnd-kit/core@npm:^6.1.0":
|
||||
version: 6.3.0
|
||||
resolution: "@dnd-kit/core@npm:6.3.0"
|
||||
version: 6.3.1
|
||||
resolution: "@dnd-kit/core@npm:6.3.1"
|
||||
dependencies:
|
||||
"@dnd-kit/accessibility": "npm:^3.1.1"
|
||||
"@dnd-kit/utilities": "npm:^3.2.2"
|
||||
|
@ -1981,7 +1981,7 @@ __metadata:
|
|||
peerDependencies:
|
||||
react: ">=16.8.0"
|
||||
react-dom: ">=16.8.0"
|
||||
checksum: 10c0/7b6ebae619921ac27a367b5f168cf66729ab2f5041a5376bb05399cdfd05e03c8fac5d218632ee04fe7c1e049bde9222930c6e8ee1dbb0ca8bde38038f1a1a48
|
||||
checksum: 10c0/196db95d81096d9dc248983533eab91ba83591770fa5c894b1ac776f42af0d99522b3fd5bb3923411470e4733fcfa103e6ee17adc17b9b7eb54c7fbec5ff7c52
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
@ -8501,8 +8501,8 @@ __metadata:
|
|||
linkType: hard
|
||||
|
||||
"express@npm:^4.17.1, express@npm:^4.18.2":
|
||||
version: 4.21.1
|
||||
resolution: "express@npm:4.21.1"
|
||||
version: 4.21.2
|
||||
resolution: "express@npm:4.21.2"
|
||||
dependencies:
|
||||
accepts: "npm:~1.3.8"
|
||||
array-flatten: "npm:1.1.1"
|
||||
|
@ -8523,7 +8523,7 @@ __metadata:
|
|||
methods: "npm:~1.1.2"
|
||||
on-finished: "npm:2.4.1"
|
||||
parseurl: "npm:~1.3.3"
|
||||
path-to-regexp: "npm:0.1.10"
|
||||
path-to-regexp: "npm:0.1.12"
|
||||
proxy-addr: "npm:~2.0.7"
|
||||
qs: "npm:6.13.0"
|
||||
range-parser: "npm:~1.2.1"
|
||||
|
@ -8535,7 +8535,7 @@ __metadata:
|
|||
type-is: "npm:~1.6.18"
|
||||
utils-merge: "npm:1.0.1"
|
||||
vary: "npm:~1.1.2"
|
||||
checksum: 10c0/0c287867e5f6129d3def1edd9b63103a53c40d4dc8628839d4b6827e35eb8f0de5a4656f9d85f4457eba584f9871ebb2ad26c750b36bd75d9bbb8bcebdc4892c
|
||||
checksum: 10c0/38168fd0a32756600b56e6214afecf4fc79ec28eca7f7a91c2ab8d50df4f47562ca3f9dee412da7f5cea6b1a1544b33b40f9f8586dbacfbdada0fe90dbb10a1f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
@ -13104,10 +13104,10 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"path-to-regexp@npm:0.1.10":
|
||||
version: 0.1.10
|
||||
resolution: "path-to-regexp@npm:0.1.10"
|
||||
checksum: 10c0/34196775b9113ca6df88e94c8d83ba82c0e1a2063dd33bfe2803a980da8d49b91db8104f49d5191b44ea780d46b8670ce2b7f4a5e349b0c48c6779b653f1afe4
|
||||
"path-to-regexp@npm:0.1.12":
|
||||
version: 0.1.12
|
||||
resolution: "path-to-regexp@npm:0.1.12"
|
||||
checksum: 10c0/1c6ff10ca169b773f3bba943bbc6a07182e332464704572962d277b900aeee81ac6aa5d060ff9e01149636c30b1f63af6e69dd7786ba6e0ddb39d4dee1f0645b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue