Merge remote-tracking branch 'origin/develop' into chats
This commit is contained in:
commit
d5fc6fe252
37 changed files with 524 additions and 404 deletions
|
@ -1,8 +1,10 @@
|
|||
import type { ModalType } from 'soapbox/features/ui/components/modal_root';
|
||||
|
||||
export const MODAL_OPEN = 'MODAL_OPEN';
|
||||
export const MODAL_CLOSE = 'MODAL_CLOSE';
|
||||
|
||||
/** Open a modal of the given type */
|
||||
export function openModal(type: string, props?: any) {
|
||||
export function openModal(type: ModalType, props?: any) {
|
||||
return {
|
||||
type: MODAL_OPEN,
|
||||
modalType: type,
|
||||
|
@ -11,7 +13,7 @@ export function openModal(type: string, props?: any) {
|
|||
}
|
||||
|
||||
/** Close the modal */
|
||||
export function closeModal(type?: string) {
|
||||
export function closeModal(type?: ModalType) {
|
||||
return {
|
||||
type: MODAL_CLOSE,
|
||||
modalType: type,
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
import {
|
||||
Map as ImmutableMap,
|
||||
} from 'immutable';
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
import 'intl-pluralrules';
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
@ -150,13 +147,13 @@ const updateNotificationsQueue = (notification: APIEntity, intlMessages: Record<
|
|||
|
||||
const dequeueNotifications = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const queuedNotifications = getState().notifications.get('queuedNotifications');
|
||||
const totalQueuedNotificationsCount = getState().notifications.get('totalQueuedNotificationsCount');
|
||||
const queuedNotifications = getState().notifications.queuedNotifications;
|
||||
const totalQueuedNotificationsCount = getState().notifications.totalQueuedNotificationsCount;
|
||||
|
||||
if (totalQueuedNotificationsCount === 0) {
|
||||
return;
|
||||
} else if (totalQueuedNotificationsCount > 0 && totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) {
|
||||
queuedNotifications.forEach((block: APIEntity) => {
|
||||
queuedNotifications.forEach((block) => {
|
||||
dispatch(updateNotifications(block.notification));
|
||||
});
|
||||
} else {
|
||||
|
@ -185,7 +182,7 @@ const expandNotifications = ({ maxId }: Record<string, any> = {}, done: () => an
|
|||
const notifications = state.notifications;
|
||||
const isLoadingMore = !!maxId;
|
||||
|
||||
if (notifications.get('isLoading')) {
|
||||
if (notifications.isLoading) {
|
||||
done();
|
||||
return dispatch(noOp);
|
||||
}
|
||||
|
@ -208,7 +205,7 @@ const expandNotifications = ({ maxId }: Record<string, any> = {}, done: () => an
|
|||
}
|
||||
}
|
||||
|
||||
if (!maxId && notifications.get('items').size > 0) {
|
||||
if (!maxId && notifications.items.size > 0) {
|
||||
params.since_id = notifications.getIn(['items', 0, 'id']);
|
||||
}
|
||||
|
||||
|
@ -307,8 +304,8 @@ const markReadNotifications = () =>
|
|||
if (!isLoggedIn(getState)) return;
|
||||
|
||||
const state = getState();
|
||||
const topNotificationId: string | undefined = state.notifications.get('items').first(ImmutableMap()).get('id');
|
||||
const lastReadId: string | -1 = state.notifications.get('lastRead');
|
||||
const topNotificationId = state.notifications.items.first()?.id;
|
||||
const lastReadId = state.notifications.lastRead;
|
||||
const v = parseVersion(state.instance.version);
|
||||
|
||||
if (topNotificationId && (lastReadId === -1 || compareId(topNotificationId, lastReadId) > 0)) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Portal from '@reach/portal';
|
||||
import { Portal } from '@reach/portal';
|
||||
import classNames from 'clsx';
|
||||
import { List as ImmutableList } from 'immutable';
|
||||
import React from 'react';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Portal from '@reach/portal';
|
||||
import { Portal } from '@reach/portal';
|
||||
import classNames from 'clsx';
|
||||
import React from 'react';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
|
Binary file not shown.
64
app/soapbox/components/extended_video_player.tsx
Normal file
64
app/soapbox/components/extended_video_player.tsx
Normal file
|
@ -0,0 +1,64 @@
|
|||
import React, { useEffect, useRef } from 'react';
|
||||
|
||||
import { isIOS } from 'soapbox/is_mobile';
|
||||
|
||||
interface IExtendedVideoPlayer {
|
||||
src: string,
|
||||
alt?: string,
|
||||
width?: number,
|
||||
height?: number,
|
||||
time?: number,
|
||||
controls?: boolean,
|
||||
muted?: boolean,
|
||||
onClick?: () => void,
|
||||
}
|
||||
|
||||
const ExtendedVideoPlayer: React.FC<IExtendedVideoPlayer> = ({ src, alt, time, controls, muted, onClick }) => {
|
||||
const video = useRef<HTMLVideoElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleLoadedData = () => {
|
||||
if (time) {
|
||||
video.current!.currentTime = time;
|
||||
}
|
||||
};
|
||||
|
||||
video.current?.addEventListener('loadeddata', handleLoadedData);
|
||||
|
||||
return () => {
|
||||
video.current?.removeEventListener('loadeddata', handleLoadedData);
|
||||
};
|
||||
}, [video.current]);
|
||||
|
||||
const handleClick: React.MouseEventHandler<HTMLVideoElement> = e => {
|
||||
e.stopPropagation();
|
||||
const handler = onClick;
|
||||
if (handler) handler();
|
||||
};
|
||||
|
||||
const conditionalAttributes: React.VideoHTMLAttributes<HTMLVideoElement> = {};
|
||||
if (isIOS()) {
|
||||
conditionalAttributes.playsInline = true;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='extended-video-player'>
|
||||
<video
|
||||
ref={video}
|
||||
src={src}
|
||||
autoPlay
|
||||
role='button'
|
||||
tabIndex={0}
|
||||
aria-label={alt}
|
||||
title={alt}
|
||||
muted={muted}
|
||||
controls={controls}
|
||||
loop={!controls}
|
||||
onClick={handleClick}
|
||||
{...conditionalAttributes}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExtendedVideoPlayer;
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Sparklines, SparklinesCurve } from 'react-sparklines';
|
||||
|
||||
import { shortNumberFormat } from '../utils/numbers';
|
||||
|
||||
import Permalink from './permalink';
|
||||
import { HStack, Stack, Text } from './ui';
|
||||
|
||||
import type { Tag } from 'soapbox/types/entities';
|
||||
|
@ -19,9 +19,9 @@ const Hashtag: React.FC<IHashtag> = ({ hashtag }) => {
|
|||
return (
|
||||
<HStack alignItems='center' justifyContent='between' data-testid='hashtag'>
|
||||
<Stack>
|
||||
<Permalink href={hashtag.url} to={`/tags/${hashtag.name}`} className='hover:underline'>
|
||||
<Link to={`/tags/${hashtag.name}`} className='hover:underline'>
|
||||
<Text tag='span' size='sm' weight='semibold'>#{hashtag.name}</Text>
|
||||
</Permalink>
|
||||
</Link>
|
||||
|
||||
{hashtag.history && (
|
||||
<Text theme='muted' size='sm'>
|
||||
|
|
|
@ -526,7 +526,6 @@ const MediaGallery: React.FC<IMediaGallery> = (props) => {
|
|||
/>
|
||||
));
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (node.current) {
|
||||
const { offsetWidth } = node.current;
|
||||
|
|
|
@ -11,6 +11,7 @@ import { queryClient } from 'soapbox/queries/client';
|
|||
import { IPolicy, PolicyKeys } from 'soapbox/queries/policies';
|
||||
|
||||
import type { UnregisterCallback } from 'history';
|
||||
import type { ModalType } from 'soapbox/features/ui/components/modal_root';
|
||||
import type { ReducerCompose } from 'soapbox/reducers/compose';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -28,8 +29,8 @@ export const checkComposeContent = (compose?: ReturnType<typeof ReducerCompose>)
|
|||
|
||||
interface IModalRoot {
|
||||
onCancel?: () => void,
|
||||
onClose: (type?: string) => void,
|
||||
type: string,
|
||||
onClose: (type?: ModalType) => void,
|
||||
type: ModalType,
|
||||
}
|
||||
|
||||
const ModalRoot: React.FC<IModalRoot> = ({ children, onCancel, onClose, type }) => {
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
import * as React from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
interface IPermaLink extends Pick<React.HTMLAttributes<HTMLAnchorElement>, 'dangerouslySetInnerHTML'> {
|
||||
className?: string,
|
||||
href: string,
|
||||
title?: string,
|
||||
to: string,
|
||||
}
|
||||
|
||||
const Permalink: React.FC<IPermaLink> = (props) => {
|
||||
const history = useHistory();
|
||||
|
||||
const { className, href, title, to, children, ...filteredProps } = props;
|
||||
|
||||
const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
if (event.button === 0 && !(event.ctrlKey || event.metaKey)) {
|
||||
event.preventDefault();
|
||||
history.push(to);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<a
|
||||
target='_blank'
|
||||
href={href}
|
||||
onClick={handleClick}
|
||||
title={title}
|
||||
className={`permalink${className ? ' ' + className : ''}`}
|
||||
{...filteredProps}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
export default Permalink;
|
|
@ -30,7 +30,7 @@ const SidebarNavigation = () => {
|
|||
const instance = useAppSelector((state) => state.instance);
|
||||
const settings = useAppSelector((state) => getSettings(state));
|
||||
const account = useOwnAccount();
|
||||
const notificationCount = useAppSelector((state) => state.notifications.get('unread'));
|
||||
const notificationCount = useAppSelector((state) => state.notifications.unread);
|
||||
const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count());
|
||||
const dashboardCount = useAppSelector((state) => state.admin.openReports.count() + state.admin.awaitingApproval.count());
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Portal from '@reach/portal';
|
||||
import { Portal } from '@reach/portal';
|
||||
import { TooltipPopup, useTooltip } from '@reach/tooltip';
|
||||
import React from 'react';
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, { useCallback } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import Avatar from 'soapbox/components/avatar';
|
||||
import DisplayName from 'soapbox/components/display-name';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import Permalink from 'soapbox/components/permalink';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
import { makeGetAccount } from 'soapbox/selectors';
|
||||
|
||||
|
@ -38,13 +38,13 @@ const Account: React.FC<IAccount> = ({ accountId }) => {
|
|||
return (
|
||||
<div className='account'>
|
||||
<div className='account__wrapper'>
|
||||
<Permalink className='account__display-name' title={account.acct} href={`/@${account.acct}`} to={`/@${account.acct}`}>
|
||||
<Link className='account__display-name' title={account.get('acct')} to={`/@${account.get('acct')}`}>
|
||||
<div className='account__display-name'>
|
||||
<div className='account__avatar-wrapper'><Avatar account={account} size={36} /></div>
|
||||
<DisplayName account={account} />
|
||||
|
||||
</div>
|
||||
</Permalink>
|
||||
</Link>
|
||||
<div
|
||||
className='flex items-center gap-0.5'
|
||||
title={intl.formatMessage(messages.birthday, {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import classNames from 'clsx';
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { getSettings } from 'soapbox/actions/settings';
|
||||
import Avatar from 'soapbox/components/avatar';
|
||||
import DisplayName from 'soapbox/components/display-name';
|
||||
import Permalink from 'soapbox/components/permalink';
|
||||
import RelativeTimestamp from 'soapbox/components/relative-timestamp';
|
||||
import { Text } from 'soapbox/components/ui';
|
||||
import ActionButton from 'soapbox/features/ui/components/action-button';
|
||||
|
@ -44,10 +44,10 @@ const AccountCard: React.FC<IAccountCard> = ({ id }) => {
|
|||
</div>
|
||||
|
||||
<div className='directory__card__bar'>
|
||||
<Permalink className='directory__card__bar__name' href={account.url} to={`/@${account.acct}`}>
|
||||
<Link className='directory__card__bar__name' to={`/@${account.acct}`}>
|
||||
<Avatar account={account} size={48} />
|
||||
<DisplayName account={account} />
|
||||
</Permalink>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className='directory__card__extra'>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { useCallback } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { authorizeFollowRequest, rejectFollowRequest } from 'soapbox/actions/accounts';
|
||||
import Avatar from 'soapbox/components/avatar';
|
||||
import DisplayName from 'soapbox/components/display-name';
|
||||
import IconButton from 'soapbox/components/icon_button';
|
||||
import Permalink from 'soapbox/components/permalink';
|
||||
import { Text } from 'soapbox/components/ui';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
import { makeGetAccount } from 'soapbox/selectors';
|
||||
|
@ -43,10 +43,10 @@ const AccountAuthorize: React.FC<IAccountAuthorize> = ({ id }) => {
|
|||
return (
|
||||
<div className='account-authorize__wrapper'>
|
||||
<div className='account-authorize'>
|
||||
<Permalink href={`/@${account.acct}`} to={`/@${account.acct}`}>
|
||||
<Link to={`/@${account.acct}`}>
|
||||
<div className='account-authorize__avatar'><Avatar account={account} size={48} /></div>
|
||||
<DisplayName account={account} />
|
||||
</Permalink>
|
||||
</Link>
|
||||
|
||||
<Text className='account__header__content' dangerouslySetInnerHTML={content} />
|
||||
</div>
|
||||
|
|
|
@ -13,7 +13,7 @@ const normalize = (notification: any) => {
|
|||
|
||||
return {
|
||||
// @ts-ignore
|
||||
notification: state.notifications.items.get(notification.id),
|
||||
notification: state.notifications.items.get(notification.id)!,
|
||||
state,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useCallback } from 'react';
|
||||
import { HotKeys } from 'react-hotkeys';
|
||||
import { defineMessages, useIntl, FormattedMessage, IntlShape, MessageDescriptor } from 'react-intl';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { defineMessages, useIntl, FormattedMessage, IntlShape, MessageDescriptor, defineMessage } from 'react-intl';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
|
||||
import { mentionCompose } from 'soapbox/actions/compose';
|
||||
import { reblog, favourite, unreblog, unfavourite } from 'soapbox/actions/interactions';
|
||||
|
@ -9,7 +9,6 @@ import { openModal } from 'soapbox/actions/modals';
|
|||
import { getSettings } from 'soapbox/actions/settings';
|
||||
import { hideStatus, revealStatus } from 'soapbox/actions/statuses';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import Permalink from 'soapbox/components/permalink';
|
||||
import { HStack, Text, Emoji } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import StatusContainer from 'soapbox/containers/status_container';
|
||||
|
@ -30,9 +29,8 @@ const notificationForScreenReader = (intl: IntlShape, message: string, timestamp
|
|||
|
||||
const buildLink = (account: Account): JSX.Element => (
|
||||
<bdi>
|
||||
<Permalink
|
||||
<Link
|
||||
className='text-gray-800 dark:text-gray-200 font-bold hover:underline'
|
||||
href={`/@${account.acct}`}
|
||||
title={account.acct}
|
||||
to={`/@${account.acct}`}
|
||||
dangerouslySetInnerHTML={{ __html: account.display_name_html }}
|
||||
|
@ -55,6 +53,11 @@ const icons: Record<NotificationType, string> = {
|
|||
update: require('@tabler/icons/pencil.svg'),
|
||||
};
|
||||
|
||||
const nameMessage = defineMessage({
|
||||
id: 'notification.name',
|
||||
defaultMessage: '{link}{others}',
|
||||
});
|
||||
|
||||
const messages: Record<NotificationType, MessageDescriptor> = defineMessages({
|
||||
follow: {
|
||||
id: 'notification.follow',
|
||||
|
@ -115,10 +118,7 @@ const buildMessage = (
|
|||
instanceTitle: string,
|
||||
): React.ReactNode => {
|
||||
const link = buildLink(account);
|
||||
const name = intl.formatMessage({
|
||||
id: 'notification.name',
|
||||
defaultMessage: '{link}{others}',
|
||||
}, {
|
||||
const name = intl.formatMessage(nameMessage, {
|
||||
link,
|
||||
others: totalCount && totalCount > 0 ? (
|
||||
<FormattedMessage
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,93 @@
|
|||
import { List as ImmutableList, Record as ImmutableRecord } from 'immutable';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import type { Attachment as AttachmentEntity } from 'soapbox/types/entities';
|
||||
|
||||
interface IPlaceholderMediaGallery {
|
||||
media: ImmutableList<AttachmentEntity>;
|
||||
defaultWidth?: number;
|
||||
}
|
||||
|
||||
const SizeData = ImmutableRecord({
|
||||
style: {} as React.CSSProperties,
|
||||
itemsDimensions: [] as Record<string, string>[],
|
||||
size: 1 as number,
|
||||
width: 0 as number,
|
||||
});
|
||||
|
||||
const PlaceholderMediaGallery: React.FC<IPlaceholderMediaGallery> = ({ media, defaultWidth }) => {
|
||||
const [width, setWidth] = useState(defaultWidth);
|
||||
|
||||
const handleRef = (node: HTMLDivElement) => {
|
||||
if (node) {
|
||||
setWidth(node.offsetWidth);
|
||||
}
|
||||
};
|
||||
|
||||
const getSizeData = (size: number) => {
|
||||
const style: React.CSSProperties = {};
|
||||
let itemsDimensions: Record<string, string>[] = [];
|
||||
|
||||
if (size === 1) {
|
||||
style.height = width! * 9 / 16;
|
||||
|
||||
itemsDimensions = [
|
||||
{ w: '100%', h: '100%' },
|
||||
];
|
||||
} else if (size === 2) {
|
||||
style.height = width! / 2;
|
||||
|
||||
itemsDimensions = [
|
||||
{ w: '50%', h: '100%', r: '2px' },
|
||||
{ w: '50%', h: '100%', l: '2px' },
|
||||
];
|
||||
} else if (size === 3) {
|
||||
style.height = width;
|
||||
|
||||
itemsDimensions = [
|
||||
{ w: '50%', h: '50%', b: '2px', r: '2px' },
|
||||
{ w: '50%', h: '50%', b: '2px', l: '2px' },
|
||||
{ w: '100%', h: '50%', t: '2px' },
|
||||
];
|
||||
} else if (size >= 4) {
|
||||
style.height = width;
|
||||
|
||||
itemsDimensions = [
|
||||
{ w: '50%', h: '50%', b: '2px', r: '2px' },
|
||||
{ w: '50%', h: '50%', b: '2px', l: '2px' },
|
||||
{ w: '50%', h: '50%', t: '2px', r: '2px' },
|
||||
{ w: '50%', h: '50%', t: '2px', l: '2px' },
|
||||
];
|
||||
}
|
||||
|
||||
return SizeData({
|
||||
style,
|
||||
itemsDimensions,
|
||||
size,
|
||||
width,
|
||||
});
|
||||
};
|
||||
|
||||
const renderItem = (dimensions: Record<string, string>, i: number) => {
|
||||
const width = dimensions.w;
|
||||
const height = dimensions.h;
|
||||
const top = dimensions.t || 'auto';
|
||||
const right = dimensions.r || 'auto';
|
||||
const bottom = dimensions.b || 'auto';
|
||||
const left = dimensions.l || 'auto';
|
||||
const float = dimensions.float as any || 'left';
|
||||
const position = dimensions.pos as any || 'relative';
|
||||
|
||||
return <div key={i} className='media-gallery__item' style={{ position, float, left, top, right, bottom, height, width }} />;
|
||||
};
|
||||
|
||||
const sizeData = getSizeData(media.size);
|
||||
|
||||
return (
|
||||
<div className='media-gallery media-gallery--placeholder' style={sizeData.get('style')} ref={handleRef}>
|
||||
{media.take(4).map((_, i) => renderItem(sizeData.get('itemsDimensions')[i], i))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PlaceholderMediaGallery;
|
Binary file not shown.
Binary file not shown.
|
@ -3,10 +3,10 @@ import React from 'react';
|
|||
const emptyComponent = () => null;
|
||||
const noop = () => { };
|
||||
|
||||
interface BundleProps {
|
||||
export interface BundleProps {
|
||||
fetchComponent: () => Promise<any>,
|
||||
loading: React.ComponentType,
|
||||
error: React.ComponentType<{ onRetry: (props: BundleProps) => void }>,
|
||||
error: React.ComponentType<{ onRetry: (props?: BundleProps) => void }>,
|
||||
children: (mod: any) => React.ReactNode,
|
||||
renderDelay?: number,
|
||||
onFetch: () => void,
|
||||
|
@ -57,7 +57,7 @@ class Bundle extends React.PureComponent<BundleProps, BundleState> {
|
|||
}
|
||||
}
|
||||
|
||||
load = (props: BundleProps) => {
|
||||
load = (props?: BundleProps) => {
|
||||
const { fetchComponent, onFetch, onFetchSuccess, onFetchFail, renderDelay } = props || this.props;
|
||||
const cachedMod = Bundle.cache.get(fetchComponent);
|
||||
|
||||
|
|
|
@ -225,7 +225,6 @@ const MediaModal: React.FC<IMediaModal> = (props) => {
|
|||
muted
|
||||
controls={false}
|
||||
width={width}
|
||||
link={link}
|
||||
height={height}
|
||||
key={attachment.preview_url}
|
||||
alt={attachment.description}
|
||||
|
|
Binary file not shown.
|
@ -1,5 +1,5 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
import OtpInput from 'react-otp-input';
|
||||
|
||||
import { verifyCredentials } from 'soapbox/actions/auth';
|
||||
|
@ -10,6 +10,37 @@ import { FormGroup, PhoneInput, Modal, Stack, Text } from 'soapbox/components/ui
|
|||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
import { getAccessToken } from 'soapbox/utils/auth';
|
||||
|
||||
const messages = defineMessages({
|
||||
verificationInvalid: {
|
||||
id: 'sms_verification.invalid',
|
||||
defaultMessage: 'Please enter a valid phone number.',
|
||||
},
|
||||
verificationSuccess: {
|
||||
id: 'sms_verification.success',
|
||||
defaultMessage: 'A verification code has been sent to your phone number.',
|
||||
},
|
||||
verificationFail: {
|
||||
id: 'sms_verification.fail',
|
||||
defaultMessage: 'Failed to send SMS message to your phone number.',
|
||||
},
|
||||
verificationExpired: {
|
||||
id: 'sms_verification.expired',
|
||||
defaultMessage: 'Your SMS token has expired.',
|
||||
},
|
||||
verifySms: {
|
||||
id: 'sms_verification.modal.verify_sms',
|
||||
defaultMessage: 'Verify SMS',
|
||||
},
|
||||
verifyNumber: {
|
||||
id: 'sms_verification.modal.verify_number',
|
||||
defaultMessage: 'Verify phone number',
|
||||
},
|
||||
verifyCode: {
|
||||
id: 'sms_verification.modal.verify_code',
|
||||
defaultMessage: 'Verify code',
|
||||
},
|
||||
});
|
||||
|
||||
interface IVerifySmsModal {
|
||||
onClose: (type: string) => void,
|
||||
}
|
||||
|
@ -47,10 +78,7 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
|||
setStatus(Statuses.IDLE);
|
||||
dispatch(
|
||||
snackbar.error(
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.invalid',
|
||||
defaultMessage: 'Please enter a valid phone number.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationInvalid),
|
||||
),
|
||||
);
|
||||
return;
|
||||
|
@ -59,10 +87,7 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
|||
dispatch(reRequestPhoneVerification(phone!)).then(() => {
|
||||
dispatch(
|
||||
snackbar.success(
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.success',
|
||||
defaultMessage: 'A verification code has been sent to your phone number.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationSuccess),
|
||||
),
|
||||
);
|
||||
})
|
||||
|
@ -70,10 +95,7 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
|||
.catch(() => {
|
||||
dispatch(
|
||||
snackbar.error(
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.fail',
|
||||
defaultMessage: 'Failed to send SMS message to your phone number.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationFail),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
@ -102,20 +124,11 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
|||
const confirmationText = useMemo(() => {
|
||||
switch (status) {
|
||||
case Statuses.IDLE:
|
||||
return intl.formatMessage({
|
||||
id: 'sms_verification.modal.verify_sms',
|
||||
defaultMessage: 'Verify SMS',
|
||||
});
|
||||
return intl.formatMessage(messages.verifySms);
|
||||
case Statuses.READY:
|
||||
return intl.formatMessage({
|
||||
id: 'sms_verification.modal.verify_number',
|
||||
defaultMessage: 'Verify phone number',
|
||||
});
|
||||
return intl.formatMessage(messages.verifyNumber);
|
||||
case Statuses.REQUESTED:
|
||||
return intl.formatMessage({
|
||||
id: 'sms_verification.modal.verify_code',
|
||||
defaultMessage: 'Verify code',
|
||||
});
|
||||
return intl.formatMessage(messages.verifyCode);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -126,12 +139,13 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
|||
case Statuses.IDLE:
|
||||
return (
|
||||
<Text theme='muted'>
|
||||
{intl.formatMessage({
|
||||
id: 'sms_verification.modal.verify_help_text',
|
||||
defaultMessage: 'Verify your phone number to start using {instance}.',
|
||||
}, {
|
||||
instance: title,
|
||||
})}
|
||||
<FormattedMessage
|
||||
id='sms_verification.modal.verify_help_text'
|
||||
defaultMessage='Verify your phone number to start using {instance}.'
|
||||
values={{
|
||||
instance: title,
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
);
|
||||
case Statuses.READY:
|
||||
|
@ -149,10 +163,10 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
|||
return (
|
||||
<>
|
||||
<Text theme='muted' size='sm' align='center'>
|
||||
{intl.formatMessage({
|
||||
id: 'sms_verification.modal.enter_code',
|
||||
defaultMessage: 'We sent you a 6-digit code via SMS. Enter it below.',
|
||||
})}
|
||||
<FormattedMessage
|
||||
id='sms_verification.modal.enter_code'
|
||||
defaultMessage='We sent you a 6-digit code via SMS. Enter it below.'
|
||||
/>
|
||||
</Text>
|
||||
|
||||
<OtpInput
|
||||
|
@ -184,10 +198,7 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
|||
})
|
||||
.catch(() => dispatch(
|
||||
snackbar.error(
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.invalid',
|
||||
defaultMessage: 'Your SMS token has expired.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationExpired),
|
||||
),
|
||||
));
|
||||
};
|
||||
|
@ -201,10 +212,10 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
|||
return (
|
||||
<Modal
|
||||
title={
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.modal.verify_title',
|
||||
defaultMessage: 'Verify your phone number',
|
||||
})
|
||||
<FormattedMessage
|
||||
id='sms_verification.modal.verify_title'
|
||||
defaultMessage='Verify your phone number'
|
||||
/>
|
||||
}
|
||||
onClose={() => onClose('VERIFY_SMS')}
|
||||
cancelAction={status === Statuses.IDLE ? () => onClose('VERIFY_SMS') : undefined}
|
||||
|
@ -212,10 +223,12 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
|||
confirmationAction={onConfirmationClick}
|
||||
confirmationText={confirmationText}
|
||||
secondaryAction={status === Statuses.REQUESTED ? resendVerificationCode : undefined}
|
||||
secondaryText={status === Statuses.REQUESTED ? intl.formatMessage({
|
||||
id: 'sms_verification.modal.resend_code',
|
||||
defaultMessage: 'Resend verification code?',
|
||||
}) : undefined}
|
||||
secondaryText={status === Statuses.REQUESTED ? (
|
||||
<FormattedMessage
|
||||
id='sms_verification.modal.resend_code'
|
||||
defaultMessage='Resend verification code?'
|
||||
/>
|
||||
) : undefined}
|
||||
secondaryDisabled={requestedAnother}
|
||||
>
|
||||
<Stack space={4}>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { connect } from 'react-redux';
|
||||
|
||||
import { fetchBundleRequest, fetchBundleSuccess, fetchBundleFail } from '../../../actions/bundles';
|
||||
import { fetchBundleRequest, fetchBundleSuccess, fetchBundleFail } from 'soapbox/actions/bundles';
|
||||
|
||||
import Bundle from '../components/bundle';
|
||||
|
||||
import type { AppDispatch } from 'soapbox/store';
|
||||
|
|
Binary file not shown.
|
@ -28,6 +28,11 @@ const messages = defineMessages({
|
|||
tokenNotFoundBody: { id: 'email_passthru.token_not_found.body', defaultMessage: 'Your email token was not found. Please request a new email confirmation from the {bold} from which you sent this email confirmation.' },
|
||||
tokenExpiredHeading: { id: 'email_passthru.token_expired.heading', defaultMessage: 'Token Expired' },
|
||||
tokenExpiredBody: { id: 'email_passthru.token_expired.body', defaultMessage: 'Your email token has expired. Please request a new email confirmation from the {bold} from which you sent this email confirmation.' },
|
||||
emailConfirmed: { id: 'email_passthru.success', defaultMessage: 'Your email has been verified!' },
|
||||
genericFail: { id: 'email_passthru.fail.generic', defaultMessage: 'Unable to confirm your email' },
|
||||
tokenExpired: { id: 'email_passthru.fail.expired', defaultMessage: 'Your email token has expired' },
|
||||
tokenNotFound: { id: 'email_passthru.fail.not_found', defaultMessage: 'Your email token is invalid.' },
|
||||
invalidToken: { id: 'email_passthru.fail.invalid_token', defaultMessage: 'Your token is invalid' },
|
||||
});
|
||||
|
||||
const Success = () => {
|
||||
|
@ -116,30 +121,21 @@ const EmailPassThru = () => {
|
|||
dispatch(confirmEmailVerification(token))
|
||||
.then(() => {
|
||||
setStatus(Statuses.SUCCESS);
|
||||
dispatch(snackbar.success(intl.formatMessage({ id: 'email_passthru.success', defaultMessage: 'Your email has been verified!' })));
|
||||
dispatch(snackbar.success(intl.formatMessage(messages.emailConfirmed)));
|
||||
})
|
||||
.catch((error: AxiosError<any>) => {
|
||||
const errorKey = error?.response?.data?.error;
|
||||
let message = intl.formatMessage({
|
||||
id: 'email_passthru.fail.generic',
|
||||
defaultMessage: 'Unable to confirm your email',
|
||||
});
|
||||
let message = intl.formatMessage(messages.genericFail);
|
||||
|
||||
if (errorKey) {
|
||||
switch (errorKey) {
|
||||
case 'token_expired':
|
||||
message = intl.formatMessage({
|
||||
id: 'email_passthru.fail.expired',
|
||||
defaultMessage: 'Your email token has expired.',
|
||||
});
|
||||
message = intl.formatMessage(messages.tokenExpired);
|
||||
setStatus(Statuses.TOKEN_EXPIRED);
|
||||
break;
|
||||
case 'token_not_found':
|
||||
message = intl.formatMessage({
|
||||
id: 'email_passthru.fail.not_found',
|
||||
defaultMessage: 'Your email token is invalid.',
|
||||
});
|
||||
message = 'Your token is invalid';
|
||||
message = intl.formatMessage(messages.tokenNotFound);
|
||||
message = intl.formatMessage(messages.invalidToken);
|
||||
setStatus(Statuses.TOKEN_NOT_FOUND);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { AxiosError } from 'axios';
|
||||
import React from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import snackbar from 'soapbox/actions/snackbar';
|
||||
import { checkEmailVerification, postEmailVerification, requestEmailVerification } from 'soapbox/actions/verification';
|
||||
|
@ -8,6 +8,13 @@ import Icon from 'soapbox/components/icon';
|
|||
import { Button, Form, FormGroup, Input, Text } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
const messages = defineMessages({
|
||||
verificationSuccess: { id: 'email_verification.success', defaultMessage: 'Verification email sent successfully.' },
|
||||
verificationFail: { id: 'email_verification.fail', defaultMessage: 'Failed to request email verification.' },
|
||||
verificationFailTakenAlert: { id: 'emai_verifilcation.exists', defaultMessage: 'This email has already been taken.' },
|
||||
verificationFailTaken: { id: 'email_verification.taken', defaultMessage: 'is taken' },
|
||||
});
|
||||
|
||||
const Statuses = {
|
||||
IDLE: 'IDLE',
|
||||
REQUESTED: 'REQUESTED',
|
||||
|
@ -77,26 +84,23 @@ const EmailVerification = () => {
|
|||
|
||||
dispatch(
|
||||
snackbar.success(
|
||||
intl.formatMessage({
|
||||
id: 'email_verification.exists',
|
||||
defaultMessage: 'Verification email sent successfully.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationSuccess),
|
||||
),
|
||||
);
|
||||
})
|
||||
.catch((error: AxiosError) => {
|
||||
const errorMessage = (error.response?.data as any)?.error;
|
||||
const isEmailTaken = errorMessage === 'email_taken';
|
||||
let message = intl.formatMessage({ id: 'email_verification.fail', defaultMessage: 'Failed to request email verification.' });
|
||||
let message = intl.formatMessage(messages.verificationFail);
|
||||
|
||||
if (isEmailTaken) {
|
||||
message = intl.formatMessage({ id: 'email_verification.exists', defaultMessage: 'This email has already been taken.' });
|
||||
message = intl.formatMessage(messages.verificationFailTakenAlert);
|
||||
} else if (errorMessage) {
|
||||
message = errorMessage;
|
||||
}
|
||||
|
||||
if (isEmailTaken) {
|
||||
setErrors([intl.formatMessage({ id: 'email_verification.taken', defaultMessage: 'is taken' })]);
|
||||
setErrors([intl.formatMessage(messages.verificationFailTaken)]);
|
||||
}
|
||||
|
||||
dispatch(snackbar.error(message));
|
||||
|
@ -111,7 +115,9 @@ const EmailVerification = () => {
|
|||
return (
|
||||
<div>
|
||||
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-800 border-solid -mx-4 sm:-mx-10'>
|
||||
<h1 className='text-center font-bold text-2xl'>{intl.formatMessage({ id: 'email_verification.header', defaultMessage: 'Enter your email address' })}</h1>
|
||||
<h1 className='text-center font-bold text-2xl'>
|
||||
<FormattedMessage id='email_verification.header' defaultMessage='Enter your email address' />
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { AxiosError } from 'axios';
|
||||
import React from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
import OtpInput from 'react-otp-input';
|
||||
|
||||
import snackbar from 'soapbox/actions/snackbar';
|
||||
|
@ -8,6 +8,13 @@ import { confirmPhoneVerification, requestPhoneVerification } from 'soapbox/acti
|
|||
import { Button, Form, FormGroup, PhoneInput, Text } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
const messages = defineMessages({
|
||||
verificationInvalid: { id: 'sms_verification.invalid', defaultMessage: 'Please enter a valid phone number.' },
|
||||
verificationSuccess: { id: 'sms_verification.success', defaultMessage: 'A verification code has been sent to your phone number.' },
|
||||
verificationFail: { id: 'sms_verification.fail', defaultMessage: 'Failed to send SMS message to your phone number.' },
|
||||
verificationExpired: { id: 'sms_verification.expired', defaultMessage: 'Your SMS token has expired.' },
|
||||
});
|
||||
|
||||
const Statuses = {
|
||||
IDLE: 'IDLE',
|
||||
REQUESTED: 'REQUESTED',
|
||||
|
@ -38,10 +45,7 @@ const SmsVerification = () => {
|
|||
setStatus(Statuses.IDLE);
|
||||
dispatch(
|
||||
snackbar.error(
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.invalid',
|
||||
defaultMessage: 'Please enter a valid phone number.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationInvalid),
|
||||
),
|
||||
);
|
||||
return;
|
||||
|
@ -50,18 +54,12 @@ const SmsVerification = () => {
|
|||
dispatch(requestPhoneVerification(phone!)).then(() => {
|
||||
dispatch(
|
||||
snackbar.success(
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.success',
|
||||
defaultMessage: 'A verification code has been sent to your phone number.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationSuccess),
|
||||
),
|
||||
);
|
||||
setStatus(Statuses.REQUESTED);
|
||||
}).catch((error: AxiosError) => {
|
||||
const message = (error.response?.data as any)?.message || intl.formatMessage({
|
||||
id: 'sms_verification.fail',
|
||||
defaultMessage: 'Failed to send SMS message to your phone number.',
|
||||
});
|
||||
const message = (error.response?.data as any)?.message || intl.formatMessage(messages.verificationFail);
|
||||
|
||||
dispatch(snackbar.error(message));
|
||||
setStatus(Statuses.FAIL);
|
||||
|
@ -78,10 +76,7 @@ const SmsVerification = () => {
|
|||
dispatch(confirmPhoneVerification(verificationCode))
|
||||
.catch(() => dispatch(
|
||||
snackbar.error(
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.invalid',
|
||||
defaultMessage: 'Your SMS token has expired.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationExpired),
|
||||
),
|
||||
));
|
||||
};
|
||||
|
@ -97,7 +92,7 @@ const SmsVerification = () => {
|
|||
<div>
|
||||
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-800 border-solid -mx-4 sm:-mx-10'>
|
||||
<h1 className='text-center font-bold text-2xl'>
|
||||
{intl.formatMessage({ id: 'sms_verification.sent.header', defaultMessage: 'Verification code' })}
|
||||
<FormattedMessage id='sms_verification.sent.header' defaultMessage='Verification code' />
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
@ -136,7 +131,9 @@ const SmsVerification = () => {
|
|||
return (
|
||||
<div>
|
||||
<div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-800 border-solid -mx-4 sm:-mx-10'>
|
||||
<h1 className='text-center font-bold text-2xl'>{intl.formatMessage({ id: 'sms_verification.header', defaultMessage: 'Enter your phone number' })}</h1>
|
||||
<h1 className='text-center font-bold text-2xl'>
|
||||
<FormattedMessage id='sms_verification.header' defaultMessage='Enter your phone number' />
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
"account.welcome": "Willkommen",
|
||||
"account_gallery.none": "Keine Medien vorhanden.",
|
||||
"account_note.hint": "You can keep notes about this user for yourself (this will not be shared with them):",
|
||||
"account_note.placeholder": "No comment provided",
|
||||
"account_note.placeholder": "Kein Kommentar hinterlegt",
|
||||
"account_note.save": "Speichern",
|
||||
"account_note.target": "Note for @{target}",
|
||||
"account_search.placeholder": "Nach einem Account suchen",
|
||||
|
@ -362,12 +362,12 @@
|
|||
"developers.navigation.network_error_label": "Network error",
|
||||
"developers.navigation.settings_store_label": "Settings store",
|
||||
"developers.navigation.test_timeline_label": "Test timeline",
|
||||
"developers.settings_store.hint": "It is possible to directly edit your user settings here. BE CAREFUL! Editing this section can break your account, and you will only be able to recover through the API.",
|
||||
"developers.settings_store.hint": "Hier können die Benutzereinstellungen direkt bearbeitet werden. VORSICHT! Die Bearbeitung dieses Abschnitts kann das Konto zerstören - eine Wiederherstellung ist ausschließlich per API möglich",
|
||||
"direct.search_placeholder": "Nachricht senden an…",
|
||||
"directory.federated": "From known fediverse",
|
||||
"directory.local": "From {domain} only",
|
||||
"directory.local": "Ausschließlich von {domain}",
|
||||
"directory.new_arrivals": "New arrivals",
|
||||
"directory.recently_active": "Recently active",
|
||||
"directory.recently_active": "Zuletzt aktiv",
|
||||
"edit_federation.followers_only": "Beitrag nur für Follower anzeigen",
|
||||
"edit_federation.force_nsfw": "Markierung aller Anhänge als heikel erzwingen",
|
||||
"edit_federation.media_removal": "Alle Medien entfernen",
|
||||
|
@ -375,7 +375,7 @@
|
|||
"edit_federation.save": "Speichern",
|
||||
"edit_federation.success": "{host} federation was updated",
|
||||
"edit_federation.unlisted": "Ungelistete Beiträge erzwingen",
|
||||
"edit_password.header": "Change Password",
|
||||
"edit_password.header": "Passwort ändern",
|
||||
"edit_profile.error": "Profil konnte nicht geändert werden",
|
||||
"edit_profile.fields.accepts_email_list_label": "Newsletter abonnieren",
|
||||
"edit_profile.fields.avatar_label": "Profilbild",
|
||||
|
@ -384,24 +384,24 @@
|
|||
"edit_profile.fields.birthday_label": "Geburtstag",
|
||||
"edit_profile.fields.birthday_placeholder": "Dein Geburtstag",
|
||||
"edit_profile.fields.bot_label": "Dieses Konto wird für einen Bot genutzt",
|
||||
"edit_profile.fields.discoverable_label": "Allow account discovery",
|
||||
"edit_profile.fields.discoverable_label": "Konto im Instanz-Verzeichnis eintragen",
|
||||
"edit_profile.fields.display_name_label": "Angezeigter Nutzername",
|
||||
"edit_profile.fields.display_name_placeholder": "Name",
|
||||
"edit_profile.fields.header_label": "Profilbanner",
|
||||
"edit_profile.fields.hide_network_label": "Follower und Nutzer, denen du folgst, nicht öffentlich anzeigen",
|
||||
"edit_profile.fields.location_label": "Location",
|
||||
"edit_profile.fields.location_placeholder": "Location",
|
||||
"edit_profile.fields.location_label": "Wohnort",
|
||||
"edit_profile.fields.location_placeholder": "Wohnort",
|
||||
"edit_profile.fields.locked_label": "Profil auf privat stellen",
|
||||
"edit_profile.fields.meta_fields.content_placeholder": "Content",
|
||||
"edit_profile.fields.meta_fields.label_placeholder": "Label",
|
||||
"edit_profile.fields.stranger_notifications_label": "Benachrichtigungen von Fremden blockieren",
|
||||
"edit_profile.fields.website_label": "Website",
|
||||
"edit_profile.fields.website_placeholder": "Display a Link",
|
||||
"edit_profile.header": "Edit Profile",
|
||||
"edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.",
|
||||
"edit_profile.fields.website_placeholder": "Link anzeigen",
|
||||
"edit_profile.header": "Profile bearbeiten",
|
||||
"edit_profile.hints.accepts_email_list": "Status- und Werbenachrichten abonnieren.",
|
||||
"edit_profile.hints.avatar": "Erlaubte Formate sind PNG, GIF oder JPG. Die Datei darf nicht größer als 2 MB sein. Das Bild wird automatisch auf 400x400px verkleinert.",
|
||||
"edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored",
|
||||
"edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services",
|
||||
"edit_profile.hints.bot": "Dieses Konto ist ein Bot. Aktivitäten werden möglicherweise nicht moderiert.",
|
||||
"edit_profile.hints.discoverable": "Konto im Verzeichnis listen und Indexierung durch externe Dienste ermöglichen",
|
||||
"edit_profile.hints.header": "Erlaubte Formate sind PNG, GIF oder JPG. Die Datei darf nicht größer als 2 MB sein. Das Bild wird automatisch auf 1500x500px verkleinert.",
|
||||
"edit_profile.hints.hide_network": "Deine Follower und wem du folgst wird nicht in deinem Profil angezeit.",
|
||||
"edit_profile.hints.locked": "Follower müssen einzeln bestätigt werden.",
|
||||
|
@ -409,13 +409,13 @@
|
|||
"edit_profile.save": "Speichern",
|
||||
"edit_profile.success": "Profil gespeichert",
|
||||
"email_passthru.confirmed.body": "Close this tab and continue the registration process on the {bold} from which you sent this email confirmation.",
|
||||
"email_passthru.confirmed.heading": "Email Confirmed!",
|
||||
"email_passthru.confirmed.heading": "E-Mail bestätigt!",
|
||||
"email_passthru.generic_fail.body": "Please request a new email confirmation.",
|
||||
"email_passthru.generic_fail.heading": "Something Went Wrong",
|
||||
"email_passthru.token_expired.body": "Your email token has expired. Please request a new email confirmation from the {bold} from which you sent this email confirmation.",
|
||||
"email_passthru.token_expired.heading": "Token Expired",
|
||||
"email_passthru.token_not_found.body": "Your email token was not found. Please request a new email confirmation from the {bold} from which you sent this email confirmation.",
|
||||
"email_passthru.token_not_found.heading": "Invalid Token",
|
||||
"email_passthru.generic_fail.heading": "Etwas ging schief",
|
||||
"email_passthru.token_expired.body": "Die Bestätigungsnachricht ist abgelaufen. Bitte eine neue Bestätigung von {bold} beantragen, von wo du diese Nachricht erhalten hast.",
|
||||
"email_passthru.token_expired.heading": "Token abgelaufen",
|
||||
"email_passthru.token_not_found.body": "Bestätigungstoken nicht erkannt. Bitte beantrage ein neues Token von {bold} wo du diese Nachricht her hast.",
|
||||
"email_passthru.token_not_found.heading": "Ungültiges Token",
|
||||
"embed.instructions": "Du kannst diesen Beitrag auf deiner Webseite einbetten, indem du den folgenden Code einfügst.",
|
||||
"embed.preview": "Vorschau:",
|
||||
"emoji_button.activity": "Aktivitäten",
|
||||
|
@ -446,7 +446,7 @@
|
|||
"empty_column.favourited_statuses": "Du hast noch keine Beiträge favorisiert. Favorisierte Beiträge erscheinen hier.",
|
||||
"empty_column.favourites": "Diesen Beitrag hat noch niemand favorisiert. Sobald es jemand tut, wird das hier angezeigt.",
|
||||
"empty_column.filters": "Du hast keine Wörter stummgeschaltet.",
|
||||
"empty_column.follow_recommendations": "Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.",
|
||||
"empty_column.follow_recommendations": "Sieht so aus, als gibt es gerade keine Vorschläge für dich. Versuche, über die Suche bekannte Personen zu finden oder schaue dich in aktuellen Hashtags um.",
|
||||
"empty_column.follow_requests": "Du hast noch keine Folgeanfragen. Sobald du eine erhältst, wird sie hier angezeigt.",
|
||||
"empty_column.group": "Diese Gruppe hat noch keine Beiträge. Sobald ein Gruppenmitglied einen Beitrag erstellt, wird er hier angezeigt.",
|
||||
"empty_column.hashtag": "Unter diesem Hashtag gibt es noch nichts.",
|
||||
|
@ -459,9 +459,9 @@
|
|||
"empty_column.public": "Hier ist nichts zu sehen! Schreibe etwas öffentlich oder folge Profilen von anderen Servern, um die Zeitleiste aufzufüllen",
|
||||
"empty_column.remote": "There is nothing here! Manually follow users from {instance} to fill it up.",
|
||||
"empty_column.scheduled_statuses": "Bisher wurden keine vorbereiteten Beiträge erstellt. Vorbereitete Beiträge werden hier angezeigt.",
|
||||
"empty_column.search.accounts": "There are no people results for \"{term}\"",
|
||||
"empty_column.search.hashtags": "There are no hashtags results for \"{term}\"",
|
||||
"empty_column.search.statuses": "There are no posts results for \"{term}\"",
|
||||
"empty_column.search.accounts": "Es wurden keine Nutzer unter \"{term}\" gefunden",
|
||||
"empty_column.search.hashtags": "Es wurden keine Hashtags unter \"{term}\" gefunden",
|
||||
"empty_column.search.statuses": "Es wurden keine Posts unter \"{term}\" gefunden",
|
||||
"export_data.actions.export": "Exportieren",
|
||||
"export_data.actions.export_blocks": "Liste geblockter Nutzer expotieren",
|
||||
"export_data.actions.export_follows": "Liste der Nutzer, denen du folgst, exportieren",
|
||||
|
@ -481,10 +481,10 @@
|
|||
"federation_restriction.media_nsfw": "Anhänge als NSFW markiert",
|
||||
"federation_restriction.partial_media_removal": "Partial media removal",
|
||||
"federation_restrictions.empty_message": "{siteTitle} has not restricted any instances.",
|
||||
"federation_restrictions.explanation_box.message": "Normally servers on the Fediverse can communicate freely. {siteTitle} has imposed restrictions on the following servers.",
|
||||
"federation_restrictions.explanation_box.message": "Üblicherweise föderieren Dienste im Fediverse. {siteTitle} hat die Föderation für die nachfolgenden Instanzen beschränkt.",
|
||||
"federation_restrictions.explanation_box.title": "Instance-specific policies",
|
||||
"federation_restrictions.not_disclosed_message": "{siteTitle} does not disclose federation restrictions through the API.",
|
||||
"fediverse_tab.explanation_box.dismiss": "Don't show again",
|
||||
"fediverse_tab.explanation_box.dismiss": "Nicht mehr anzeigen",
|
||||
"fediverse_tab.explanation_box.explanation": "{site_title} ist Teil des Fediverse, einem Sozialen Netzwerk, das aus tausenden unabhängigen Instanzen (aka \"Servern\") besteht. Die Beiträge, die du hier siehst, stammen überwiegend von anderen Servern. Du kannst auf alle Einträge reagieren oder jeden Server blockieren, der dir nicht gefällt. Die Bezeichnung hinter dem zweiten @-Symbol ist der Name des entsprechenden Servers. Um nur Beiträge von {site_title} zu sehen, wähle {local} aus.",
|
||||
"fediverse_tab.explanation_box.title": "Was ist das Fediverse?",
|
||||
"filters.added": "Filter hinzugefügt.",
|
||||
|
@ -492,16 +492,16 @@
|
|||
"filters.context_hint": "One or multiple contexts where the filter should apply",
|
||||
"filters.filters_list_context_label": "Filter contexts:",
|
||||
"filters.filters_list_delete": "Löschen",
|
||||
"filters.filters_list_details_label": "Filter settings:",
|
||||
"filters.filters_list_details_label": "Filtereinstellungen:",
|
||||
"filters.filters_list_drop": "Drop",
|
||||
"filters.filters_list_hide": "Hide",
|
||||
"filters.filters_list_hide": "Verstecken",
|
||||
"filters.filters_list_phrase_label": "Stichwort oder Wortfolge:",
|
||||
"filters.filters_list_whole-word": "Whole word",
|
||||
"filters.removed": "Filter gelöscht.",
|
||||
"follow_recommendation.subhead": "Let's get started!",
|
||||
"follow_recommendations.done": "Done",
|
||||
"follow_recommendations.heading": "Folge Nutzern, deren Beiträge du sehen möchtest. Hier sind einige Vorschläge:",
|
||||
"follow_recommendations.lead": "Posts from people you follow will show up in chronological order on your home feed. Don't be afraid to make mistakes, you can unfollow people just as easily any time!",
|
||||
"follow_recommendations.lead": "Posts von Usern, denen du folgst, werden in deinem Home-Feed in chronologischer Reihenfolge angezeigt. Los geht's - du kannst anderen später jederzeit wieder entfolgen.",
|
||||
"follow_request.authorize": "Bestätigen",
|
||||
"follow_request.reject": "Ablehnen",
|
||||
"forms.copy": "Kopieren",
|
||||
|
@ -528,7 +528,7 @@
|
|||
"groups.join": "Gruppe beitreten",
|
||||
"groups.leave": "Gruppe verlassen",
|
||||
"groups.removed_accounts": "Entfernte Accounts",
|
||||
"groups.sidebar-panel.item.no_recent_activity": "No recent activity",
|
||||
"groups.sidebar-panel.item.no_recent_activity": "Keine kürzliche Aktivität",
|
||||
"groups.sidebar-panel.item.view": "Neue Beiträge",
|
||||
"groups.sidebar-panel.show_all": "Alle anzeigen",
|
||||
"groups.sidebar-panel.title": "Gruppenmitgliedschaften",
|
||||
|
@ -543,7 +543,7 @@
|
|||
"header.login.label": "Anmelden",
|
||||
"header.login.password.label": "Password",
|
||||
"header.login.username.placeholder": "Email oder Nutzername",
|
||||
"header.register.label": "Anmelden",
|
||||
"header.register.label": "Registrieren",
|
||||
"home.column_settings.show_direct": "Direktnachricht anzeigen",
|
||||
"home.column_settings.show_reblogs": "Geteilte Beiträge anzeigen",
|
||||
"home.column_settings.show_replies": "Antworten anzeigen",
|
||||
|
@ -571,10 +571,10 @@
|
|||
"intervals.full.minutes": "{number, plural, one {# Minute} other {# Minuten}}",
|
||||
"introduction.federation.action": "Weiter",
|
||||
"introduction.federation.home.headline": "Home",
|
||||
"introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!",
|
||||
"introduction.federation.home.text": "Posts von Konten, denen du folgst, werden in deinem Home-Feed erscheinen. Du kannst jedem auf deiner Instanz folgen!!",
|
||||
"introduction.interactions.action": "Finish tutorial!",
|
||||
"introduction.interactions.favourite.headline": "Favorite",
|
||||
"introduction.interactions.favourite.text": "You can save a post for later, and let the author know that you liked it, by favoriting it.",
|
||||
"introduction.interactions.favourite.headline": "Favorisieren",
|
||||
"introduction.interactions.favourite.text": "Du kannst einen Beitrag für später speichern und den Autor wissen lassen, dass er Ihnen gefallen hat, indem du ihm ein Like hinterlässt.",
|
||||
"introduction.interactions.reblog.headline": "Teilen",
|
||||
"introduction.interactions.reblog.text": "You can share other people's posts with your followers by reposting them.",
|
||||
"introduction.interactions.reply.headline": "Antworten",
|
||||
|
@ -633,37 +633,37 @@
|
|||
"login.fields.instance_label": "Instance",
|
||||
"login.fields.instance_placeholder": "example.com",
|
||||
"login.fields.otp_code_hint": "Enter the two-factor code generated by your phone app or use one of your recovery codes",
|
||||
"login.fields.otp_code_label": "Two-factor code:",
|
||||
"login.fields.otp_code_label": "Zwei-Faktoren-Code:",
|
||||
"login.fields.password_placeholder": "Passwort",
|
||||
"login.fields.username_label": "Email or username",
|
||||
"login.fields.username_label": "E-Mail oder Nutzername",
|
||||
"login.log_in": "Anmelden",
|
||||
"login.otp_log_in": "OTP Login",
|
||||
"login.reset_password_hint": "Probleme beim Anmelden?",
|
||||
"login.sign_in": "Sign in",
|
||||
"media_gallery.toggle_visible": "Sichtbarkeit umschalten",
|
||||
"media_panel.empty_message": "No media found.",
|
||||
"media_panel.empty_message": "Keine Medien gefunden.",
|
||||
"media_panel.title": "Media",
|
||||
"mfa.confirm.success_message": "MFA confirmed",
|
||||
"mfa.disable.success_message": "MFA disabled",
|
||||
"mfa.mfa_disable_enter_password": "Enter your current password to disable two-factor auth:",
|
||||
"mfa.mfa_setup.code_hint": "Enter the code from your two-factor app.",
|
||||
"mfa.confirm.success_message": "MFA bestätigt",
|
||||
"mfa.disable.success_message": "MFA abgeschaltet",
|
||||
"mfa.mfa_disable_enter_password": "Aktuelles Passwort eingäben, um Zwei-Faktoren-Authentifizierung zu deaktivieren:",
|
||||
"mfa.mfa_setup.code_hint": "Bitte den Code aus der 2FA-App eingeben.",
|
||||
"mfa.mfa_setup.code_placeholder": "Code",
|
||||
"mfa.mfa_setup.password_hint": "Enter your current password to confirm your identity.",
|
||||
"mfa.mfa_setup.password_placeholder": "Password",
|
||||
"mfa.mfa_setup_scan_description": "Using your two-factor app, scan this QR code or enter text key:",
|
||||
"mfa.mfa_setup.password_hint": "Aktuelles Passwort zur Bestätigung eingeben.",
|
||||
"mfa.mfa_setup.password_placeholder": "Passwort",
|
||||
"mfa.mfa_setup_scan_description": "Nutze eine 2FA-App, scanne den QR-Code oder gibt diesen Schlüsseltext ein:",
|
||||
"mfa.mfa_setup_scan_title": "Scan",
|
||||
"mfa.mfa_setup_verify_title": "Verify",
|
||||
"mfa.otp_enabled_description": "You have enabled two-factor authentication via OTP.",
|
||||
"mfa.otp_enabled_title": "OTP Enabled",
|
||||
"mfa.setup_recoverycodes": "Recovery codes",
|
||||
"mfa.setup_warning": "Write these codes down or save them somewhere secure - otherwise you won't see them again. If you lose access to your 2FA app and recovery codes you'll be locked out of your account.",
|
||||
"migration.fields.acct.label": "Handle of the new account",
|
||||
"mfa.mfa_setup_verify_title": "Bestätigen",
|
||||
"mfa.otp_enabled_description": "Du hast die Zwei-Faktoren-Authentifizierung per OTP aktiviert.",
|
||||
"mfa.otp_enabled_title": "OTP eingeschaltet",
|
||||
"mfa.setup_recoverycodes": "Sicherungs-Keys",
|
||||
"mfa.setup_warning": "Notiere dir diese Codes an einem sicheren Platz - andernfalls wirst du sie nicht mehr auffinden und aus deinem Konto ausgesperrt.",
|
||||
"migration.fields.acct.label": "Handle des neuen Kontos",
|
||||
"migration.fields.acct.placeholder": "username@domain",
|
||||
"migration.fields.confirm_password.label": "Current password",
|
||||
"migration.hint": "This will move your followers to the new account. No other data will be moved. To perform migration, you need to {link} on your new account first.",
|
||||
"migration.hint.link": "create an account alias",
|
||||
"migration.move_account.fail": "Account migration failed.",
|
||||
"migration.move_account.success": "Account successfully moved.",
|
||||
"migration.fields.confirm_password.label": "Aktuelles Passwort",
|
||||
"migration.hint": "Damit werden deine Follower auf dein neues Konto übertragen - weitere Daten werden nicht migriert. Zur Bestätigung ist es nötig, {link} auf deinem neuen Konto zunächst zu bestätigen.",
|
||||
"migration.hint.link": "Neues Alias erstellen",
|
||||
"migration.move_account.fail": "Account-Übertragung fehlgeschlagen.",
|
||||
"migration.move_account.success": "Account-Übertragung fehlgeschlagen.",
|
||||
"migration.submit": "Move followers",
|
||||
"missing_description_modal.cancel": "Abbrechen",
|
||||
"missing_description_modal.continue": "Senden",
|
||||
|
@ -702,8 +702,8 @@
|
|||
"navigation_bar.preferences": "Einstellungen",
|
||||
"navigation_bar.profile_directory": "Profilverzeichnis",
|
||||
"navigation_bar.security": "Sicherheit",
|
||||
"navigation_bar.soapbox_config": "Soapbox config",
|
||||
"notification.birthday": "{name} has a birthday today",
|
||||
"navigation_bar.soapbox_config": "Soapbox Konfiguration",
|
||||
"notification.birthday": "{name} hat Geburtstag!",
|
||||
"notification.birthday.more": "{count} more {count, plural, one {friend} other {friends}}",
|
||||
"notification.birthday_plural": "{name} and {more} have birthday today",
|
||||
"notification.pleroma:chat_mention": "{name} hat dir eine Nachricht gesendet",
|
||||
|
@ -718,7 +718,7 @@
|
|||
"notification.status": "{name} just posted",
|
||||
"notifications.clear": "Benachrichtigungen löschen",
|
||||
"notifications.clear_confirmation": "Bist du dir sicher, dass du alle Benachrichtigungen löschen möchtest?",
|
||||
"notifications.clear_heading": "Clear notifications",
|
||||
"notifications.clear_heading": "Benachrichtigungen löschen",
|
||||
"notifications.column_settings.alert": "Desktop-Benachrichtigungen",
|
||||
"notifications.column_settings.birthdays.category": "Geburtstage",
|
||||
"notifications.column_settings.birthdays.show": "Geburtstagserinnerungen anzeigen",
|
||||
|
@ -786,12 +786,12 @@
|
|||
"preferences.fields.auto_play_gif_label": "Animierte GIFs automatisch abspielen",
|
||||
"preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page",
|
||||
"preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page",
|
||||
"preferences.fields.boost_modal_label": "Show confirmation dialog before reposting",
|
||||
"preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post",
|
||||
"preferences.fields.display_media.default": "Hide media marked as sensitive",
|
||||
"preferences.fields.display_media.hide_all": "Always hide media",
|
||||
"preferences.fields.display_media.show_all": "Always show media",
|
||||
"preferences.fields.expand_spoilers_label": "Always expand posts marked with content warnings",
|
||||
"preferences.fields.boost_modal_label": "Bestätigungsdialog öffnen, bevor ein Beitrag geboostet wird",
|
||||
"preferences.fields.delete_modal_label": "Bestätigungsdialog öffnen, bevor ein Beitrag gelöscht wird",
|
||||
"preferences.fields.display_media.default": "Als verstörend gekennzeichnete Medien grundsätzlich anzeigen",
|
||||
"preferences.fields.display_media.hide_all": "Medien grundsätzlich ausblenden",
|
||||
"preferences.fields.display_media.show_all": "Medien grundsätzlich anzeigen",
|
||||
"preferences.fields.expand_spoilers_label": "Als verstörend gekennzeichnete Posts grundsätzlich ausklappen",
|
||||
"preferences.fields.language_label": "Sprache",
|
||||
"preferences.fields.media_display_label": "Media display",
|
||||
"preferences.hints.feed": "In your home feed",
|
||||
|
@ -804,29 +804,29 @@
|
|||
"privacy.public.short": "Öffentlich",
|
||||
"privacy.unlisted.long": "Wird in öffentlichen Zeitleisten nicht gezeigt",
|
||||
"privacy.unlisted.short": "Nicht gelistet",
|
||||
"profile_dropdown.add_account": "Add an existing account",
|
||||
"profile_dropdown.logout": "Log out @{acct}",
|
||||
"profile_dropdown.add_account": "Bestehendes Konto hinzufügen",
|
||||
"profile_dropdown.logout": "Aus @{acct} abmelden",
|
||||
"profile_fields_panel.title": "Profile fields",
|
||||
"public.column_settings.title": "Fediverse timeline settings",
|
||||
"reactions.all": "All",
|
||||
"public.column_settings.title": "Einstellungen der globalen Timeline",
|
||||
"reactions.all": "Alle",
|
||||
"regeneration_indicator.label": "Laden…",
|
||||
"regeneration_indicator.sublabel": "Deine Startseite wird gerade vorbereitet!",
|
||||
"register_invite.lead": "Complete the form below to create an account.",
|
||||
"register_invite.title": "You've been invited to join {siteTitle}!",
|
||||
"register_invite.lead": "Fülle folgendes Formular aus, bevor dein Konto erstellt wird.",
|
||||
"register_invite.title": "Du wurdest zu {siteTitle} eingeladen!",
|
||||
"registration.agreement": "Ich akzeptiere die {tos}.",
|
||||
"registration.captcha.hint": "Click the image to get a new captcha",
|
||||
"registration.closed_message": "{instance} is not accepting new members",
|
||||
"registration.closed_title": "Registrations Closed",
|
||||
"registration.confirmation_modal.close": "Close",
|
||||
"registration.captcha.hint": "Bild anklicken, um neues Captcha zu erhalten",
|
||||
"registration.closed_message": "{instance} nimmt keine neuen Mitglieder auf",
|
||||
"registration.closed_title": "Registrierungen geschlossen",
|
||||
"registration.confirmation_modal.close": "Schließen",
|
||||
"registration.fields.confirm_placeholder": "Passwort (wiederholen)",
|
||||
"registration.fields.email_placeholder": "Emailadresse",
|
||||
"registration.fields.password_placeholder": "Passwort",
|
||||
"registration.fields.username_hint": "Only letters, numbers, and underscores are allowed.",
|
||||
"registration.fields.username_placeholder": "Nutzername",
|
||||
"registration.fields.username_placeholder": "Benutzername",
|
||||
"registration.newsletter": "Newsletter abonnieren.",
|
||||
"registration.password_mismatch": "Die eingegebenen Passwörter stimmen nicht überein",
|
||||
"registration.reason": "Why do you want to join?",
|
||||
"registration.reason_hint": "This will help us review your application",
|
||||
"registration.reason": "Warum möchtest du ein Teil von uns werden?",
|
||||
"registration.reason_hint": "Damit hilfst du uns, über deinen Antrag zu entscheiden",
|
||||
"registration.sign_up": "Registrieren",
|
||||
"registration.tos": "Nutzungsbedingungen",
|
||||
"registration.username_unavailable": "Der gewählte Nutzername ist bereits vorhanden.",
|
||||
|
@ -846,15 +846,15 @@
|
|||
"remote_interaction.divider": "or",
|
||||
"remote_interaction.favourite": "Proceed to like",
|
||||
"remote_interaction.favourite_title": "Like a post remotely",
|
||||
"remote_interaction.follow": "Proceed to follow",
|
||||
"remote_interaction.follow": "Fortsetzen, um zu folgen",
|
||||
"remote_interaction.follow_title": "Follow {user} remotely",
|
||||
"remote_interaction.poll_vote": "Proceed to vote",
|
||||
"remote_interaction.poll_vote_title": "Vote in a poll remotely",
|
||||
"remote_interaction.reblog": "Proceed to repost",
|
||||
"remote_interaction.reblog": "Boost bestätigen",
|
||||
"remote_interaction.reblog_title": "Reblog a post remotely",
|
||||
"remote_interaction.reply": "Proceed to reply",
|
||||
"remote_interaction.reply": "Antwort bestätigen",
|
||||
"remote_interaction.reply_title": "Reply to a post remotely",
|
||||
"remote_interaction.user_not_found_error": "Couldn't find given user",
|
||||
"remote_interaction.user_not_found_error": "Konto nicht gefunden",
|
||||
"remote_timeline.filter_message": "You are viewing the timeline of {instance}.",
|
||||
"reply_indicator.cancel": "Abbrechen",
|
||||
"reply_mentions.account.add": "Add to mentions",
|
||||
|
@ -873,8 +873,8 @@
|
|||
"reset_password.header": "Set New Password",
|
||||
"schedule.post_time": "Post Date/Time",
|
||||
"schedule.remove": "Remove schedule",
|
||||
"schedule_button.add_schedule": "Schedule post for later",
|
||||
"schedule_button.remove_schedule": "Post immediately",
|
||||
"schedule_button.add_schedule": "Für späteres Absenden planen",
|
||||
"schedule_button.remove_schedule": "Sofort posten",
|
||||
"scheduled_status.cancel": "Cancel",
|
||||
"search.action": "Search for “{query}”",
|
||||
"search.placeholder": "Suche",
|
||||
|
@ -883,11 +883,11 @@
|
|||
"search_results.statuses": "Beiträge",
|
||||
"search_results.top": "Top",
|
||||
"security.codes.fail": "Failed to fetch backup codes",
|
||||
"security.confirm.fail": "Incorrect code or password. Try again.",
|
||||
"security.confirm.fail": "Falscher Code oder falsches Passwort. Bitte erneut versuchen.",
|
||||
"security.delete_account.fail": "Account deletion failed.",
|
||||
"security.delete_account.success": "Das Konto wurde erfolgreich gelöscht.",
|
||||
"security.disable.fail": "Incorrect password. Try again.",
|
||||
"security.disable_mfa": "Disable",
|
||||
"security.disable.fail": "Falsches Passwort. Versuche es erneut.",
|
||||
"security.disable_mfa": "Abschalten",
|
||||
"security.fields.email.label": "Emailaddresse",
|
||||
"security.fields.new_password.label": "Neues Passwort",
|
||||
"security.fields.old_password.label": "Bisheriges Passwort",
|
||||
|
@ -897,33 +897,33 @@
|
|||
"security.headers.tokens": "Sessions",
|
||||
"security.headers.update_email": "Email ändern",
|
||||
"security.headers.update_password": "Passwort ändern",
|
||||
"security.mfa": "Set up 2-Factor Auth",
|
||||
"security.mfa": "Zwei-Faktoren-Authentifizierung einstellen",
|
||||
"security.mfa_enabled": "You have multi-factor authentication set up with OTP.",
|
||||
"security.mfa_header": "Authorization Methods",
|
||||
"security.mfa_setup_hint": "Configure multi-factor authentication with OTP",
|
||||
"security.mfa_header": "Authentifizierungsmethoden",
|
||||
"security.mfa_setup_hint": "OTP-Zwei-Faktoren-Authentifizierung konfigurieren",
|
||||
"security.qr.fail": "Failed to fetch setup key",
|
||||
"security.submit": "Änderungen speichern",
|
||||
"security.submit.delete": "Konto löschen",
|
||||
"security.text.delete": "To delete your account, enter your password then click Delete Account. This is a permanent action that cannot be undone. Your account will be destroyed from this server, and a deletion request will be sent to other servers. It's not guaranteed that all servers will purge your account.",
|
||||
"security.text.delete": "Gib dein Passwort ein, um dein Konto zu löschen. Diese Löschung ist dauerhaft und kann nicht rückgängig gemacht werden. Dein Konto wird von diesem Server aus gelöscht und eine Löschungsanfrage wird an andere Server gesendet. Es ist nicht garantiert, dass alle Instanzen dein Konto löschen..",
|
||||
"security.tokens.revoke": "Widerrufen",
|
||||
"security.update_email.fail": "Änderung der Emailadresse fehlgeschlagen.",
|
||||
"security.update_email.success": "Die neue Emailadresse wurde gespeichert.",
|
||||
"security.update_password.fail": "Änderung des Passwortes fehlgeschlagen.",
|
||||
"security.update_password.success": "Das Passwort wurde erfolgreich geändert.",
|
||||
"settings.change_email": "Change Email",
|
||||
"settings.change_password": "Change Password",
|
||||
"settings.configure_mfa": "Configure MFA",
|
||||
"settings.delete_account": "Delete Account",
|
||||
"settings.change_email": "E-Mail ändern",
|
||||
"settings.change_password": "Passwort ändern",
|
||||
"settings.configure_mfa": "MFA konfigurieren",
|
||||
"settings.delete_account": "Konto löschen",
|
||||
"settings.edit_profile": "Edit Profile",
|
||||
"settings.preferences": "Preferences",
|
||||
"settings.profile": "Profile",
|
||||
"settings.save.success": "Your preferences have been saved!",
|
||||
"settings.security": "Security",
|
||||
"settings.settings": "Settings",
|
||||
"settings.preferences": "Einstellungen",
|
||||
"settings.profile": "Profil",
|
||||
"settings.save.success": "Einstellungen wurden gespeichert!",
|
||||
"settings.security": "Sicherheit",
|
||||
"settings.settings": "Einstellungen",
|
||||
"signup_panel.subtitle": "Jetzt anmelden, um mitzureden.",
|
||||
"signup_panel.title": "Neu auf {site_title}?",
|
||||
"snackbar.view": "View",
|
||||
"soapbox_config.authenticated_profile_hint": "Users must be logged-in to view replies and media on user profiles.",
|
||||
"snackbar.view": "Anzeigen",
|
||||
"soapbox_config.authenticated_profile_hint": "Nur angemeldete Nutzer können Antworten und Medien auf Nutzerprofilen sehen.",
|
||||
"soapbox_config.authenticated_profile_label": "Profiles require authentication",
|
||||
"soapbox_config.copyright_footer.meta_fields.label_placeholder": "Copyright footer",
|
||||
"soapbox_config.crypto_address.meta_fields.address_placeholder": "Address",
|
||||
|
@ -934,21 +934,21 @@
|
|||
"soapbox_config.display_fqn_label": "Display domain (eg @user@domain) for local accounts.",
|
||||
"soapbox_config.fields.accent_color_label": "Accent color",
|
||||
"soapbox_config.fields.brand_color_label": "Brand color",
|
||||
"soapbox_config.fields.crypto_address.add": "Add new crypto address",
|
||||
"soapbox_config.fields.crypto_addresses_label": "Cryptocurrency addresses",
|
||||
"soapbox_config.fields.crypto_address.add": "Cryptocoin-Adresse hinzufügen",
|
||||
"soapbox_config.fields.crypto_addresses_label": "Cryptocoin-Adresse",
|
||||
"soapbox_config.fields.home_footer.add": "Add new Home Footer Item",
|
||||
"soapbox_config.fields.home_footer_fields_label": "Home footer items",
|
||||
"soapbox_config.fields.logo_label": "Logo",
|
||||
"soapbox_config.fields.promo_panel.add": "Add new Promo panel item",
|
||||
"soapbox_config.fields.promo_panel_fields_label": "Promo panel items",
|
||||
"soapbox_config.fields.theme_label": "Default theme",
|
||||
"soapbox_config.fields.theme_label": "Standard-Theme",
|
||||
"soapbox_config.greentext_label": "Enable greentext support",
|
||||
"soapbox_config.hints.crypto_addresses": "Add cryptocurrency addresses so users of your site can donate to you. Order matters, and you must use lowercase ticker values.",
|
||||
"soapbox_config.hints.home_footer_fields": "You can have custom defined links displayed on the footer of your static pages",
|
||||
"soapbox_config.hints.logo": "SVG. At most 2 MB. Will be displayed to 50px height, maintaining aspect ratio",
|
||||
"soapbox_config.hints.logo": "SVG. Maximal 2 MB. Die Darstellung erfolgt mit 50px Höhe, das Seitenverhältnis wird beibehalten",
|
||||
"soapbox_config.hints.promo_panel_fields": "You can have custom defined links displayed on the right panel of the timelines page.",
|
||||
"soapbox_config.hints.promo_panel_icons": "{ link }",
|
||||
"soapbox_config.hints.promo_panel_icons.link": "Soapbox Icons List",
|
||||
"soapbox_config.hints.promo_panel_icons.link": "Soapbox Icon-Liste",
|
||||
"soapbox_config.home_footer.meta_fields.label_placeholder": "Label",
|
||||
"soapbox_config.home_footer.meta_fields.url_placeholder": "URL",
|
||||
"soapbox_config.promo_panel.meta_fields.icon_placeholder": "Icon",
|
||||
|
@ -957,13 +957,13 @@
|
|||
"soapbox_config.raw_json_hint": "Edit the settings data directly. Changes made directly to the JSON file will override the form fields above. Click Save to apply your changes.",
|
||||
"soapbox_config.raw_json_label": "Advanced: Edit raw JSON data",
|
||||
"soapbox_config.save": "Speichern",
|
||||
"soapbox_config.saved": "Soapbox config saved!",
|
||||
"soapbox_config.single_user_mode_hint": "Front page will redirect to a given user profile.",
|
||||
"soapbox_config.saved": "Soapbox-Konfiruation gespeichert!",
|
||||
"soapbox_config.single_user_mode_hint": "Startseite leitet zum Nutzerprofil weiter.",
|
||||
"soapbox_config.single_user_mode_label": "Single user mode",
|
||||
"soapbox_config.single_user_mode_profile_hint": "@handle",
|
||||
"soapbox_config.single_user_mode_profile_label": "Main user handle",
|
||||
"soapbox_config.verified_can_edit_name_label": "Allow verified users to edit their own display name.",
|
||||
"status.actions.more": "More",
|
||||
"soapbox_config.verified_can_edit_name_label": "Verifizierten Nutzern die Änderung des Anzeigenamens gestatten.",
|
||||
"status.actions.more": "Weitere Einstellungen",
|
||||
"status.admin_account": "Öffne Moderationsoberfläche für @{name}",
|
||||
"status.admin_status": "Öffne Beitrag in der Moderationsoberfläche",
|
||||
"status.block": "@{name} blockieren",
|
||||
|
@ -989,13 +989,13 @@
|
|||
"status.pin": "Im Profil anheften",
|
||||
"status.pinned": "Angehefteter Beitrag",
|
||||
"status.quote": "Beitrag zitieren",
|
||||
"status.reactions.cry": "Sad",
|
||||
"status.reactions.cry": "Traurig",
|
||||
"status.reactions.empty": "No one has reacted to this post yet. When someone does, they will show up here.",
|
||||
"status.reactions.heart": "Love",
|
||||
"status.reactions.heart": "Liebe",
|
||||
"status.reactions.laughing": "Haha",
|
||||
"status.reactions.like": "Like",
|
||||
"status.reactions.open_mouth": "Wow",
|
||||
"status.reactions.weary": "Weary",
|
||||
"status.reactions.weary": "Überdrüssig",
|
||||
"status.reactions_expand": "Emoji auswählen",
|
||||
"status.read_more": "Mehr lesen",
|
||||
"status.reblog": "Teilen",
|
||||
|
|
|
@ -197,7 +197,7 @@ describe('normalizeInstance()', () => {
|
|||
const instance = require('soapbox/__fixtures__/akkoma-instance.json');
|
||||
const result = normalizeInstance(instance);
|
||||
|
||||
expect(result.version).toEqual('2.7.2 (compatible; Pleroma 2.4.5+akkoma)');
|
||||
expect(result.version).toEqual('2.7.2 (compatible; Pleroma 2.4.50+akkoma)');
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -103,7 +103,7 @@ const fixAkkoma = (instance: ImmutableMap<string, any>) => {
|
|||
const version: string = instance.get('version', '');
|
||||
|
||||
if (version.includes('Akkoma')) {
|
||||
return instance.set('version', '2.7.2 (compatible; Pleroma 2.4.5+akkoma)');
|
||||
return instance.set('version', '2.7.2 (compatible; Pleroma 2.4.50+akkoma)');
|
||||
} else {
|
||||
return instance;
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -533,7 +533,7 @@ const getInstanceFeatures = (instance: Instance) => {
|
|||
* @see POST /api/v1/statuses
|
||||
*/
|
||||
quotePosts: any([
|
||||
v.software === PLEROMA && v.build === SOAPBOX && gte(v.version, '2.4.50'),
|
||||
v.software === PLEROMA && [SOAPBOX, AKKOMA].includes(v.build!) && gte(v.version, '2.4.50'),
|
||||
instance.feature_quote === true,
|
||||
]),
|
||||
|
||||
|
|
18
package.json
18
package.json
|
@ -56,17 +56,17 @@
|
|||
"@lcdp/offline-plugin": "^5.1.0",
|
||||
"@metamask/providers": "^9.0.0",
|
||||
"@popperjs/core": "^2.11.5",
|
||||
"@reach/menu-button": "^0.16.2",
|
||||
"@reach/popover": "^0.16.2",
|
||||
"@reach/portal": "^0.16.2",
|
||||
"@reach/rect": "^0.16.0",
|
||||
"@reach/tabs": "^0.16.4",
|
||||
"@reach/tooltip": "^0.16.2",
|
||||
"@reach/menu-button": "^0.18.0",
|
||||
"@reach/popover": "^0.18.0",
|
||||
"@reach/portal": "^0.18.0",
|
||||
"@reach/rect": "^0.18.0",
|
||||
"@reach/tabs": "^0.18.0",
|
||||
"@reach/tooltip": "^0.18.0",
|
||||
"@reduxjs/toolkit": "^1.8.1",
|
||||
"@sentry/browser": "^7.11.1",
|
||||
"@sentry/react": "^7.11.1",
|
||||
"@sentry/tracing": "^7.11.1",
|
||||
"@tabler/icons": "^1.109.0",
|
||||
"@tabler/icons": "^1.111.0",
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"@tailwindcss/typography": "^0.5.7",
|
||||
"@tanstack/react-query": "^4.0.10",
|
||||
|
@ -173,13 +173,13 @@
|
|||
"react-redux": "^7.2.5",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-router-scroll-4": "^1.0.0-beta.2",
|
||||
"react-simple-pull-to-refresh": "^1.3.0",
|
||||
"react-simple-pull-to-refresh": "^1.3.3",
|
||||
"react-sparklines": "^1.7.0",
|
||||
"react-sticky-box": "^1.0.2",
|
||||
"react-swipeable-views": "^0.14.0",
|
||||
"react-textarea-autosize": "^8.3.4",
|
||||
"react-toggle": "^4.1.2",
|
||||
"react-virtuoso": "^2.19.1",
|
||||
"react-virtuoso": "^3.1.3",
|
||||
"redux": "^4.1.1",
|
||||
"redux-immutable": "^4.0.0",
|
||||
"redux-thunk": "^2.2.0",
|
||||
|
|
203
yarn.lock
203
yarn.lock
|
@ -2048,121 +2048,110 @@
|
|||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.1.tgz#728ecd95ab207aab8a9a4e421f0422db329232be"
|
||||
integrity sha512-HnUhk1Sy9IuKrxEMdIRCxpIqPw6BFsbYSEUO9p/hNw5sMld/+3OLMWQP80F8/db9qsv3qUjs7ZR5bS/R+iinXw==
|
||||
|
||||
"@reach/auto-id@0.16.0":
|
||||
version "0.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.16.0.tgz#dfabc3227844e8c04f8e6e45203a8e14a8edbaed"
|
||||
integrity sha512-5ssbeP5bCkM39uVsfQCwBBL+KT8YColdnMN5/Eto6Rj7929ql95R3HZUOkKIvj7mgPtEb60BLQxd1P3o6cjbmg==
|
||||
"@reach/auto-id@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.18.0.tgz#4b97085cd1cf1360a9bedc6e9c78e97824014f0d"
|
||||
integrity sha512-XwY1IwhM7mkHZFghhjiqjQ6dstbOdpbFLdggeke75u8/8icT8uEHLbovFUgzKjy9qPvYwZIB87rLiR8WdtOXCg==
|
||||
dependencies:
|
||||
"@reach/utils" "0.16.0"
|
||||
tslib "^2.3.0"
|
||||
"@reach/utils" "0.18.0"
|
||||
|
||||
"@reach/descendants@0.16.1":
|
||||
version "0.16.1"
|
||||
resolved "https://registry.yarnpkg.com/@reach/descendants/-/descendants-0.16.1.tgz#fa3d89c0503565369707f32985d87eef61985d9f"
|
||||
integrity sha512-3WZgRnD9O4EORKE31rrduJDiPFNMOjUkATx0zl192ZxMq3qITe4tUj70pS5IbJl/+v9zk78JwyQLvA1pL7XAPA==
|
||||
"@reach/descendants@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/descendants/-/descendants-0.18.0.tgz#16fe52a5154da262994b0b8768baff4f670922d1"
|
||||
integrity sha512-GXUxnM6CfrX5URdnipPIl3Tlc6geuz4xb4n61y4tVWXQX1278Ra9Jz9DMRN8x4wheHAysvrYwnR/SzAlxQzwtA==
|
||||
dependencies:
|
||||
"@reach/utils" "0.16.0"
|
||||
tslib "^2.3.0"
|
||||
"@reach/utils" "0.18.0"
|
||||
|
||||
"@reach/dropdown@0.16.2":
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/dropdown/-/dropdown-0.16.2.tgz#4aa7df0f716cb448d01bc020d54df595303d5fa6"
|
||||
integrity sha512-l4nNiX6iUpMdHQNbZMhgW5APtw0AUwJuRnkqE93vkjvdtrYl/sNJy1Jr6cGG7TrZIABLSOsfwbXU3C+qwJ3ftQ==
|
||||
"@reach/dropdown@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/dropdown/-/dropdown-0.18.0.tgz#c2e2e99df682f2136558851b80dc05b4f9dd92a5"
|
||||
integrity sha512-LriXdVgxJoUhIQfS2r2DHYv3X6fHyplYxa9FmSwQIMXdESpE/P9Zsb1pVEObcNf3ZQBrl0L1bl/5rk7SpK7qfA==
|
||||
dependencies:
|
||||
"@reach/auto-id" "0.16.0"
|
||||
"@reach/descendants" "0.16.1"
|
||||
"@reach/popover" "0.16.2"
|
||||
"@reach/utils" "0.16.0"
|
||||
tslib "^2.3.0"
|
||||
"@reach/auto-id" "0.18.0"
|
||||
"@reach/descendants" "0.18.0"
|
||||
"@reach/polymorphic" "0.18.0"
|
||||
"@reach/popover" "0.18.0"
|
||||
"@reach/utils" "0.18.0"
|
||||
|
||||
"@reach/menu-button@^0.16.2":
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/menu-button/-/menu-button-0.16.2.tgz#664e33e70de431f88abf1f8537c48b1b6ce87e88"
|
||||
integrity sha512-p4n6tFVaJZHJZEznHWy0YH2Xr3I+W7tsQWAT72PqKGT+uryGRdtgEQqi76f/8cRaw/00ueazBk5lwLG7UKGFaA==
|
||||
"@reach/menu-button@^0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/menu-button/-/menu-button-0.18.0.tgz#ae40dc86e47e7f925599ca720e3ba65263cc56f3"
|
||||
integrity sha512-v1lj5rYSpavOKI4ipXj8OfvQmvVNAYXCv+UcltRkjOcWEKWADUUKkGX55wiUhsCsTGCJ7lGYz5LqOZrn3LP6PQ==
|
||||
dependencies:
|
||||
"@reach/dropdown" "0.16.2"
|
||||
"@reach/popover" "0.16.2"
|
||||
"@reach/utils" "0.16.0"
|
||||
prop-types "^15.7.2"
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
"@reach/dropdown" "0.18.0"
|
||||
"@reach/polymorphic" "0.18.0"
|
||||
"@reach/popover" "0.18.0"
|
||||
"@reach/utils" "0.18.0"
|
||||
|
||||
"@reach/observe-rect@1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.2.0.tgz#d7a6013b8aafcc64c778a0ccb83355a11204d3b2"
|
||||
integrity sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ==
|
||||
|
||||
"@reach/popover@0.16.2", "@reach/popover@^0.16.2":
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/popover/-/popover-0.16.2.tgz#71d7af3002ca49d791476b22dee1840dd1719c19"
|
||||
integrity sha512-IwkRrHM7Vt33BEkSXneovymJv7oIToOfTDwRKpuYEB/BWYMAuNfbsRL7KVe6MjkgchDeQzAk24cYY1ztQj5HQQ==
|
||||
dependencies:
|
||||
"@reach/portal" "0.16.2"
|
||||
"@reach/rect" "0.16.0"
|
||||
"@reach/utils" "0.16.0"
|
||||
tabbable "^4.0.0"
|
||||
tslib "^2.3.0"
|
||||
"@reach/polymorphic@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/polymorphic/-/polymorphic-0.18.0.tgz#2fe42007a774e06cdbc8e13e0d46f2dc30f2f1ed"
|
||||
integrity sha512-N9iAjdMbE//6rryZZxAPLRorzDcGBnluf7YQij6XDLiMtfCj1noa7KyLpEc/5XCIB/EwhX3zCluFAwloBKdblA==
|
||||
|
||||
"@reach/portal@0.16.2", "@reach/portal@^0.16.2":
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.16.2.tgz#ca83696215ee03acc2bb25a5ae5d8793eaaf2f64"
|
||||
integrity sha512-9ur/yxNkuVYTIjAcfi46LdKUvH0uYZPfEp4usWcpt6PIp+WDF57F/5deMe/uGi/B/nfDweQu8VVwuMVrCb97JQ==
|
||||
"@reach/popover@0.18.0", "@reach/popover@^0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/popover/-/popover-0.18.0.tgz#1eba3e9ed826ac69dfdf3b01a1dab15ca889b5fc"
|
||||
integrity sha512-mpnWWn4w74L2U7fcneVdA6Fz3yKWNdZIRMoK8s6H7F8U2dLM/qN7AjzjEBqi6LXKb3Uf1ge4KHSbMixW0BygJQ==
|
||||
dependencies:
|
||||
"@reach/utils" "0.16.0"
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
"@reach/polymorphic" "0.18.0"
|
||||
"@reach/portal" "0.18.0"
|
||||
"@reach/rect" "0.18.0"
|
||||
"@reach/utils" "0.18.0"
|
||||
tabbable "^5.3.3"
|
||||
|
||||
"@reach/rect@0.16.0", "@reach/rect@^0.16.0":
|
||||
version "0.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.16.0.tgz#78cf6acefe2e83d3957fa84f938f6e1fc5700f16"
|
||||
integrity sha512-/qO9jQDzpOCdrSxVPR6l674mRHNTqfEjkaxZHluwJ/2qGUtYsA0GSZiF/+wX/yOWeBif1ycxJDa6HusAMJZC5Q==
|
||||
"@reach/portal@0.18.0", "@reach/portal@^0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.18.0.tgz#dd466f5110689d14a0e7491b3aa8a449e8cefb40"
|
||||
integrity sha512-TImozRapd576ofRk30Le2L3lRTFXF1p47B182wnp5eMTdZa74JX138BtNGEPJFOyrMaVmguVF8SSwZ6a0fon1Q==
|
||||
dependencies:
|
||||
"@reach/utils" "0.18.0"
|
||||
|
||||
"@reach/rect@0.18.0", "@reach/rect@^0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.18.0.tgz#d1dc45adc92f80cc54b64498e19de909ced40722"
|
||||
integrity sha512-Xk8urN4NLn3F70da/DtByMow83qO6DF6vOxpLjuDBqud+kjKgxAU9vZMBSZJyH37+F8mZinRnHyXtlLn5njQOg==
|
||||
dependencies:
|
||||
"@reach/observe-rect" "1.2.0"
|
||||
"@reach/utils" "0.16.0"
|
||||
prop-types "^15.7.2"
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
"@reach/utils" "0.18.0"
|
||||
|
||||
"@reach/tabs@^0.16.4":
|
||||
version "0.16.4"
|
||||
resolved "https://registry.yarnpkg.com/@reach/tabs/-/tabs-0.16.4.tgz#7da85e46f64052bdd1c0f9582f900e379b098ac5"
|
||||
integrity sha512-4EK+1U0OoLfg2tJ1BSZf6/tx0hF5vlXKxY7qB//bPWtlIh9Xfp/aSDIdspFf3xS8MjtKeb6IVmo5UAxDMq85ZA==
|
||||
"@reach/tabs@^0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/tabs/-/tabs-0.18.0.tgz#f2e789d445d61a371eace9415841502729d099c9"
|
||||
integrity sha512-gTRJzStWJJtgMhn9FDEmKogAJMcqNaGZx0i1SGoTdVM+D29DBhVeRdO8qEg+I2l2k32DkmuZxG/Mrh+GZTjczQ==
|
||||
dependencies:
|
||||
"@reach/auto-id" "0.16.0"
|
||||
"@reach/descendants" "0.16.1"
|
||||
"@reach/utils" "0.16.0"
|
||||
prop-types "^15.7.2"
|
||||
tslib "^2.3.0"
|
||||
"@reach/auto-id" "0.18.0"
|
||||
"@reach/descendants" "0.18.0"
|
||||
"@reach/polymorphic" "0.18.0"
|
||||
"@reach/utils" "0.18.0"
|
||||
|
||||
"@reach/tooltip@^0.16.2":
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/tooltip/-/tooltip-0.16.2.tgz#8448cee341476e4f795fa7192f7a0864f06b8085"
|
||||
integrity sha512-wtJPnbJ6l4pmudMpQHGU9v1NS4ncDgcwRNi9re9KsIdsM525zccZvHQLteBKYiaW4ib7k09t2dbwhyNU9oa0Iw==
|
||||
"@reach/tooltip@^0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/tooltip/-/tooltip-0.18.0.tgz#6d416e77a82543af9a57d122962f9c0294fc2a5f"
|
||||
integrity sha512-yugoTmTjB3qoMk/nUvcnw99MqpyE2TQMOXE29qnQhSqHriRwQhfftjXlTAGTSzsUJmbyms3A/1gQW0X61kjFZw==
|
||||
dependencies:
|
||||
"@reach/auto-id" "0.16.0"
|
||||
"@reach/portal" "0.16.2"
|
||||
"@reach/rect" "0.16.0"
|
||||
"@reach/utils" "0.16.0"
|
||||
"@reach/visually-hidden" "0.16.0"
|
||||
prop-types "^15.7.2"
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
"@reach/auto-id" "0.18.0"
|
||||
"@reach/polymorphic" "0.18.0"
|
||||
"@reach/portal" "0.18.0"
|
||||
"@reach/rect" "0.18.0"
|
||||
"@reach/utils" "0.18.0"
|
||||
"@reach/visually-hidden" "0.18.0"
|
||||
|
||||
"@reach/utils@0.16.0":
|
||||
version "0.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.16.0.tgz#5b0777cf16a7cab1ddd4728d5d02762df0ba84ce"
|
||||
integrity sha512-PCggBet3qaQmwFNcmQ/GqHSefadAFyNCUekq9RrWoaU9hh/S4iaFgf2MBMdM47eQj5i/Bk0Mm07cP/XPFlkN+Q==
|
||||
dependencies:
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
"@reach/utils@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.18.0.tgz#4f3cebe093dd436eeaff633809bf0f68f4f9d2ee"
|
||||
integrity sha512-KdVMdpTgDyK8FzdKO9SCpiibuy/kbv3pwgfXshTI6tEcQT1OOwj7BAksnzGC0rPz0UholwC+AgkqEl3EJX3M1A==
|
||||
|
||||
"@reach/visually-hidden@0.16.0":
|
||||
version "0.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.16.0.tgz#2a5e834af9e93c554065ff8cbb0907fbeb26ad02"
|
||||
integrity sha512-IIayZ3jzJtI5KfcfRVtOMFkw2ef/1dMT8D9BUuFcU2ORZAWLNvnzj1oXNoIfABKl5wtsLjY6SGmkYQ+tMPN8TA==
|
||||
"@reach/visually-hidden@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.18.0.tgz#17923c08acc5946624c2836b2b09d359b3aa8c27"
|
||||
integrity sha512-NsJ3oeHJtPc6UOeV6MHMuzQ5sl1ouKhW85i3C0S7VM+klxVlYScBZ2J4UVnWB50A2c+evdVpCnld2YeuyYYwBw==
|
||||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
tslib "^2.3.0"
|
||||
"@reach/polymorphic" "0.18.0"
|
||||
|
||||
"@reduxjs/toolkit@^1.8.1":
|
||||
version "1.8.1"
|
||||
|
@ -2271,10 +2260,10 @@
|
|||
remark "^13.0.0"
|
||||
unist-util-find-all-after "^3.0.2"
|
||||
|
||||
"@tabler/icons@^1.109.0":
|
||||
version "1.109.0"
|
||||
resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-1.109.0.tgz#11626c3fc097f2f70c4c197e4b9909fb05380752"
|
||||
integrity sha512-B0YetE4pB6HY2Wa57v/LJ3NgkJzKYPze4U0DurIqPoKSptatKv2ga76FZSkO6EUpkYfHMtGPM6QjpJljfuCmAQ==
|
||||
"@tabler/icons@^1.111.0":
|
||||
version "1.111.0"
|
||||
resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-1.111.0.tgz#0538fdd8b5de7072ae60fc5d2f13a9a636d2d0e3"
|
||||
integrity sha512-TZWYiMT5ccqfHxRE0Qtgvl+sGsMbNkrv7cJMt/tm8TN9l/CDXx/o7d8uAwUN+3PAlSFfF5e/rD1bi1WJs2xNIA==
|
||||
|
||||
"@tailwindcss/forms@^0.5.3":
|
||||
version "0.5.3"
|
||||
|
@ -10021,10 +10010,10 @@ react-side-effect@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.1.tgz#66c5701c3e7560ab4822a4ee2742dee215d72eb3"
|
||||
integrity sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==
|
||||
|
||||
react-simple-pull-to-refresh@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-simple-pull-to-refresh/-/react-simple-pull-to-refresh-1.3.0.tgz#5f7bcd475ea5c33ecd505d097b14f56c3e5e3ce8"
|
||||
integrity sha512-QPFGFsbroh2WoTcLCh3f6peMRfSettYJKCXMS9FNbFav7GWKD2whqACiNLx+Mi+VkP/I+aerB7kEirk+DQx41A==
|
||||
react-simple-pull-to-refresh@^1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/react-simple-pull-to-refresh/-/react-simple-pull-to-refresh-1.3.3.tgz#118afe0d8ba6cade87094786b3889fb2ffd5b9bc"
|
||||
integrity sha512-6qXsa5RtNVmKJhLWvDLIX8UK51HFtCEGjdqQGf+M1Qjrcc4qH4fki97sgVpGEFBRwbY7DiVDA5N5p97kF16DTw==
|
||||
|
||||
react-sparklines@^1.7.0:
|
||||
version "1.7.0"
|
||||
|
@ -10097,10 +10086,10 @@ react-transition-group@^2.2.1:
|
|||
prop-types "^15.6.2"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
|
||||
react-virtuoso@^2.19.1:
|
||||
version "2.19.1"
|
||||
resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-2.19.1.tgz#a660a5c3cafcc7a84b59dfc356e1916e632c1e3a"
|
||||
integrity sha512-zF6MAwujNGy2nJWCx/Df92ay/RnV2Kj4glUZfdyadI4suAn0kAZHB1BeI7yPFVp2iSccLzFlszhakWyr+fJ4Dw==
|
||||
react-virtuoso@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-3.1.3.tgz#db811ff6fdd4749cfe9348f6d0b1333a348e65c4"
|
||||
integrity sha512-sc4WICEZkyT+XdVc7gA/61UT43ZnMSX0ugh+xBG2cX+EDWs31wP1dSKQ2HSQ0YFLhZXRJ+Jqndqa8MTu4NE4CQ==
|
||||
dependencies:
|
||||
"@virtuoso.dev/react-urx" "^0.2.12"
|
||||
"@virtuoso.dev/urx" "^0.2.12"
|
||||
|
@ -11329,10 +11318,10 @@ symbol-tree@^3.2.4:
|
|||
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
|
||||
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
|
||||
|
||||
tabbable@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-4.0.0.tgz#5bff1d1135df1482cf0f0206434f15eadbeb9261"
|
||||
integrity sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ==
|
||||
tabbable@^5.3.3:
|
||||
version "5.3.3"
|
||||
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-5.3.3.tgz#aac0ff88c73b22d6c3c5a50b1586310006b47fbf"
|
||||
integrity sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==
|
||||
|
||||
table@^6.0.9, table@^6.6.0:
|
||||
version "6.7.1"
|
||||
|
@ -11608,7 +11597,7 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
|||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.3.1:
|
||||
tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
||||
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
|
||||
|
|
Loading…
Reference in a new issue