Merge commit '081d38679f965ac20ff1a6c72e2fc1108c34ac30' into glitch-soc/merge-upstream
This commit is contained in:
commit
53185f5381
69 files changed
+1172
-529
No files matched your search
@@ -37,7 +37,7 @@ export interface BaseApiAccountJSON {
|
||||
roles?: ApiAccountJSON[];
|
||||
statuses_count: number;
|
||||
uri: string;
|
||||
url: string;
|
||||
url?: string;
|
||||
username: string;
|
||||
moved?: ApiAccountJSON;
|
||||
suspended?: boolean;
|
||||
|
||||
@@ -13,6 +13,7 @@ export const allNotificationTypes = [
|
||||
'favourite',
|
||||
'reblog',
|
||||
'mention',
|
||||
'quote',
|
||||
'poll',
|
||||
'status',
|
||||
'update',
|
||||
@@ -28,6 +29,7 @@ export type NotificationWithStatusType =
|
||||
| 'reblog'
|
||||
| 'status'
|
||||
| 'mention'
|
||||
| 'quote'
|
||||
| 'poll'
|
||||
| 'update';
|
||||
|
||||
|
||||
@@ -15,17 +15,6 @@ export const SKIN_TONE_CODES = [
|
||||
0x1f3ff, // Dark skin tone
|
||||
] as const;
|
||||
|
||||
// TODO: Test and create fallback for browsers that do not handle the /v flag.
|
||||
export const UNICODE_EMOJI_REGEX = /\p{RGI_Emoji}/v;
|
||||
// See: https://www.unicode.org/reports/tr51/#valid-emoji-tag-sequences
|
||||
export const UNICODE_FLAG_EMOJI_REGEX =
|
||||
/\p{RGI_Emoji_Flag_Sequence}|\p{RGI_Emoji_Tag_Sequence}/v;
|
||||
export const CUSTOM_EMOJI_REGEX = /:([a-z0-9_]+):/i;
|
||||
export const ANY_EMOJI_REGEX = new RegExp(
|
||||
`(${UNICODE_EMOJI_REGEX.source}|${CUSTOM_EMOJI_REGEX.source})`,
|
||||
'gv',
|
||||
);
|
||||
|
||||
// Emoji rendering modes. A mode is what we are using to render emojis, a style is what the user has selected.
|
||||
export const EMOJI_MODE_NATIVE = 'native';
|
||||
export const EMOJI_MODE_NATIVE_WITH_FLAGS = 'native-flags';
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { ComponentPropsWithoutRef, ElementType } from 'react';
|
||||
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
|
||||
import { useEmojify } from './hooks';
|
||||
import type { CustomEmojiMapArg } from './types';
|
||||
|
||||
@@ -12,7 +14,7 @@ type EmojiHTMLProps<Element extends ElementType = 'div'> = Omit<
|
||||
as?: Element;
|
||||
};
|
||||
|
||||
export const EmojiHTML = <Element extends ElementType>({
|
||||
export const ModernEmojiHTML = <Element extends ElementType>({
|
||||
extraEmojis,
|
||||
htmlString,
|
||||
as: asElement, // Rename for syntax highlighting
|
||||
@@ -29,3 +31,18 @@ export const EmojiHTML = <Element extends ElementType>({
|
||||
<Wrapper {...props} dangerouslySetInnerHTML={{ __html: emojifiedHtml }} />
|
||||
);
|
||||
};
|
||||
|
||||
export const EmojiHTML = <Element extends ElementType>(
|
||||
props: EmojiHTMLProps<Element>,
|
||||
) => {
|
||||
if (isModernEmojiEnabled()) {
|
||||
return <ModernEmojiHTML {...props} />;
|
||||
}
|
||||
const Wrapper = props.as ?? 'div';
|
||||
return (
|
||||
<Wrapper
|
||||
{...props}
|
||||
dangerouslySetInnerHTML={{ __html: props.htmlString }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -8,7 +8,6 @@ import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
|
||||
import { toSupportedLocale } from './locale';
|
||||
import { determineEmojiMode } from './mode';
|
||||
import { emojifyElement } from './render';
|
||||
import type {
|
||||
CustomEmojiMapArg,
|
||||
EmojiAppState,
|
||||
@@ -39,6 +38,7 @@ export function useEmojify(text: string, extraEmojis?: CustomEmojiMapArg) {
|
||||
async (input: string) => {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.innerHTML = input;
|
||||
const { emojifyElement } = await import('./render');
|
||||
const result = await emojifyElement(wrapper, appState, extra);
|
||||
if (result) {
|
||||
setEmojifiedText(result.innerHTML);
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
EMOJI_TYPE_UNICODE,
|
||||
EMOJI_TYPE_CUSTOM,
|
||||
EMOJI_STATE_MISSING,
|
||||
ANY_EMOJI_REGEX,
|
||||
} from './constants';
|
||||
import {
|
||||
searchCustomEmojisByShortcodes,
|
||||
@@ -32,7 +31,12 @@ import type {
|
||||
LocaleOrCustom,
|
||||
UnicodeEmojiToken,
|
||||
} from './types';
|
||||
import { emojiLogger, stringHasAnyEmoji, stringHasUnicodeFlags } from './utils';
|
||||
import {
|
||||
anyEmojiRegex,
|
||||
emojiLogger,
|
||||
stringHasAnyEmoji,
|
||||
stringHasUnicodeFlags,
|
||||
} from './utils';
|
||||
|
||||
const log = emojiLogger('render');
|
||||
|
||||
@@ -207,7 +211,7 @@ export function tokenizeText(text: string): TokenizedText {
|
||||
|
||||
const tokens = [];
|
||||
let lastIndex = 0;
|
||||
for (const match of text.matchAll(ANY_EMOJI_REGEX)) {
|
||||
for (const match of text.matchAll(anyEmojiRegex())) {
|
||||
if (match.index > lastIndex) {
|
||||
tokens.push(text.slice(lastIndex, match.index));
|
||||
}
|
||||
|
||||
@@ -1,23 +1,32 @@
|
||||
import debug from 'debug';
|
||||
|
||||
import {
|
||||
CUSTOM_EMOJI_REGEX,
|
||||
UNICODE_EMOJI_REGEX,
|
||||
UNICODE_FLAG_EMOJI_REGEX,
|
||||
} from './constants';
|
||||
import { emojiRegexPolyfill } from '@/mastodon/polyfills';
|
||||
|
||||
export function emojiLogger(segment: string) {
|
||||
return debug(`emojis:${segment}`);
|
||||
}
|
||||
|
||||
export function stringHasUnicodeEmoji(input: string): boolean {
|
||||
return UNICODE_EMOJI_REGEX.test(input);
|
||||
return new RegExp(EMOJI_REGEX, supportedFlags()).test(input);
|
||||
}
|
||||
|
||||
export function stringHasUnicodeFlags(input: string): boolean {
|
||||
return UNICODE_FLAG_EMOJI_REGEX.test(input);
|
||||
if (supportsRegExpSets()) {
|
||||
return new RegExp(
|
||||
'\\p{RGI_Emoji_Flag_Sequence}|\\p{RGI_Emoji_Tag_Sequence}',
|
||||
'v',
|
||||
).test(input);
|
||||
}
|
||||
return new RegExp(
|
||||
// First range is regional indicator symbols,
|
||||
// Second is a black flag + 0-9|a-z tag chars + cancel tag.
|
||||
// See: https://en.wikipedia.org/wiki/Regional_indicator_symbol
|
||||
'(?:\uD83C[\uDDE6-\uDDFF]){2}|\uD83C\uDFF4(?:\uDB40[\uDC30-\uDC7A])+\uDB40\uDC7F',
|
||||
).test(input);
|
||||
}
|
||||
|
||||
// Constant as this is supported by all browsers.
|
||||
const CUSTOM_EMOJI_REGEX = /:([a-z0-9_]+):/i;
|
||||
export function stringHasCustomEmoji(input: string) {
|
||||
return CUSTOM_EMOJI_REGEX.test(input);
|
||||
}
|
||||
@@ -25,3 +34,23 @@ export function stringHasCustomEmoji(input: string) {
|
||||
export function stringHasAnyEmoji(input: string) {
|
||||
return stringHasUnicodeEmoji(input) || stringHasCustomEmoji(input);
|
||||
}
|
||||
|
||||
export function anyEmojiRegex() {
|
||||
return new RegExp(
|
||||
`${EMOJI_REGEX}|${CUSTOM_EMOJI_REGEX.source}`,
|
||||
supportedFlags('gi'),
|
||||
);
|
||||
}
|
||||
|
||||
function supportsRegExpSets() {
|
||||
return 'unicodeSets' in RegExp.prototype;
|
||||
}
|
||||
|
||||
function supportedFlags(flags = '') {
|
||||
if (supportsRegExpSets()) {
|
||||
return `${flags}v`;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
const EMOJI_REGEX = emojiRegexPolyfill?.source ?? '\\p{RGI_Emoji}';
|
||||
@@ -8,9 +8,9 @@ import { Link, withRouter } from 'react-router-dom';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
|
||||
import EditIcon from '@/material-icons/400-24px/edit.svg?react';
|
||||
import FlagIcon from '@/material-icons/400-24px/flag-fill.svg?react';
|
||||
import FormatQuoteIcon from '@/material-icons/400-24px/format_quote.svg?react';
|
||||
import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react';
|
||||
import InsertChartIcon from '@/material-icons/400-24px/insert_chart.svg?react';
|
||||
import PersonIcon from '@/material-icons/400-24px/person-fill.svg?react';
|
||||
@@ -42,6 +42,7 @@ const messages = defineMessages({
|
||||
adminReport: { id: 'notification.admin.report', defaultMessage: '{name} reported {target}' },
|
||||
relationshipsSevered: { id: 'notification.relationships_severance_event', defaultMessage: 'Lost connections with {name}' },
|
||||
moderationWarning: { id: 'notification.moderation_warning', defaultMessage: 'You have received a moderation warning' },
|
||||
quote: { id: 'notification.label.quote', defaultMessage: '{name} quoted your post'}
|
||||
});
|
||||
|
||||
const notificationForScreenReader = (intl, message, timestamp) => {
|
||||
@@ -251,6 +252,36 @@ class Notification extends ImmutablePureComponent {
|
||||
);
|
||||
}
|
||||
|
||||
renderQuote (notification, link) {
|
||||
const { intl, unread } = this.props;
|
||||
|
||||
return (
|
||||
<Hotkeys handlers={this.getHandlers()}>
|
||||
<div className={classNames('notification notification-quote focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.quote, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
|
||||
<div className='notification__message'>
|
||||
<Icon id='quote' icon={FormatQuoteIcon} />
|
||||
|
||||
<span title={notification.get('created_at')}>
|
||||
<FormattedMessage id='notification.label.quote' defaultMessage='{name} quoted your post' values={{ name: link }} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<StatusQuoteManager
|
||||
id={notification.get('status')}
|
||||
account={notification.get('account')}
|
||||
muted
|
||||
withDismiss
|
||||
hidden={this.props.hidden}
|
||||
getScrollPosition={this.props.getScrollPosition}
|
||||
updateScrollBottom={this.props.updateScrollBottom}
|
||||
cachedMediaWidth={this.props.cachedMediaWidth}
|
||||
cacheMediaWidth={this.props.cacheMediaWidth}
|
||||
/>
|
||||
</div>
|
||||
</Hotkeys>
|
||||
);
|
||||
}
|
||||
|
||||
renderStatus (notification, link) {
|
||||
const { intl, unread, status } = this.props;
|
||||
|
||||
@@ -467,6 +498,8 @@ class Notification extends ImmutablePureComponent {
|
||||
return this.renderFollowRequest(notification, account, link);
|
||||
case 'mention':
|
||||
return this.renderMention(notification);
|
||||
case 'quote':
|
||||
return this.renderQuote(notification);
|
||||
case 'favourite':
|
||||
return this.renderFavourite(notification, link);
|
||||
case 'reblog':
|
||||
|
||||
@@ -15,6 +15,7 @@ import { NotificationFollowRequest } from './notification_follow_request';
|
||||
import { NotificationMention } from './notification_mention';
|
||||
import { NotificationModerationWarning } from './notification_moderation_warning';
|
||||
import { NotificationPoll } from './notification_poll';
|
||||
import { NotificationQuote } from './notification_quote';
|
||||
import { NotificationReblog } from './notification_reblog';
|
||||
import { NotificationSeveredRelationships } from './notification_severed_relationships';
|
||||
import { NotificationStatus } from './notification_status';
|
||||
@@ -91,6 +92,11 @@ export const NotificationGroup: React.FC<{
|
||||
<NotificationMention unread={unread} notification={notificationGroup} />
|
||||
);
|
||||
break;
|
||||
case 'quote':
|
||||
content = (
|
||||
<NotificationQuote unread={unread} notification={notificationGroup} />
|
||||
);
|
||||
break;
|
||||
case 'follow':
|
||||
content = (
|
||||
<NotificationFollow unread={unread} notification={notificationGroup} />
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import FormatQuoteIcon from '@/material-icons/400-24px/format_quote.svg?react';
|
||||
import type { NotificationGroupQuote } from 'mastodon/models/notification_group';
|
||||
|
||||
import type { LabelRenderer } from './notification_group_with_status';
|
||||
import { NotificationWithStatus } from './notification_with_status';
|
||||
|
||||
const quoteLabelRenderer: LabelRenderer = (displayName) => (
|
||||
<FormattedMessage
|
||||
id='notification.label.quote'
|
||||
defaultMessage='{name} quoted your post'
|
||||
values={{ name: displayName }}
|
||||
/>
|
||||
);
|
||||
|
||||
export const NotificationQuote: React.FC<{
|
||||
notification: NotificationGroupQuote;
|
||||
unread: boolean;
|
||||
}> = ({ notification, unread }) => {
|
||||
return (
|
||||
<NotificationWithStatus
|
||||
type='quote'
|
||||
icon={FormatQuoteIcon}
|
||||
iconId='quote'
|
||||
accountIds={notification.sampleAccountIds}
|
||||
count={notification.notifications_count}
|
||||
statusId={notification.statusId}
|
||||
labelRenderer={quoteLabelRenderer}
|
||||
unread={unread}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -600,6 +600,7 @@
|
||||
"notification.label.mention": "Mention",
|
||||
"notification.label.private_mention": "Private mention",
|
||||
"notification.label.private_reply": "Private reply",
|
||||
"notification.label.quote": "{name} quoted your post",
|
||||
"notification.label.reply": "Reply",
|
||||
"notification.mention": "Mention",
|
||||
"notification.mentioned_you": "{name} mentioned you",
|
||||
|
||||
@@ -756,7 +756,7 @@
|
||||
"reply_indicator.cancel": "Peruuta",
|
||||
"reply_indicator.poll": "Äänestys",
|
||||
"report.block": "Estä",
|
||||
"report.block_explanation": "Et näe hänen julkaisujaan. Hän voi nähdä julkaisujasi eikä seurata sinua. Hän näkee, että olet estänyt hänet.",
|
||||
"report.block_explanation": "Et näe hänen julkaisujaan. Hän ei voi nähdä julkaisujasi eikä seurata sinua. Hän näkee, että olet estänyt hänet.",
|
||||
"report.categories.legal": "Lakiseikat",
|
||||
"report.categories.other": "Muu",
|
||||
"report.categories.spam": "Roskaposti",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"about.blocks": "Servī moderātī",
|
||||
"about.contact": "Ratio:",
|
||||
"about.default_locale": "Default",
|
||||
"about.disclaimer": "Mastodon est software līberum, apertum fontem, et nōtam commercium Mastodon gGmbH.",
|
||||
"about.domain_blocks.no_reason_available": "Ratio abdere est",
|
||||
"about.domain_blocks.preamble": "Mastodon genērāliter sinit tē contentum ex aliīs servientibus in fedīversō vidēre et cum usoribus ab iīs interāgere. Haē sunt exceptionēs quae in hōc particulārī servientē factae sunt.",
|
||||
@@ -8,6 +9,7 @@
|
||||
"about.domain_blocks.silenced.title": "Limitātus",
|
||||
"about.domain_blocks.suspended.explanation": "Nulla data ab hōc servientē processābuntur, servābuntur aut commūtābuntur, faciendumque omnem interactionem aut communicātiōnem cum usoribus ab hōc servientē impossibilem.",
|
||||
"about.domain_blocks.suspended.title": "suspensus",
|
||||
"about.language_label": "Linguae",
|
||||
"about.not_available": "Haec informātiō in hōc servientē nōn praebita est.",
|
||||
"about.powered_by": "Nuntii socīālēs decentralizātī ā {mastodon} sustentātī.",
|
||||
"about.rules": "Servo praecepta",
|
||||
@@ -41,7 +43,12 @@
|
||||
"account.followers": "Sectatores",
|
||||
"account.followers.empty": "Nemo hunc usorem adhuc sequitur.",
|
||||
"account.followers_counter": "{count, plural, one {{counter} sectator} other {{counter} sectatores}}",
|
||||
"account.followers_you_know_counter": "{counter} scis",
|
||||
"account.following": "Sequentia",
|
||||
"account.following_counter": "{count, plural, one {{counter} sectans} other {{counter} sectans}}",
|
||||
"account.follows.empty": "Hic usor adhuc neminem sequitur.",
|
||||
"account.follows_you": "Sequitur te",
|
||||
"account.go_to_profile": "Vade ad profile",
|
||||
"account.moved_to": "{name} significavit eum suam rationem novam nunc esse:",
|
||||
"account.muted": "Confutatus",
|
||||
"account.requested_follow": "{name} postulavit ut te sequeretur",
|
||||
|
||||
@@ -876,6 +876,9 @@
|
||||
"status.quote_error.filtered": "Lí所設定ê過濾器kā tse khàm起來",
|
||||
"status.quote_error.not_available": "鋪文bē當看",
|
||||
"status.quote_error.pending_approval": "鋪文當咧送",
|
||||
"status.quote_error.pending_approval_popout.body": "因為無kâng ê服侍器有無kâng ê協定,佇聯邦宇宙分享ê引文可能愛開時間來顯示。",
|
||||
"status.quote_error.pending_approval_popout.title": "Leh送引文?請sió等leh",
|
||||
"status.quote_post_author": "引用 @{name} ê PO文ah",
|
||||
"status.read_more": "讀詳細",
|
||||
"status.reblog": "轉送",
|
||||
"status.reblog_private": "照原PO ê通看見ê範圍轉送",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"about.blocks": "Serwery moderowane",
|
||||
"about.contact": "Kontakt:",
|
||||
"about.default_locale": "Domyślny",
|
||||
"about.disclaimer": "Mastodon jest darmowym, otwartym oprogramowaniem i znakiem towarowym Mastodon gGmbH.",
|
||||
"about.domain_blocks.no_reason_available": "Powód niedostępny",
|
||||
"about.domain_blocks.preamble": "Domyślnie Mastodon pozwala ci przeglądać i reagować na treści od innych użytkowników z jakiegokolwiek serwera w fediwersum. Poniżej znajduje się lista wyjątków, które zostały stworzone na tym konkretnym serwerze.",
|
||||
@@ -8,6 +9,7 @@
|
||||
"about.domain_blocks.silenced.title": "Ograniczone",
|
||||
"about.domain_blocks.suspended.explanation": "Żadne dane z tego serwera nie będą przetwarzane, przechowywane lub wymieniane, co uniemożliwia jakąkolwiek interakcję lub komunikację z użytkownikami z tego serwera.",
|
||||
"about.domain_blocks.suspended.title": "Zawieszono",
|
||||
"about.language_label": "Język",
|
||||
"about.not_available": "Ta informacja nie została udostępniona na tym serwerze.",
|
||||
"about.powered_by": "Zdecentralizowane media społecznościowe napędzane przez {mastodon}",
|
||||
"about.rules": "Regulamin serwera",
|
||||
@@ -19,13 +21,21 @@
|
||||
"account.block_domain": "Blokuj wszystko z {domain}",
|
||||
"account.block_short": "Zablokuj",
|
||||
"account.blocked": "Zablokowany(-a)",
|
||||
"account.blocking": "Blokowanie",
|
||||
"account.cancel_follow_request": "Nie obserwuj",
|
||||
"account.copy": "Skopiuj link do profilu",
|
||||
"account.direct": "Napisz bezpośrednio do @{name}",
|
||||
"account.disable_notifications": "Przestań powiadamiać mnie o wpisach @{name}",
|
||||
"account.domain_blocking": "Blokowanie domeny",
|
||||
"account.edit_profile": "Edytuj profil",
|
||||
"account.enable_notifications": "Powiadamiaj mnie o wpisach @{name}",
|
||||
"account.endorse": "Wyróżnij na profilu",
|
||||
"account.familiar_followers_many": "Obserwowane przez: {name1}, {name2} i {othersCount, plural, one {jeszcze jedną osobę, którą znasz} few {# inne osoby, które znasz} many {# innych osób, które znasz} other {# innych osób, które znasz}}",
|
||||
"account.familiar_followers_one": "Obserwowane przez {name1}",
|
||||
"account.familiar_followers_two": "Obserwowane przez {name1} i {name2}",
|
||||
"account.featured": "Wyróżnione",
|
||||
"account.featured.accounts": "Profile",
|
||||
"account.featured.hashtags": "Tagi",
|
||||
"account.featured_tags.last_status_at": "Ostatni post {date}",
|
||||
"account.featured_tags.last_status_never": "Brak postów",
|
||||
"account.follow": "Obserwuj",
|
||||
@@ -33,9 +43,11 @@
|
||||
"account.followers": "Obserwujący",
|
||||
"account.followers.empty": "Nikt jeszcze nie obserwuje tego użytkownika.",
|
||||
"account.followers_counter": "{count, plural, one {{counter} obserwujący} few {{counter} obserwujących} many {{counter} obserwujących} other {{counter} obserwujących}}",
|
||||
"account.followers_you_know_counter": "{counter} które znasz",
|
||||
"account.following": "Obserwowani",
|
||||
"account.following_counter": "{count, plural, one {{counter} obserwowany} few {{counter} obserwowanych} many {{counter} obserwowanych} other {{counter} obserwowanych}}",
|
||||
"account.follows.empty": "Ten użytkownik nie obserwuje jeszcze nikogo.",
|
||||
"account.follows_you": "Obserwuje cię",
|
||||
"account.go_to_profile": "Przejdź do profilu",
|
||||
"account.hide_reblogs": "Ukryj podbicia od @{name}",
|
||||
"account.in_memoriam": "Ku pamięci.",
|
||||
@@ -50,18 +62,23 @@
|
||||
"account.mute_notifications_short": "Wycisz powiadomienia",
|
||||
"account.mute_short": "Wycisz",
|
||||
"account.muted": "Wyciszony",
|
||||
"account.muting": "Wyciszenie",
|
||||
"account.mutual": "Obserwujecie siebie nazwajem",
|
||||
"account.no_bio": "Brak opisu.",
|
||||
"account.open_original_page": "Otwórz stronę oryginalną",
|
||||
"account.posts": "Wpisy",
|
||||
"account.posts_with_replies": "Wpisy i odpowiedzi",
|
||||
"account.remove_from_followers": "Usuń {name} z obserwujących",
|
||||
"account.report": "Zgłoś @{name}",
|
||||
"account.requested": "Oczekująca prośba, kliknij aby anulować",
|
||||
"account.requested_follow": "{name} chce cię zaobserwować",
|
||||
"account.requests_to_follow_you": "Prośby o obserwowanie",
|
||||
"account.share": "Udostępnij profil @{name}",
|
||||
"account.show_reblogs": "Pokazuj podbicia od @{name}",
|
||||
"account.statuses_counter": "{count, plural, one {{counter} wpis} few {{counter} wpisy} many {{counter} wpisów} other {{counter} wpisów}}",
|
||||
"account.unblock": "Odblokuj @{name}",
|
||||
"account.unblock_domain": "Odblokuj domenę {domain}",
|
||||
"account.unblock_domain_short": "Odblokuj",
|
||||
"account.unblock_short": "Odblokuj",
|
||||
"account.unendorse": "Nie wyświetlaj w profilu",
|
||||
"account.unfollow": "Nie obserwuj",
|
||||
@@ -202,6 +219,12 @@
|
||||
"confirmations.delete_list.confirm": "Usuń",
|
||||
"confirmations.delete_list.message": "Czy na pewno chcesz trwale usunąć tę listę?",
|
||||
"confirmations.delete_list.title": "Usunąć listę?",
|
||||
"confirmations.discard_draft.confirm": "Odrzuć i kontynuuj",
|
||||
"confirmations.discard_draft.edit.cancel": "Wznów edytowanie",
|
||||
"confirmations.discard_draft.edit.message": "Kontynuowanie spowoduje utratę wszystkich zmian wprowadzonych przez Ciebie w aktualnie edytowanym poście.",
|
||||
"confirmations.discard_draft.edit.title": "Odrzucić zmiany w poście?",
|
||||
"confirmations.discard_draft.post.cancel": "Wznów wersję roboczą",
|
||||
"confirmations.discard_draft.post.title": "Anulować wersję roboczą?",
|
||||
"confirmations.discard_edit_media.confirm": "Odrzuć",
|
||||
"confirmations.discard_edit_media.message": "Masz niezapisane zmiany w opisie lub podglądzie, odrzucić je mimo to?",
|
||||
"confirmations.follow_to_list.confirm": "Zaobserwuj i dodaj do listy",
|
||||
@@ -218,6 +241,9 @@
|
||||
"confirmations.redraft.confirm": "Usuń i popraw",
|
||||
"confirmations.redraft.message": "Czy na pewno chcesz usunąć i poprawić ten wpis? Polubienia, podbicia i komentarze pierwotnego wpisu zostaną utracone.",
|
||||
"confirmations.redraft.title": "Usunąć i poprawić wpis?",
|
||||
"confirmations.remove_from_followers.confirm": "Usuń obserwującego",
|
||||
"confirmations.remove_from_followers.message": "{name} przestanie Cię obserwować. Czy na pewno chcesz kontynuować?",
|
||||
"confirmations.remove_from_followers.title": "Usunąć obserwującego?",
|
||||
"confirmations.unfollow.confirm": "Nie obserwuj",
|
||||
"confirmations.unfollow.message": "Czy na pewno nie chcesz obserwować {name}?",
|
||||
"confirmations.unfollow.title": "Cofnąć obserwację?",
|
||||
@@ -307,9 +333,15 @@
|
||||
"errors.unexpected_crash.copy_stacktrace": "Skopiuj stacktrace do schowka",
|
||||
"errors.unexpected_crash.report_issue": "Zgłoś problem",
|
||||
"explore.suggested_follows": "Ludzie",
|
||||
"explore.title": "Na czasie",
|
||||
"explore.trending_links": "Aktualności",
|
||||
"explore.trending_statuses": "Wpisy",
|
||||
"explore.trending_tags": "Hasztagi",
|
||||
"featured_carousel.header": "{count, plural, one {Przypięty post} other {Przypięte posty}}",
|
||||
"featured_carousel.next": "Następny",
|
||||
"featured_carousel.post": "Opublikuj",
|
||||
"featured_carousel.previous": "Poprzedni",
|
||||
"featured_carousel.slide": "{index} z {total}",
|
||||
"filter_modal.added.context_mismatch_explanation": "To filtrowanie nie dotyczy kategorii, w której pojawił się ten wpis. Jeśli chcesz, aby wpis był filtrowany również w tym kontekście, musisz edytować ustawienia filtrowania.",
|
||||
"filter_modal.added.context_mismatch_title": "Niewłaściwy kontekst!",
|
||||
"filter_modal.added.expired_explanation": "Ta kategoria filtrowania wygasła, aby ją zastosować, należy zmienić datę wygaśnięcia.",
|
||||
@@ -362,6 +394,8 @@
|
||||
"generic.saved": "Zapisano",
|
||||
"getting_started.heading": "Pierwsze kroki",
|
||||
"hashtag.admin_moderation": "Otwórz interfejs moderacji #{name}",
|
||||
"hashtag.browse": "Przeglądaj posty z #{hashtag}",
|
||||
"hashtag.browse_from_account": "Przeglądaj posty od @{name} z #{hashtag}",
|
||||
"hashtag.column_header.tag_mode.all": "i {additional}",
|
||||
"hashtag.column_header.tag_mode.any": "lub {additional}",
|
||||
"hashtag.column_header.tag_mode.none": "bez {additional}",
|
||||
@@ -374,7 +408,10 @@
|
||||
"hashtag.counter_by_accounts": "{count, plural, one {{counter} osoba} few {{counter} osoby} many {{counter} osób} other {{counter} osób}}",
|
||||
"hashtag.counter_by_uses": "{count, plural, one {{counter} wpis} few {{counter} wpisy} many {{counter} wpisów} other {{counter} wpisów}}",
|
||||
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} wpis} few {{counter} wpisy} many {{counter} wpisów} other {{counter} wpisów}} dzisiaj",
|
||||
"hashtag.feature": "Wyróżnij w profilu",
|
||||
"hashtag.follow": "Obserwuj hasztag",
|
||||
"hashtag.mute": "Wycisz #{hashtag}",
|
||||
"hashtag.unfeature": "Nie wyróżniaj w profilu",
|
||||
"hashtag.unfollow": "Przestań obserwować hashtag",
|
||||
"hashtags.and_other": "…i {count, plural, other {jeszcze #}}",
|
||||
"hints.profiles.followers_may_be_missing": "Niektórzy obserwujący ten profil mogą być niewidoczni.",
|
||||
@@ -383,6 +420,7 @@
|
||||
"hints.profiles.see_more_followers": "Zobacz więcej obserwujących na {domain}",
|
||||
"hints.profiles.see_more_follows": "Zobacz więcej obserwowanych na {domain}",
|
||||
"hints.profiles.see_more_posts": "Zobacz więcej wpisów na {domain}",
|
||||
"home.column_settings.show_quotes": "Pokaż cytaty",
|
||||
"home.column_settings.show_reblogs": "Pokazuj podbicia",
|
||||
"home.column_settings.show_replies": "Pokazuj odpowiedzi",
|
||||
"home.hide_announcements": "Ukryj ogłoszenia",
|
||||
@@ -456,6 +494,8 @@
|
||||
"keyboard_shortcuts.translate": "aby przetłumaczyć wpis",
|
||||
"keyboard_shortcuts.unfocus": "Opuść pole tekstowe",
|
||||
"keyboard_shortcuts.up": "Przesuń w górę na liście",
|
||||
"learn_more_link.got_it": "Rozumiem",
|
||||
"learn_more_link.learn_more": "Dowiedz się więcej",
|
||||
"lightbox.close": "Zamknij",
|
||||
"lightbox.next": "Następne",
|
||||
"lightbox.previous": "Poprzednie",
|
||||
@@ -505,8 +545,10 @@
|
||||
"mute_modal.you_wont_see_mentions": "Nie zobaczysz wpisów wzmiankujących tę osobę.",
|
||||
"mute_modal.you_wont_see_posts": "Nie zobaczysz wpisów tej osoby, ale ona może widzieć twoje.",
|
||||
"navigation_bar.about": "O serwerze",
|
||||
"navigation_bar.account_settings": "Hasło i zabezpieczenia",
|
||||
"navigation_bar.administration": "Administracja",
|
||||
"navigation_bar.advanced_interface": "Otwórz w widoku zaawansowanym",
|
||||
"navigation_bar.automated_deletion": "Automatyczne usuwanie postów",
|
||||
"navigation_bar.blocks": "Zablokowani",
|
||||
"navigation_bar.bookmarks": "Zakładki",
|
||||
"navigation_bar.direct": "Wzmianki bezpośrednie",
|
||||
@@ -516,13 +558,21 @@
|
||||
"navigation_bar.follow_requests": "Prośby o obserwowanie",
|
||||
"navigation_bar.followed_tags": "Obserwowane hasztagi",
|
||||
"navigation_bar.follows_and_followers": "Obserwowani i obserwujący",
|
||||
"navigation_bar.import_export": "Import i eksport",
|
||||
"navigation_bar.lists": "Listy",
|
||||
"navigation_bar.logout": "Wyloguj",
|
||||
"navigation_bar.moderation": "Moderacja",
|
||||
"navigation_bar.more": "Więcej",
|
||||
"navigation_bar.mutes": "Wyciszeni",
|
||||
"navigation_bar.opened_in_classic_interface": "Wpisy, konta i inne określone strony są domyślnie otwierane w widoku klasycznym.",
|
||||
"navigation_bar.preferences": "Ustawienia",
|
||||
"navigation_bar.privacy_and_reach": "Prywatność i zasięg",
|
||||
"navigation_bar.search": "Szukaj",
|
||||
"navigation_bar.search_trends": "Szukaj / Na czasie",
|
||||
"navigation_panel.collapse_followed_tags": "Zwiń menu obserwowanych hashtagów",
|
||||
"navigation_panel.collapse_lists": "Zwiń menu listy",
|
||||
"navigation_panel.expand_followed_tags": "Rozwiń menu obserwowanych hashtagów",
|
||||
"navigation_panel.expand_lists": "Rozwiń menu listy",
|
||||
"not_signed_in_indicator.not_signed_in": "Zaloguj się, aby uzyskać dostęp.",
|
||||
"notification.admin.report": "{name} zgłosił {target}",
|
||||
"notification.admin.report_account": "{name} zgłosił(a) {count, plural, one {1 wpis} few {# wpisy} other {# wpisów}} z {target} w kategorii {category}",
|
||||
@@ -749,6 +799,7 @@
|
||||
"report_notification.categories.violation": "Naruszenie zasad",
|
||||
"report_notification.categories.violation_sentence": "naruszenie zasad",
|
||||
"report_notification.open": "Otwórz zgłoszenie",
|
||||
"search.clear": "Wyczyść wyszukiwanie",
|
||||
"search.no_recent_searches": "Brak ostatnich wyszukiwań",
|
||||
"search.placeholder": "Szukaj",
|
||||
"search.quick_action.account_search": "Profile pasujące do {x}",
|
||||
@@ -790,6 +841,8 @@
|
||||
"status.bookmark": "Dodaj zakładkę",
|
||||
"status.cancel_reblog_private": "Cofnij podbicie",
|
||||
"status.cannot_reblog": "Ten wpis nie może zostać podbity",
|
||||
"status.context.load_new_replies": "Dostępne są nowe odpowiedzi",
|
||||
"status.context.loading": "Sprawdzanie kolejnych odpowiedzi",
|
||||
"status.continued_thread": "Ciąg dalszy wątku",
|
||||
"status.copy": "Skopiuj odnośnik do wpisu",
|
||||
"status.delete": "Usuń",
|
||||
@@ -815,6 +868,10 @@
|
||||
"status.mute_conversation": "Wycisz konwersację",
|
||||
"status.open": "Rozszerz ten wpis",
|
||||
"status.pin": "Przypnij do profilu",
|
||||
"status.quote_error.filtered": "Ukryte z powodu jednego z Twoich filtrów",
|
||||
"status.quote_error.not_available": "Post niedostępny",
|
||||
"status.quote_error.pending_approval": "Post oczekujący",
|
||||
"status.quote_post_author": "Zacytowano post @{name}",
|
||||
"status.read_more": "Czytaj dalej",
|
||||
"status.reblog": "Podbij",
|
||||
"status.reblog_private": "Podbij dla odbiorców oryginalnego wpisu",
|
||||
@@ -844,8 +901,13 @@
|
||||
"subscribed_languages.save": "Zapisz zmiany",
|
||||
"subscribed_languages.target": "Zmień subskrybowane języki dla {target}",
|
||||
"tabs_bar.home": "Strona główna",
|
||||
"tabs_bar.menu": "Menu",
|
||||
"tabs_bar.notifications": "Powiadomienia",
|
||||
"tabs_bar.publish": "Nowy post",
|
||||
"tabs_bar.search": "Szukaj",
|
||||
"terms_of_service.effective_as_of": "Obowiązuje od {date}",
|
||||
"terms_of_service.title": "Warunki korzystania z usługi",
|
||||
"terms_of_service.upcoming_changes_on": "Nadchodzące zmiany od {date}",
|
||||
"time_remaining.days": "{number, plural, one {Pozostał # dzień} few {Pozostały # dni} many {Pozostało # dni} other {Pozostało # dni}}",
|
||||
"time_remaining.hours": "{number, plural, one {Pozostała # godzina} few {Pozostały # godziny} many {Pozostało # godzin} other {Pozostało # godzin}}",
|
||||
"time_remaining.minutes": "{number, plural, one {Pozostała # minuta} few {Pozostały # minuty} many {Pozostało # minut} other {Pozostało # minut}}",
|
||||
@@ -876,6 +938,12 @@
|
||||
"video.expand": "Rozszerz film",
|
||||
"video.fullscreen": "Pełny ekran",
|
||||
"video.hide": "Ukryj film",
|
||||
"video.mute": "Wycisz",
|
||||
"video.pause": "Pauzuj",
|
||||
"video.play": "Odtwórz"
|
||||
"video.play": "Odtwórz",
|
||||
"video.skip_backward": "Skocz do tyłu",
|
||||
"video.skip_forward": "Skocz do przodu",
|
||||
"video.unmute": "Wyłącz wyciszenie",
|
||||
"video.volume_down": "Zmniejsz głośność",
|
||||
"video.volume_up": "Zwiększ głośność"
|
||||
}
|
||||
@@ -498,6 +498,8 @@
|
||||
"keyboard_shortcuts.translate": "bir gönderiyi çevirmek için",
|
||||
"keyboard_shortcuts.unfocus": "Aramada bir gönderiye odaklanmamak için",
|
||||
"keyboard_shortcuts.up": "Listede yukarıya çıkmak için",
|
||||
"learn_more_link.got_it": "Anladım",
|
||||
"learn_more_link.learn_more": "Daha fazla bilgi edin",
|
||||
"lightbox.close": "Kapat",
|
||||
"lightbox.next": "Sonraki",
|
||||
"lightbox.previous": "Önceki",
|
||||
@@ -873,6 +875,11 @@
|
||||
"status.open": "Bu gönderiyi genişlet",
|
||||
"status.pin": "Profile sabitle",
|
||||
"status.quote_error.filtered": "Bazı filtrelerinizden dolayı gizlenmiştir",
|
||||
"status.quote_error.not_available": "Gönderi kullanılamıyor",
|
||||
"status.quote_error.pending_approval": "Gönderi beklemede",
|
||||
"status.quote_error.pending_approval_popout.body": "Fediverse genelinde paylaşılan alıntıların görüntülenmesi zaman alabilir, çünkü farklı sunucuların farklı protokolleri vardır.",
|
||||
"status.quote_error.pending_approval_popout.title": "Bekleyen bir teklif mi var? Sakin olun.",
|
||||
"status.quote_post_author": "@{name} adlı kullanıcının bir gönderisini alıntıladı",
|
||||
"status.read_more": "Devamını okuyun",
|
||||
"status.reblog": "Yeniden paylaş",
|
||||
"status.reblog_private": "Özgün görünürlük ile yeniden paylaş",
|
||||
|
||||
@@ -45,7 +45,7 @@ const AccountRoleFactory = ImmutableRecord<AccountRoleShape>({
|
||||
// Account
|
||||
export interface AccountShape
|
||||
extends Required<
|
||||
Omit<ApiAccountJSON, 'emojis' | 'fields' | 'roles' | 'moved'>
|
||||
Omit<ApiAccountJSON, 'emojis' | 'fields' | 'roles' | 'moved' | 'url'>
|
||||
> {
|
||||
emojis: ImmutableList<CustomEmoji>;
|
||||
fields: ImmutableList<AccountField>;
|
||||
@@ -55,6 +55,7 @@ export interface AccountShape
|
||||
note_plain: string | null;
|
||||
hidden: boolean;
|
||||
moved: string | null;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export type Account = RecordOf<AccountShape>;
|
||||
@@ -148,8 +149,8 @@ export function createAccountFromServerJSON(serverJSON: ApiAccountJSON) {
|
||||
note_emojified: emojify(accountNote, emojiMap),
|
||||
note_plain: unescapeHTML(accountNote),
|
||||
url:
|
||||
accountJSON.url.startsWith('http://') ||
|
||||
accountJSON.url.startsWith('https://')
|
||||
accountJSON.url?.startsWith('http://') ||
|
||||
accountJSON.url?.startsWith('https://')
|
||||
? accountJSON.url
|
||||
: accountJSON.uri,
|
||||
});
|
||||
|
||||
@@ -36,6 +36,7 @@ export type NotificationGroupFavourite =
|
||||
export type NotificationGroupReblog = BaseNotificationWithStatus<'reblog'>;
|
||||
export type NotificationGroupStatus = BaseNotificationWithStatus<'status'>;
|
||||
export type NotificationGroupMention = BaseNotificationWithStatus<'mention'>;
|
||||
export type NotificationGroupQuote = BaseNotificationWithStatus<'quote'>;
|
||||
export type NotificationGroupPoll = BaseNotificationWithStatus<'poll'>;
|
||||
export type NotificationGroupUpdate = BaseNotificationWithStatus<'update'>;
|
||||
export type NotificationGroupFollow = BaseNotification<'follow'>;
|
||||
@@ -87,6 +88,7 @@ export type NotificationGroup =
|
||||
| NotificationGroupReblog
|
||||
| NotificationGroupStatus
|
||||
| NotificationGroupMention
|
||||
| NotificationGroupQuote
|
||||
| NotificationGroupPoll
|
||||
| NotificationGroupUpdate
|
||||
| NotificationGroupFollow
|
||||
@@ -137,6 +139,7 @@ export function createNotificationGroupFromJSON(
|
||||
case 'reblog':
|
||||
case 'status':
|
||||
case 'mention':
|
||||
case 'quote':
|
||||
case 'poll':
|
||||
case 'update': {
|
||||
const { status_id: statusId, ...groupWithoutStatus } = group;
|
||||
@@ -209,6 +212,7 @@ export function createNotificationGroupFromNotificationJSON(
|
||||
case 'reblog':
|
||||
case 'status':
|
||||
case 'mention':
|
||||
case 'quote':
|
||||
case 'poll':
|
||||
case 'update':
|
||||
return {
|
||||
|
||||
@@ -20,5 +20,16 @@ export function loadPolyfills() {
|
||||
loadIntlPolyfills(),
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- those properties might not exist in old browsers, even if they are always here in types
|
||||
needsExtraPolyfills && importExtraPolyfills(),
|
||||
loadEmojiPolyfills(),
|
||||
]);
|
||||
}
|
||||
|
||||
// In the case of no /v support, rely on the emojibase data.
|
||||
async function loadEmojiPolyfills() {
|
||||
if (!('unicodeSets' in RegExp.prototype)) {
|
||||
emojiRegexPolyfill = (await import('emojibase-regex/emoji')).default;
|
||||
}
|
||||
}
|
||||
|
||||
// Null unless polyfill is needed.
|
||||
export let emojiRegexPolyfill: RegExp | null = null;
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m228-240 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T458-480L320-240h-92Zm360 0 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T818-480L680-240h-92Z"/></svg>
|
||||
|
After Width: | Height: | Size: 322 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m228-240 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T458-480L320-240h-92Zm360 0 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T818-480L680-240h-92ZM320-500q25 0 42.5-17.5T380-560q0-25-17.5-42.5T320-620q-25 0-42.5 17.5T260-560q0 25 17.5 42.5T320-500Zm360 0q25 0 42.5-17.5T740-560q0-25-17.5-42.5T680-620q-25 0-42.5 17.5T620-560q0 25 17.5 42.5T680-500Zm0-60Zm-360 0Z"/></svg>
|
||||
|
After Width: | Height: | Size: 538 B |
Reference in new issue
Block a user