Merge remote-tracking branch 'origin/develop' into use-instance

environments/review-use-instan-qjj6sf/deployments/1586
Alex Gleason 2022-11-27 16:42:06 -06:00
commit ed573bfeb2
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
18 zmienionych plików z 364 dodań i 379 usunięć

Wyświetl plik

@ -63,9 +63,9 @@
@apply w-5 h-5;
}
/* Markdown images */
[data-markup] img:not(.emojione):not([width][height]) {
@apply w-full h-72 object-contain rounded-lg overflow-hidden my-4 block;
/* Hide Markdown images (Pleroma) */
[data-markup] img:not(.emojione) {
@apply hidden;
}
/* User setting to underline links */

Wyświetl plik

@ -106,7 +106,7 @@ export const ProfileHoverCard: React.FC<IProfileHoverCard> = ({ visible = true }
onMouseEnter={handleMouseEnter(dispatch)}
onMouseLeave={handleMouseLeave(dispatch)}
>
<Card variant='rounded' className='relative'>
<Card variant='rounded' className='relative isolate'>
<CardBody>
<Stack space={2}>
<BundleContainer fetchComponent={UserPanel}>

Wyświetl plik

@ -33,7 +33,7 @@ const Card = React.forwardRef<HTMLDivElement, ICard>(({ children, variant = 'def
ref={ref}
{...filteredProps}
className={classNames({
'bg-white dark:bg-primary-900 text-gray-900 dark:text-gray-100 shadow-lg dark:shadow-none overflow-hidden isolate': variant === 'rounded',
'bg-white dark:bg-primary-900 text-gray-900 dark:text-gray-100 shadow-lg dark:shadow-none overflow-hidden': variant === 'rounded',
[sizes[size]]: variant === 'rounded',
}, className)}
>

Wyświetl plik

@ -47,8 +47,7 @@ const EmojiSelector: React.FC<IEmojiSelector> = ({ emojis, onReact, visible = fa
return (
<HStack
space={2}
className={classNames('bg-white dark:bg-gray-900 p-3 rounded-full shadow-md z-[999] w-max')}
className={classNames('gap-2 bg-white dark:bg-gray-900 p-3 rounded-full shadow-md z-[999] w-max max-w-[100vw] flex-wrap')}
>
{Array.from(emojis).map((emoji, i) => (
<EmojiButton

Wyświetl plik

@ -35,29 +35,29 @@ const Chat: React.FC<IChat> = ({ chatId, onClick }) => {
<button className='floating-link' onClick={() => onClick(chat)} />
<HStack key={account.id} space={3} className='relative overflow-hidden'>
<Avatar className='flex-none' src={account.avatar} size={36} />
<Stack className='overflow-hidden'>
<Stack className='overflow-hidden flex-1'>
<DisplayName account={account} withSuffix={false} />
{attachment && (
<Icon
className='chat__attachment-icon'
src={image ? require('@tabler/icons/photo.svg') : require('@tabler/icons/paperclip.svg')}
/>
)}
{content ? (
<Text
theme='muted'
size='sm'
className='chat__last-message'
dangerouslySetInnerHTML={{ __html: parsedContent }}
truncate
/>
) : attachment && (
<span
className='chat__last-message attachment'
>
{image ? <FormattedMessage id='chats.attachment_image' defaultMessage='Image' /> : <FormattedMessage id='chats.attachment' defaultMessage='Attachment' />}
</span>
)}
<HStack space={1} justifyContent='between'>
{content ? (
<Text
theme='muted'
size='sm'
className='max-h-5'
dangerouslySetInnerHTML={{ __html: parsedContent }}
truncate
/>
) : attachment && (
<Text theme='muted' size='sm' className='italic'>
{image ? <FormattedMessage id='chats.attachment_image' defaultMessage='Image' /> : <FormattedMessage id='chats.attachment' defaultMessage='Attachment' />}
</Text>
)}
{attachment && (
<Icon
className='chat__attachment-icon'
src={image ? require('@tabler/icons/photo.svg') : require('@tabler/icons/paperclip.svg')}
/>
)}
</HStack>
{unreadCount > 0 && (
<div className='absolute top-1 right-0'>
<Counter count={unreadCount} />

Wyświetl plik

@ -5,14 +5,13 @@ import { directComposeById } from 'soapbox/actions/compose';
import { connectDirectStream } from 'soapbox/actions/streaming';
import { expandDirectTimeline } from 'soapbox/actions/timelines';
import AccountSearch from 'soapbox/components/account-search';
import ColumnHeader from 'soapbox/components/column-header';
import { Column } from 'soapbox/components/ui';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { useAppDispatch } from 'soapbox/hooks';
import Timeline from '../ui/components/timeline';
const messages = defineMessages({
title: { id: 'column.direct', defaultMessage: 'Direct messages' },
heading: { id: 'column.direct', defaultMessage: 'Direct messages' },
searchPlaceholder: { id: 'direct.search_placeholder', defaultMessage: 'Send a message to…' },
});
@ -20,8 +19,6 @@ const DirectTimeline = () => {
const intl = useIntl();
const dispatch = useAppDispatch();
const hasUnread = useAppSelector((state) => (state.timelines.get('direct')?.unread || 0) > 0);
useEffect(() => {
dispatch(expandDirectTimeline());
const disconnect = dispatch(connectDirectStream());
@ -40,13 +37,7 @@ const DirectTimeline = () => {
};
return (
<Column label={intl.formatMessage(messages.title)} transparent withHeader={false}>
<ColumnHeader
icon='envelope'
active={hasUnread}
title={intl.formatMessage(messages.title)}
/>
<Column label={intl.formatMessage(messages.heading)}>
<AccountSearch
placeholder={intl.formatMessage(messages.searchPlaceholder)}
onSelected={handleSuggestion}
@ -57,7 +48,7 @@ const DirectTimeline = () => {
timelineId='direct'
onLoadMore={handleLoadMore}
emptyMessage={<FormattedMessage id='empty_column.direct' defaultMessage="You don't have any direct messages yet. When you send or receive one, it will show up here." />}
divideType='space'
divideType='border'
/>
</Column>
);

Wyświetl plik

@ -4,7 +4,7 @@ import React from 'react';
import { FormattedMessage } from 'react-intl';
import Icon from 'soapbox/components/icon';
import { Text } from 'soapbox/components/ui';
import { HStack, Stack, Text } from 'soapbox/components/ui';
import { useInstance } from 'soapbox/hooks';
import type { Map as ImmutableMap } from 'immutable';
@ -16,6 +16,23 @@ const hasRestrictions = (remoteInstance: ImmutableMap<string, any>): boolean =>
.reduce((acc: boolean, value: boolean) => acc || value, false);
};
interface IRestriction {
icon: string,
children: React.ReactNode,
}
const Restriction: React.FC<IRestriction> = ({ icon, children }) => {
return (
<HStack space={3}>
<Icon className='flex-none w-5 h-5' src={icon} />
<Text theme='muted'>
{children}
</Text>
</HStack>
);
};
interface IInstanceRestrictions {
remoteInstance: ImmutableMap<string, any>,
}
@ -40,57 +57,52 @@ const InstanceRestrictions: React.FC<IInstanceRestrictions> = ({ remoteInstance
if (followers_only) {
items.push((
<Text key='followers_only' className='flex items-center gap-2' theme='muted'>
<Icon src={require('@tabler/icons/lock.svg')} />
<Restriction key='followersOnly' icon={require('@tabler/icons/lock.svg')}>
<FormattedMessage
id='federation_restriction.followers_only'
defaultMessage='Hidden except to followers'
/>
</Text>
</Restriction>
));
} else if (federated_timeline_removal) {
items.push((
<Text key='federated_timeline_removal' className='flex items-center gap-2' theme='muted'>
<Icon src={require('@tabler/icons/lock-open.svg')} />
<Restriction key='federatedTimelineRemoval' icon={require('@tabler/icons/lock-open.svg')}>
<FormattedMessage
id='federation_restriction.federated_timeline_removal'
defaultMessage='Fediverse timeline removal'
/>
</Text>
</Restriction>
));
}
if (fullMediaRemoval) {
items.push((
<Text key='full_media_removal' className='flex items-center gap-2' theme='muted'>
<Icon src={require('@tabler/icons/photo-off.svg')} />
<Restriction key='fullMediaRemoval' icon={require('@tabler/icons/photo-off.svg')}>
<FormattedMessage
id='federation_restriction.full_media_removal'
defaultMessage='Full media removal'
/>
</Text>
</Restriction>
));
} else if (partialMediaRemoval) {
items.push((
<Text key='partial_media_removal' className='flex items-center gap-2' theme='muted'>
<Icon src={require('@tabler/icons/photo-off.svg')} />
<Restriction key='partialMediaRemoval' icon={require('@tabler/icons/photo-off.svg')}>
<FormattedMessage
id='federation_restriction.partial_media_removal'
defaultMessage='Partial media removal'
/>
</Text>
</Restriction>
));
}
if (!fullMediaRemoval && media_nsfw) {
items.push((
<Text key='media_nsfw' className='flex items-center gap-2' theme='muted'>
<Icon src={require('@tabler/icons/eye-off.svg')} />
<Restriction key='mediaNsfw' icon={require('@tabler/icons/eye-off.svg')}>
<FormattedMessage
id='federation_restriction.media_nsfw'
defaultMessage='Attachments marked NSFW'
/>
</Text>
</Restriction>
));
}
@ -105,46 +117,45 @@ const InstanceRestrictions: React.FC<IInstanceRestrictions> = ({ remoteInstance
if (remoteInstance.getIn(['federation', 'reject']) === true) {
return (
<Text className='flex items-center gap-2' theme='muted'>
<Icon src={require('@tabler/icons/x.svg')} />
<Restriction icon={require('@tabler/icons/shield-x.svg')}>
<FormattedMessage
id='remote_instance.federation_panel.restricted_message'
defaultMessage='{siteTitle} blocks all activities from {host}.'
values={{ host, siteTitle }}
/>
</Text>
</Restriction>
);
} else if (hasRestrictions(remoteInstance)) {
return [
(
<Text theme='muted'>
return (
<>
<Restriction icon={require('@tabler/icons/shield-lock.svg')}>
<FormattedMessage
id='remote_instance.federation_panel.some_restrictions_message'
defaultMessage='{siteTitle} has placed some restrictions on {host}.'
values={{ host, siteTitle }}
/>
</Text>
),
renderRestrictions(),
];
</Restriction>
{renderRestrictions()}
</>
);
} else {
return (
<Text className='flex items-center gap-2' theme='muted'>
<Icon src={require('@tabler/icons/check.svg')} />
<Restriction icon={require('@tabler/icons/shield-check.svg')}>
<FormattedMessage
id='remote_instance.federation_panel.no_restrictions_message'
defaultMessage='{siteTitle} has placed no restrictions on {host}.'
values={{ host, siteTitle }}
/>
</Text>
</Restriction>
);
}
};
return (
<div className='py-1 pl-4 mb-4 border-solid border-l-[3px] border-gray-300 dark:border-gray-500'>
<Stack space={3}>
{renderContent()}
</div>
</Stack>
);
};

Wyświetl plik

@ -1,5 +1,7 @@
import React from 'react';
import { HStack, Stack } from 'soapbox/components/ui';
import { randomIntFromInterval, generateText } from '../utils';
import PlaceholderAvatar from './placeholder-avatar';
@ -10,20 +12,16 @@ const PlaceholderChat: React.FC = () => {
const messageLength = randomIntFromInterval(5, 75);
return (
<div className='chat-list-item chat-list-item--placeholder'>
<div className='account'>
<div className='account__wrapper'>
<div className='account__display-name'>
<div className='account__avatar-wrapper'>
<PlaceholderAvatar size={36} />
</div>
<PlaceholderDisplayName minLength={3} maxLength={25} />
<span className='chat__last-message'>
{generateText(messageLength)}
</span>
</div>
</div>
</div>
<div className='account chat-list-item--placeholder'>
<HStack space={3}>
<PlaceholderAvatar size={36} />
<Stack className='overflow-hidden'>
<PlaceholderDisplayName minLength={3} maxLength={25} withSuffix={false} />
<span className='overflow-hidden text-ellipsis whitespace-nowrap text-primary-50 dark:text-primary-800'>
{generateText(messageLength)}
</span>
</Stack>
</HStack>
</div>
);
};

Wyświetl plik

@ -5,17 +5,18 @@ import { randomIntFromInterval, generateText } from '../utils';
interface IPlaceholderDisplayName {
maxLength: number,
minLength: number,
withSuffix?: boolean,
}
/** Fake display name to show when data is loading. */
const PlaceholderDisplayName: React.FC<IPlaceholderDisplayName> = ({ minLength, maxLength }) => {
const PlaceholderDisplayName: React.FC<IPlaceholderDisplayName> = ({ minLength, maxLength, withSuffix = true }) => {
const length = randomIntFromInterval(maxLength, minLength);
const acctLength = randomIntFromInterval(maxLength, minLength);
return (
<div className='flex flex-col text-primary-50 dark:text-primary-800'>
<p>{generateText(length)}</p>
<p>{generateText(acctLength)}</p>
{withSuffix && <p>{generateText(acctLength)}</p>}
</div>
);
};

Wyświetl plik

@ -5,8 +5,8 @@ import { useHistory } from 'react-router-dom';
import { connectRemoteStream } from 'soapbox/actions/streaming';
import { expandRemoteTimeline } from 'soapbox/actions/timelines';
import IconButton from 'soapbox/components/icon-button';
import { HStack, Text } from 'soapbox/components/ui';
import Column from 'soapbox/features/ui/components/column';
import SubNavigation from 'soapbox/components/sub-navigation';
import { Column, HStack, Text } from 'soapbox/components/ui';
import { useAppDispatch, useSettings } from 'soapbox/hooks';
import Timeline from '../ui/components/timeline';
@ -14,7 +14,7 @@ import Timeline from '../ui/components/timeline';
import PinnedHostsPicker from './components/pinned-hosts-picker';
const messages = defineMessages({
title: { id: 'column.remote', defaultMessage: 'Federated timeline' },
heading: { id: 'column.remote', defaultMessage: 'Federated timeline' },
});
interface IRemoteTimeline {
@ -65,18 +65,26 @@ const RemoteTimeline: React.FC<IRemoteTimeline> = ({ params }) => {
}, [onlyMedia]);
return (
<Column label={intl.formatMessage(messages.title)} heading={instance} transparent withHeader={false}>
{instance && <PinnedHostsPicker host={instance} />}
{!pinned && <HStack className='mb-4 px-2' space={2}>
<IconButton iconClassName='h-5 w-5' src={require('@tabler/icons/x.svg')} onClick={handleCloseClick} />
<Text>
<FormattedMessage
id='remote_timeline.filter_message'
defaultMessage='You are viewing the timeline of {instance}.'
values={{ instance }}
/>
</Text>
</HStack>}
<Column label={intl.formatMessage(messages.heading)} transparent withHeader={false}>
<div className='px-4 pt-4 sm:p-0'>
<SubNavigation message={instance} />
{instance && <PinnedHostsPicker host={instance} />}
{!pinned && (
<HStack className='mb-4 px-2' space={2}>
<IconButton iconClassName='h-5 w-5' src={require('@tabler/icons/x.svg')} onClick={handleCloseClick} />
<Text>
<FormattedMessage
id='remote_timeline.filter_message'
defaultMessage='You are viewing the timeline of {instance}.'
values={{ instance }}
/>
</Text>
</HStack>
)}
</div>
<Timeline
scrollKey={`${timelineId}_${instance}_timeline`}
timelineId={`${timelineId}${onlyMedia ? ':media' : ''}:${instance}`}

Wyświetl plik

@ -1,17 +1,15 @@
import { Map as ImmutableMap } from 'immutable';
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import Toggle from 'react-toggle';
import { updateMrf } from 'soapbox/actions/mrf';
import snackbar from 'soapbox/actions/snackbar';
import { HStack, Modal, Stack, Text } from 'soapbox/components/ui';
import { SimpleForm } from 'soapbox/features/forms';
import List, { ListItem } from 'soapbox/components/list';
import { Modal } from 'soapbox/components/ui';
import { useAppSelector, useAppDispatch } from 'soapbox/hooks';
import { makeGetRemoteInstance } from 'soapbox/selectors';
const getRemoteInstance = makeGetRemoteInstance();
const messages = defineMessages({
mediaRemoval: { id: 'edit_federation.media_removal', defaultMessage: 'Strip media' },
forceNsfw: { id: 'edit_federation.force_nsfw', defaultMessage: 'Force attachments to be marked sensitive' },
@ -31,6 +29,7 @@ const EditFederationModal: React.FC<IEditFederationModal> = ({ host, onClose })
const intl = useIntl();
const dispatch = useAppDispatch();
const getRemoteInstance = useCallback(makeGetRemoteInstance(), []);
const remoteInstance = useAppSelector(state => getRemoteInstance(state, host));
const [data, setData] = useState(ImmutableMap<string, any>());
@ -82,74 +81,56 @@ const EditFederationModal: React.FC<IEditFederationModal> = ({ host, onClose })
confirmationAction={handleSubmit}
confirmationText={intl.formatMessage(messages.save)}
>
<SimpleForm onSubmit={handleSubmit}>
<Stack space={2}>
<HStack space={2} alignItems='center'>
<Toggle
checked={reject}
onChange={handleDataChange('reject')}
icons={false}
id='reject'
/>
<List>
<ListItem label={<FormattedMessage id='edit_federation.reject' defaultMessage='Reject all activities' />}>
<Toggle
checked={reject}
onChange={handleDataChange('reject')}
icons={false}
id='reject'
/>
</ListItem>
<Text theme='muted' tag='label' size='sm' htmlFor='reject'>
<FormattedMessage id='edit_federation.reject' defaultMessage='Reject all activities' />
</Text>
</HStack>
<HStack space={2} alignItems='center'>
<Toggle
checked={fullMediaRemoval}
onChange={handleMediaRemoval}
icons={false}
id='media_removal'
disabled={reject}
/>
<ListItem label={<FormattedMessage id='edit_federation.media_removal' defaultMessage='Strip media' />}>
<Toggle
checked={fullMediaRemoval}
onChange={handleMediaRemoval}
icons={false}
id='media_removal'
disabled={reject}
/>
</ListItem>
<Text theme='muted' tag='label' size='sm' htmlFor='media_removal'>
<FormattedMessage id='edit_federation.media_removal' defaultMessage='Strip media' />
</Text>
</HStack>
<HStack space={2} alignItems='center'>
<Toggle
checked={media_nsfw}
onChange={handleDataChange('media_nsfw')}
icons={false}
id='media_nsfw'
disabled={reject || media_removal}
/>
<ListItem label={<FormattedMessage id='edit_federation.force_nsfw' defaultMessage='Force attachments to be marked sensitive' />}>
<Toggle
checked={media_nsfw}
onChange={handleDataChange('media_nsfw')}
icons={false}
id='media_nsfw'
disabled={reject || media_removal}
/>
</ListItem>
<Text theme='muted' tag='label' size='sm' htmlFor='media_nsfw'>
<FormattedMessage id='edit_federation.force_nsfw' defaultMessage='Force attachments to be marked sensitive' />
</Text>
</HStack>
<HStack space={2} alignItems='center'>
<Toggle
checked={followers_only}
onChange={handleDataChange('followers_only')}
icons={false}
id='followers_only'
disabled={reject}
/>
<ListItem label={<FormattedMessage id='edit_federation.followers_only' defaultMessage='Hide posts except to followers' />}>
<Toggle
checked={followers_only}
onChange={handleDataChange('followers_only')}
icons={false}
id='followers_only'
disabled={reject}
/>
</ListItem>
<Text theme='muted' tag='label' size='sm' htmlFor='followers_only'>
<FormattedMessage id='edit_federation.followers_only' defaultMessage='Hide posts except to followers' />
</Text>
</HStack>
<HStack space={2} alignItems='center'>
<Toggle
checked={federated_timeline_removal}
onChange={handleDataChange('federated_timeline_removal')}
icons={false}
id='federated_timeline_removal'
disabled={reject || followers_only}
/>
<Text theme='muted' tag='label' size='sm' htmlFor='federated_timeline_removal'>
<FormattedMessage id='edit_federation.unlisted' defaultMessage='Force posts unlisted' />
</Text>
</HStack>
</Stack>
</SimpleForm>
<ListItem label={<FormattedMessage id='edit_federation.unlisted' defaultMessage='Force posts unlisted' />}>
<Toggle
checked={federated_timeline_removal}
onChange={handleDataChange('federated_timeline_removal')}
icons={false}
id='federated_timeline_removal'
disabled={reject || followers_only}
/>
</ListItem>
</List>
</Modal>
);
};

Wyświetl plik

@ -0,0 +1,73 @@
import classNames from 'clsx';
import React from 'react';
import { defineMessages, useIntl, FormatDateOptions } from 'react-intl';
import Markup from 'soapbox/components/markup';
import { HStack, Icon } from 'soapbox/components/ui';
import BundleContainer from 'soapbox/features/ui/containers/bundle-container';
import { CryptoAddress } from 'soapbox/features/ui/util/async-components';
import type { Field } from 'soapbox/types/entities';
const getTicker = (value: string): string => (value.match(/\$([a-zA-Z]*)/i) || [])[1];
const isTicker = (value: string): boolean => Boolean(getTicker(value));
const messages = defineMessages({
linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' },
});
const dateFormatOptions: FormatDateOptions = {
month: 'short',
day: 'numeric',
year: 'numeric',
hour12: true,
hour: 'numeric',
minute: '2-digit',
};
interface IProfileField {
field: Field,
}
/** Renders a single profile field. */
const ProfileField: React.FC<IProfileField> = ({ field }) => {
const intl = useIntl();
if (isTicker(field.name)) {
return (
<BundleContainer fetchComponent={CryptoAddress}>
{Component => (
<Component
ticker={getTicker(field.name).toLowerCase()}
address={field.value_plain}
/>
)}
</BundleContainer>
);
}
return (
<dl>
<dt title={field.name}>
<Markup weight='bold' tag='span' dangerouslySetInnerHTML={{ __html: field.name_emojified }} />
</dt>
<dd
className={classNames({ 'text-success-500': field.verified_at })}
title={field.value_plain}
>
<HStack space={2} alignItems='center'>
{field.verified_at && (
<span className='flex-none' title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(field.verified_at, dateFormatOptions) })}>
<Icon src={require('@tabler/icons/check.svg')} />
</span>
)}
<Markup className='break-words overflow-hidden' tag='span' dangerouslySetInnerHTML={{ __html: field.value_emojified }} />
</HStack>
</dd>
</dl>
);
};
export default ProfileField;

Wyświetl plik

@ -1,77 +1,11 @@
import classNames from 'clsx';
import React from 'react';
import { defineMessages, useIntl, FormattedMessage, FormatDateOptions } from 'react-intl';
import { FormattedMessage } from 'react-intl';
import Markup from 'soapbox/components/markup';
import { Widget, Stack, HStack, Icon } from 'soapbox/components/ui';
import BundleContainer from 'soapbox/features/ui/containers/bundle-container';
import { CryptoAddress } from 'soapbox/features/ui/util/async-components';
import { Widget, Stack } from 'soapbox/components/ui';
import type { Account, Field } from 'soapbox/types/entities';
import ProfileField from './profile-field';
const getTicker = (value: string): string => (value.match(/\$([a-zA-Z]*)/i) || [])[1];
const isTicker = (value: string): boolean => Boolean(getTicker(value));
const messages = defineMessages({
linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' },
account_locked: { id: 'account.locked_info', defaultMessage: 'This account privacy status is set to locked. The owner manually reviews who can follow them.' },
deactivated: { id: 'account.deactivated', defaultMessage: 'Deactivated' },
bot: { id: 'account.badges.bot', defaultMessage: 'Bot' },
});
const dateFormatOptions: FormatDateOptions = {
month: 'short',
day: 'numeric',
year: 'numeric',
hour12: true,
hour: 'numeric',
minute: '2-digit',
};
interface IProfileField {
field: Field,
}
/** Renders a single profile field. */
const ProfileField: React.FC<IProfileField> = ({ field }) => {
const intl = useIntl();
if (isTicker(field.name)) {
return (
<BundleContainer fetchComponent={CryptoAddress}>
{Component => (
<Component
ticker={getTicker(field.name).toLowerCase()}
address={field.value_plain}
/>
)}
</BundleContainer>
);
}
return (
<dl>
<dt title={field.name}>
<Markup weight='bold' tag='span' dangerouslySetInnerHTML={{ __html: field.name_emojified }} />
</dt>
<dd
className={classNames({ 'text-success-500': field.verified_at })}
title={field.value_plain}
>
<HStack space={2} alignItems='center'>
{field.verified_at && (
<span className='flex-none' title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(field.verified_at, dateFormatOptions) })}>
<Icon src={require('@tabler/icons/check.svg')} />
</span>
)}
<Markup className='break-words overflow-hidden' tag='span' dangerouslySetInnerHTML={{ __html: field.value_emojified }} />
</HStack>
</dd>
</dl>
);
};
import type { Account } from 'soapbox/types/entities';
interface IProfileFieldsPanel {
account: Account,

Wyświetl plik

@ -13,6 +13,7 @@ import { badgeToTag, getBadges as getAccountBadges } from 'soapbox/utils/badges'
import { capitalize } from 'soapbox/utils/strings';
import ProfileFamiliarFollowers from './profile-familiar-followers';
import ProfileField from './profile-field';
import ProfileStats from './profile-stats';
import type { Account } from 'soapbox/types/entities';
@ -231,6 +232,14 @@ const ProfileInfoPanel: React.FC<IProfileInfoPanel> = ({ account, username }) =>
<ProfileFamiliarFollowers account={account} />
</Stack>
{account.fields.size > 0 && (
<Stack space={2} className='mt-4 xl:hidden'>
{account.fields.map((field, i) => (
<ProfileField field={field} key={i} />
))}
</Stack>
)}
</div>
);
};

Wyświetl plik

@ -5,7 +5,7 @@
"account.add_or_remove_from_list": "Hinzufügen oder Entfernen von Listen",
"account.badges.bot": "Bot",
"account.birthday": "Geburtsdatum {date}",
"account.birthday_today": "Birthday is today!",
"account.birthday_today": "Hat heute Geburtstag!",
"account.block": "@{name} blockieren",
"account.block_domain": "Alles von {domain} verstecken",
"account.blocked": "Blockiert",
@ -104,14 +104,14 @@
"admin.users.actions.promote_to_admin_message": "@{acct} ist nun Adminstrator.",
"admin.users.actions.promote_to_moderator": "@{name} zum Moderator ernennen",
"admin.users.actions.promote_to_moderator_message": "@{acct} ist nun Moderator",
"admin.users.actions.remove_donor": "Remove @{name} as a donor",
"admin.users.actions.set_donor": "Set @{name} as a donor",
"admin.users.actions.remove_donor": "@{name} aus der Liste der Unterstützer:innen entfernen",
"admin.users.actions.set_donor": "@{name} als Unterstützer:in festlegen",
"admin.users.actions.suggest_user": "@{name} vorschlagen",
"admin.users.actions.unsuggest_user": "Vorschlag von @{name} zurücknehmen",
"admin.users.actions.unverify_user": "Verifizierung von @{name} aufheben",
"admin.users.actions.verify_user": "Verifizierung von @{name} bestätigen",
"admin.users.remove_donor_message": "@{acct} was removed as a donor",
"admin.users.set_donor_message": "@{acct} was set as a donor",
"admin.users.remove_donor_message": "@{acct} wurde als Unterstützer:in entfernt",
"admin.users.set_donor_message": "@{acct} wurde als Unterstützer:in festgelegt",
"admin.users.user_deactivated_message": "@{acct} wurde deaktiviert",
"admin.users.user_deleted_message": "@{acct} wurde gelöscht",
"admin.users.user_suggested_message": "@{acct} vorgeschlagen",
@ -121,10 +121,10 @@
"admin_nav.awaiting_approval": "Wartet auf Bestätigung",
"admin_nav.dashboard": "Steuerung",
"admin_nav.reports": "Beschwerden",
"alert.unexpected.body": "We're sorry for the interruption. If the problem persists, please reach out to our support team. You may also try to {clearCookies} (this will log you out).",
"alert.unexpected.body": "Verzeihe die Unannnehmlichkeiten. Wende dich an den Support, wenn das Problem über längere Zeit besteht. Möglicherweise hilft es, {clearCookies}. Hierdurch wirst du abgemeldet.",
"alert.unexpected.browser": "Browser",
"alert.unexpected.clear_cookies": "Cookies und Browserdaten löschen",
"alert.unexpected.links.help": "Help Center",
"alert.unexpected.links.help": "Hilfe",
"alert.unexpected.links.status": "Status",
"alert.unexpected.links.support": "Support",
"alert.unexpected.message": "Ein unerwarteter Fehler ist aufgetreten.",
@ -155,7 +155,7 @@
"backups.empty_message.action": "Backup jetzt erstellen?",
"backups.pending": "Anstehende Backups",
"beta.also_available": "Available in:",
"birthday_panel.title": "Birthdays",
"birthday_panel.title": "Geburtstage",
"boost_modal.combo": "Drücke {combo}, um dieses Fenster zu überspringen",
"bundle_column_error.body": "Beim Laden ist ein Fehler aufgetreten.",
"bundle_column_error.retry": "Erneut versuchen",
@ -216,17 +216,17 @@
"column.filters.drop_hint": "Gefilterte Beiträge bleiben dauerhaft unsichtbar, auch wenn der Filter später entfernt wird.",
"column.filters.expires": "Gültig bis",
"column.filters.expires_hint": "Ablaufdaten werden zurzeit nicht unterstüzt.",
"column.filters.home_timeline": "Home timeline",
"column.filters.home_timeline": "Persönliche Timeline",
"column.filters.keyword": "Stichwort oder Wortfolge",
"column.filters.notifications": "Benachrichtgungen",
"column.filters.public_timeline": "Öffentliche Zeitleiste",
"column.filters.subheading_add_new": "Filter hinzufügen",
"column.filters.subheading_filters": "Bestehnde Filter",
"column.filters.whole_word_header": "Ganzes Wort",
"column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word",
"column.follow_requests": "Folgeanfragen",
"column.followers": "Followers",
"column.following": "Following",
"column.filters.whole_word_hint": "Wenn das Schlüsselwort oder die Phrase ausschließlich alphanumerisch ist, wird der Filter ausschließlich auf das gesamte Wort angewandt.",
"column.follow_requests": "Follower-Anfragen",
"column.followers": "Follower",
"column.following": "Gefolgte",
"column.groups": "Gruppen",
"column.home": "Startseite",
"column.import_data": "Daten importieren",
@ -246,7 +246,7 @@
"column.public": "Föderierte Zeitleiste",
"column.reactions": "Reaktionen",
"column.reblogs": "Geteilte Beiträge",
"column.remote": "Federated timeline",
"column.remote": "Föderierte Timeline",
"column.scheduled_statuses": "Vorbereitete Beiträge",
"column.search": "Suche",
"column.security": "Sicherheitseinstellungen",
@ -288,7 +288,7 @@
"compose_form.spoiler.marked": "Text ist hinter einer Warnung versteckt",
"compose_form.spoiler.unmarked": "Text ist nicht versteckt",
"compose_form.spoiler_placeholder": "Inhaltswarnung",
"confirmation_modal.cancel": "Abbrechen",
"confirmation_modal.cancel": "Bearbeiten",
"confirmations.admin.deactivate_user.confirm": "@{name} deaktivieren",
"confirmations.admin.deactivate_user.heading": "Deactivate @{acct}",
"confirmations.admin.deactivate_user.message": "Hiermit wird das Konto von @{acct} deaktiviert. Diese Entscheidung kann später zurückgenommen werden.",
@ -303,23 +303,23 @@
"confirmations.admin.mark_status_not_sensitive.heading": "Mark post not sensitive.",
"confirmations.admin.mark_status_not_sensitive.message": "Hiermit wird der Beitrag von @{acct} als nicht heikel markiert.",
"confirmations.admin.mark_status_sensitive.confirm": "Beitrag als heikel markieren",
"confirmations.admin.mark_status_sensitive.heading": "Mark post sensitive",
"confirmations.admin.mark_status_sensitive.heading": "Beitrag als heikel festlegen",
"confirmations.admin.mark_status_sensitive.message": "Hiermit wird der Beitrag von @{acct} als heikel markiert.",
"confirmations.admin.reject_user.confirm": "@{name} ablehnen",
"confirmations.admin.reject_user.heading": "@{acct} ablehnen",
"confirmations.admin.reject_user.message": "Hiermit wird der Aufnahmeantrag von @{acct} abgelehnt. Diese Entscheidung kann nicht rückgängig gemacht werden.",
"confirmations.block.block_and_report": "Blockieren und melden",
"confirmations.block.confirm": "Blockieren",
"confirmations.block.heading": "Block @{name}",
"confirmations.block.heading": "Blockiere @{name}",
"confirmations.block.message": "Bist du dir sicher, dass du {name} blockieren möchtest?",
"confirmations.delete.confirm": "Löschen",
"confirmations.delete.confirm": "Entwurf löschen",
"confirmations.delete.heading": "Beitrag löschen",
"confirmations.delete.message": "Bist du dir sicher, dass du diesen Beitrag löschen möchtest?",
"confirmations.delete_list.confirm": "Löschen",
"confirmations.delete_list.heading": "Liste löschen",
"confirmations.delete_list.message": "Bist du dir sicher, dass du diese Liste permanent löschen möchtest?",
"confirmations.domain_block.confirm": "Die ganze Domain verbergen",
"confirmations.domain_block.heading": "Block {domain}",
"confirmations.domain_block.heading": "Blockiere {domain}",
"confirmations.domain_block.message": "Bist du dir wirklich sicher, dass du die ganze Domain {domain} blockieren willst? In den meisten Fällen reichen ein paar gezielte Blockierungen oder Stummschaltungen aus. Du wirst den Inhalt von dieser Domain dann nicht mehr in irgendwelchen öffentlichen Timelines oder den Benachrichtigungen finden. Von dieser Domain kann dir auch niemand mehr folgen.",
"confirmations.mute.confirm": "Stummschalten",
"confirmations.mute.heading": "@{name} stummschalten",
@ -333,7 +333,7 @@
"confirmations.register.needs_confirmation.header": "Bestätigung erforderlich",
"confirmations.reply.confirm": "Antworten",
"confirmations.reply.message": "Wenn du jetzt antwortest, wird die gesamte Nachricht verworfen, die du gerade schreibst. Möchtest du wirklich fortfahren?",
"confirmations.scheduled_status_delete.confirm": "Abbrechen",
"confirmations.scheduled_status_delete.confirm": "Bearbeiten",
"confirmations.scheduled_status_delete.heading": "Vorbereiteten Beitrag verwerfen",
"confirmations.scheduled_status_delete.message": "Den vorbereiteten Beitrag wirklich verwerfen?",
"confirmations.unfollow.confirm": "Entfolgen",
@ -345,13 +345,13 @@
"crypto_donate_panel.heading": "Kryptowährungen spenden",
"crypto_donate_panel.intro.message": "{siteTitle} akzeptiert Kryptowährungen, um dieses Angebot zu finanzieren. Danke für deine Unterstützung!",
"datepicker.hint": "Beitrag veröffentlichen am…",
"datepicker.next_month": "Next month",
"datepicker.next_year": "Next year",
"datepicker.previous_month": "Previous month",
"datepicker.previous_year": "Previous year",
"developers.challenge.answer_label": "Answer",
"developers.challenge.answer_placeholder": "Your answer",
"developers.challenge.fail": "Wrong answer",
"datepicker.next_month": "Nächster Monat",
"datepicker.next_year": "Nächstes Jahr",
"datepicker.previous_month": "Vorheriger Monat",
"datepicker.previous_year": "Vorheriges Jahr",
"developers.challenge.answer_label": "Antworten",
"developers.challenge.answer_placeholder": "Deine Antwort",
"developers.challenge.fail": "Falsche Antwort",
"developers.challenge.message": "What is the result of calling {function}?",
"developers.challenge.submit": "Become a developer",
"developers.challenge.success": "You are now a developer",
@ -359,14 +359,14 @@
"developers.navigation.app_create_label": "App erstellen",
"developers.navigation.intentional_error_label": "Trigger an error",
"developers.navigation.leave_developers_label": "Leave developers",
"developers.navigation.network_error_label": "Network error",
"developers.navigation.network_error_label": "Netzwerkfehler",
"developers.navigation.settings_store_label": "Settings store",
"developers.navigation.test_timeline_label": "Test timeline",
"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.federated": "Aus dem Fediverse",
"directory.local": "Ausschließlich von {domain}",
"directory.new_arrivals": "New arrivals",
"directory.new_arrivals": "Neuankömmlinge",
"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",
@ -498,8 +498,8 @@
"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_recommendation.subhead": "Lass uns anfangen!",
"follow_recommendations.done": "Fertig",
"follow_recommendations.heading": "Folge Nutzern, deren Beiträge du sehen möchtest. Hier sind einige Vorschläge:",
"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",
@ -580,8 +580,8 @@
"introduction.interactions.reply.headline": "Antworten",
"introduction.interactions.reply.text": "You can reply to other people's and your own posts, which will chain them together in a conversation.",
"introduction.welcome.action": "Let's go!",
"introduction.welcome.headline": "First steps",
"introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.",
"introduction.welcome.headline": "Erste Schritte",
"introduction.welcome.text": "Willkommen im Fediverse! Gleich kannst du Nachrichten in die Welt verschicken oder mit deinen Freunden teilen. Wichtig: Dein Konto existiert ausschließlich auf der Instanz {domain}. Notiere dir daher neben deinem Nutzernamen (Handle) auch den Namen deiner Instanz.",
"keyboard_shortcuts.back": "zurück navigieren",
"keyboard_shortcuts.blocked": "Liste blockierter Profile öffnen",
"keyboard_shortcuts.boost": "teilen",
@ -611,7 +611,7 @@
"keyboard_shortcuts.unfocus": "Textfeld/die Suche nicht mehr fokussieren",
"keyboard_shortcuts.up": "sich in der Liste hinauf bewegen",
"landing_page_modal.download": "Download",
"landing_page_modal.helpCenter": "Help Center",
"landing_page_modal.helpCenter": "Hilfe",
"lightbox.close": "Schließen",
"lightbox.next": "Weiter",
"lightbox.previous": "Zurück",
@ -620,7 +620,7 @@
"list_adder.header_title": "Nutzer hinzufügen oder entfernen",
"lists.account.add": "Zur Liste hinzufügen",
"lists.account.remove": "Von der Liste entfernen",
"lists.delete": "Delete list",
"lists.delete": "Liste löschen",
"lists.edit": "Liste bearbeiten",
"lists.edit.submit": "Titel ändern",
"lists.new.create": "Liste hinzufügen",
@ -630,16 +630,16 @@
"lists.search": "Suche nach Leuten, denen du folgst",
"lists.subheading": "Deine Listen",
"loading_indicator.label": "Wird geladen …",
"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.instance_label": "Instanz für den Login eingeben",
"login.fields.instance_placeholder": "instanz.de",
"login.fields.otp_code_hint": "Gib den Zwei-Faktoren-Code aus deiner App oder deinen Wiederherstellungsschlüssel ein",
"login.fields.otp_code_label": "Zwei-Faktoren-Code:",
"login.fields.password_placeholder": "Passwort",
"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",
"login.sign_in": "Anmelden",
"media_gallery.toggle_visible": "Sichtbarkeit umschalten",
"media_panel.empty_message": "Keine Medien gefunden.",
"media_panel.title": "Media",
@ -664,19 +664,19 @@
"migration.hint.link": "Neues Alias erstellen",
"migration.move_account.fail": "Account-Übertragung fehlgeschlagen.",
"migration.move_account.success": "Account-Übertragung fehlgeschlagen.",
"migration.submit": "Move followers",
"migration.submit": "Follower übertragen",
"missing_description_modal.cancel": "Abbrechen",
"missing_description_modal.continue": "Senden",
"missing_description_modal.description": "Dennoch fortfahren?",
"missing_description_modal.text": "Du hast nicht für alle Anhänge Beschreibungen angegeben. Dennoch fortfahren?",
"missing_indicator.label": "Nicht gefunden",
"missing_indicator.sublabel": "Der Eintrag konnte nicht gefunden werden",
"mobile.also_available": "Available in:",
"mobile.also_available": "Verfügbar auf:",
"morefollows.followers_label": "…and {count} more {count, plural, one {follower} other {followers}} on remote sites.",
"morefollows.following_label": "…and {count} more {count, plural, one {follow} other {follows}} on remote sites.",
"mute_modal.hide_notifications": "Benachrichtigungen von diesem Account verbergen?",
"navigation.chats": "Chats",
"navigation.compose": "Compose",
"navigation.compose": "Verfassen",
"navigation.dashboard": "Steuerung",
"navigation.developers": "Entwickler",
"navigation.direct_messages": "Nachrichten",
@ -684,7 +684,7 @@
"navigation.invites": "Einladungen",
"navigation.notifications": "Benachrichtigungen",
"navigation.search": "Suche",
"navigation_bar.account_migration": "Move account",
"navigation_bar.account_migration": "Account umziehen",
"navigation_bar.blocks": "Blockierte Profile",
"navigation_bar.compose": "Neuen Beitrag verfassen",
"navigation_bar.compose_direct": "Direktnachrichten",
@ -702,7 +702,7 @@
"navigation_bar.preferences": "Einstellungen",
"navigation_bar.profile_directory": "Profilverzeichnis",
"navigation_bar.security": "Sicherheit",
"navigation_bar.soapbox_config": "Soapbox Konfiguration",
"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",
@ -730,7 +730,7 @@
"notifications.column_settings.follow": "Neue Follower:",
"notifications.column_settings.follow_request": "Neue Follower-Anfragen:",
"notifications.column_settings.mention": "Erwähnungen:",
"notifications.column_settings.move": "Moves:",
"notifications.column_settings.move": "Umzüge:",
"notifications.column_settings.poll": "Ergebnisse von Umfragen:",
"notifications.column_settings.push": "Push-Benachrichtigungen",
"notifications.column_settings.reblog": "Geteilte Beiträge:",
@ -752,26 +752,26 @@
"notifications.queue_label": "{count, plural, one {Eine neue Benachrichtigung} other {# neue Benachrichtigungen}}. Hier klicken, um sie anzuzeigen.",
"onboarding.avatar.subtitle": "Just have fun with it.",
"onboarding.avatar.title": "Profilbild auswählen",
"onboarding.display_name.subtitle": "You can always edit this later.",
"onboarding.display_name.title": "Choose a display name",
"onboarding.done": "Done",
"onboarding.finished.message": "We are very excited to welcome you to our community! Tap the button below to get started.",
"onboarding.display_name.subtitle": "Du kannst diesen Eintrag später jederzeit bearbeiten.",
"onboarding.display_name.title": "Wähle deinen angezeigten Namen",
"onboarding.done": "Fertig",
"onboarding.finished.message": "Schön, dich bei uns begrüßen zu dürfen! Wenn du jetzt bestätigst, kann unserer Reise beginnen.",
"onboarding.finished.title": "Onboarding complete",
"onboarding.header.subtitle": "This will be shown at the top of your profile.",
"onboarding.header.title": "Pick a cover image",
"onboarding.next": "Next",
"onboarding.note.subtitle": "You can always edit this later.",
"onboarding.note.title": "Write a short bio",
"onboarding.saving": "Saving…",
"onboarding.skip": "Skip for now",
"onboarding.suggestions.subtitle": "Here are a few of the most popular accounts you might like.",
"onboarding.suggestions.title": "Suggested accounts",
"onboarding.view_feed": "View Feed",
"password_reset.confirmation": "Check your email for confirmation.",
"onboarding.header.subtitle": "Dies wird in deinen Profilinfos deiner persönlichen Seite zu sehen sein.",
"onboarding.header.title": "Wähle ein Cover für dein Profil",
"onboarding.next": "Weiter",
"onboarding.note.subtitle": "Du kannst diesen Eintrag später jederzeit ändern.",
"onboarding.note.title": "Stell dich deinen Followern kurz vor",
"onboarding.saving": "Speichern…",
"onboarding.skip": "Überspringen",
"onboarding.suggestions.subtitle": "Hier sind ein paar bekannte Gesichter, die dir vielleicht den Einstieg erleichtern.",
"onboarding.suggestions.title": "Vorgeschlagene User",
"onboarding.view_feed": "Timeline anzeigen",
"password_reset.confirmation": "Überprüfe jetzt deine E-Mails.",
"password_reset.fields.username_placeholder": "Email oder Nutzername",
"password_reset.reset": "Passwort zurücksetzen",
"patron.donate": "Donate",
"patron.title": "Funding Goal",
"patron.donate": "Spenden",
"patron.title": "Spendenziel",
"pinned_accounts.title": "{name}s choices",
"pinned_statuses.none": "Keine angehefteten Beiträge.",
"poll.closed": "Geschlossen",
@ -782,10 +782,10 @@
"poll.votes": "{votes, plural, one {# vote} other {# votes}}",
"poll_button.add_poll": "Eine Umfrage erstellen",
"poll_button.remove_poll": "Umfrage entfernen",
"pre_header.close": "Close",
"pre_header.close": "Schließen",
"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.autoload_more_label": "Weitere Posts automatisch laden, wenn das Ende der Timeline erreicht wurde",
"preferences.fields.autoload_timelines_label": "Neue Posts automatisch laden, wenn das obere Ende der Timeline erreicht wurde",
"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",
@ -793,8 +793,8 @@
"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",
"preferences.fields.media_display_label": "Bilder & Videos",
"preferences.hints.feed": "Auf deiner persönlichen Timeline",
"privacy.change": "Sichtbarkeit des Beitrags anpassen",
"privacy.direct.long": "Wird nur an erwähnte Profile gesendet",
"privacy.direct.short": "Direktnachricht",
@ -806,7 +806,7 @@
"privacy.unlisted.short": "Nicht gelistet",
"profile_dropdown.add_account": "Bestehendes Konto hinzufügen",
"profile_dropdown.logout": "Aus @{acct} abmelden",
"profile_fields_panel.title": "Profile fields",
"profile_fields_panel.title": "Profilfelder",
"public.column_settings.title": "Einstellungen der globalen Timeline",
"reactions.all": "Alle",
"regeneration_indicator.label": "Laden…",
@ -835,30 +835,30 @@
"relative_time.just_now": "jetzt",
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"remote_instance.edit_federation": "Edit federation",
"remote_instance.federation_panel.heading": "Federation Restrictions",
"remote_instance.edit_federation": "Föderation bearbeiten",
"remote_instance.federation_panel.heading": "Föderationsbeschränkungen",
"remote_instance.federation_panel.no_restrictions_message": "{siteTitle} has placed no restrictions on {host}.",
"remote_instance.federation_panel.restricted_message": "{siteTitle} blocks all activities from {host}.",
"remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.",
"remote_instance.pin_host": "Pin {host}",
"remote_instance.unpin_host": "Unpin {host}",
"remote_instance.pin_host": "{host} anhenften",
"remote_instance.unpin_host": "{host} abheften",
"remote_interaction.account_placeholder": "Enter your username@domain you want to act from",
"remote_interaction.divider": "or",
"remote_interaction.favourite": "Proceed to like",
"remote_interaction.favourite_title": "Like a post remotely",
"remote_interaction.divider": "oder",
"remote_interaction.favourite": "Like bestätigen",
"remote_interaction.favourite_title": "Beitrag vom Remotekonto liken",
"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.follow_title": "User {user} per Remote folgen",
"remote_interaction.poll_vote": "Bestätige deine Wahl",
"remote_interaction.poll_vote_title": "Stimme per Remotekonto ab",
"remote_interaction.reblog": "Boost bestätigen",
"remote_interaction.reblog_title": "Reblog a post remotely",
"remote_interaction.reply": "Antwort bestätigen",
"remote_interaction.reply_title": "Reply to a post remotely",
"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",
"reply_mentions.account.remove": "Remove from mentions",
"remote_timeline.filter_message": "Du betrachtest die Timeline der Instanz {instance}.",
"reply_indicator.cancel": "Bearbeiten",
"reply_mentions.account.add": "Erwähnen",
"reply_mentions.account.remove": "Aus Erwähnungen entfernen",
"reply_mentions.more": "{count, plural, one {einen weiteren Nutzer} other {# weitere Nutzer}}",
"reply_mentions.reply": "<hover>Antwort an</hover> {accounts}",
"reply_mentions.reply_empty": "Antwort auf einen Beitrag",
@ -870,13 +870,13 @@
"report.placeholder": "Zusätzliche Kommentare",
"report.submit": "Absenden",
"report.target": "{target} melden",
"reset_password.header": "Set New Password",
"schedule.post_time": "Post Date/Time",
"schedule.remove": "Remove schedule",
"reset_password.header": "Neues Passwort festlegen",
"schedule.post_time": "Datum/Uhrzeit zum Absenden",
"schedule.remove": "Ohne Verzögerung absenden",
"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}”",
"scheduled_status.cancel": "Abbrechen",
"search.action": "Suche nach “{query}”",
"search.placeholder": "Suche",
"search_results.accounts": "Personen",
"search_results.hashtags": "Hashtags",
@ -898,10 +898,10 @@
"security.headers.update_email": "Email ändern",
"security.headers.update_password": "Passwort ändern",
"security.mfa": "Zwei-Faktoren-Authentifizierung einstellen",
"security.mfa_enabled": "You have multi-factor authentication set up with OTP.",
"security.mfa_enabled": "Du hast die Zwei-Faktoren-Authentifizierung per OTP aktiviert.",
"security.mfa_header": "Authentifizierungsmethoden",
"security.mfa_setup_hint": "OTP-Zwei-Faktoren-Authentifizierung konfigurieren",
"security.qr.fail": "Failed to fetch setup key",
"security.qr.fail": "Schlüssel konnte nicht abgerufen werden",
"security.submit": "Änderungen speichern",
"security.submit.delete": "Konto löschen",
"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..",
@ -914,7 +914,7 @@
"settings.change_password": "Passwort ändern",
"settings.configure_mfa": "MFA konfigurieren",
"settings.delete_account": "Konto löschen",
"settings.edit_profile": "Edit Profile",
"settings.edit_profile": "Profil bearbeiten",
"settings.preferences": "Einstellungen",
"settings.profile": "Profil",
"settings.save.success": "Einstellungen wurden gespeichert!",
@ -924,15 +924,15 @@
"signup_panel.title": "Neu auf {site_title}?",
"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.authenticated_profile_label": "Profil erfordert Authentifizierung",
"soapbox_config.copyright_footer.meta_fields.label_placeholder": "Copyright Fußnote",
"soapbox_config.crypto_address.meta_fields.address_placeholder": "Address",
"soapbox_config.crypto_address.meta_fields.note_placeholder": "Note (optional)",
"soapbox_config.crypto_address.meta_fields.note_placeholder": "Notiz (optional)",
"soapbox_config.crypto_address.meta_fields.ticker_placeholder": "Ticker",
"soapbox_config.crypto_donate_panel_limit.meta_fields.limit_placeholder": "Number of items to display in the crypto homepage widget",
"soapbox_config.custom_css.meta_fields.url_placeholder": "URL",
"soapbox_config.display_fqn_label": "Display domain (eg @user@domain) for local accounts.",
"soapbox_config.fields.accent_color_label": "Accent color",
"soapbox_config.display_fqn_label": "Zeige Instanz (z. B. @user@instanz) für User auf der lokalen Instanz an.",
"soapbox_config.fields.accent_color_label": "Akzentfarbe",
"soapbox_config.fields.brand_color_label": "Brand color",
"soapbox_config.fields.crypto_address.add": "Cryptocoin-Adresse hinzufügen",
"soapbox_config.fields.crypto_addresses_label": "Cryptocoin-Adresse",
@ -946,7 +946,7 @@
"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. 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_fields": "Du kannst persönliche Links angeben, welche im Panel rechts auf der Timeline angezeigt werden.",
"soapbox_config.hints.promo_panel_icons": "{ link }",
"soapbox_config.hints.promo_panel_icons.link": "Soapbox Icon-Liste",
"soapbox_config.home_footer.meta_fields.label_placeholder": "Label",
@ -959,9 +959,9 @@
"soapbox_config.save": "Speichern",
"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_label": "Einzelnutzer-Modus",
"soapbox_config.single_user_mode_profile_hint": "@handle",
"soapbox_config.single_user_mode_profile_label": "Main user handle",
"soapbox_config.single_user_mode_profile_label": "Primäres Profil",
"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}",
@ -1024,19 +1024,19 @@
"statuses.quote_tombstone": "Der Beitrag kann nicht angezeigt werden.",
"statuses.tombstone": "Beitrag oder Beiträge können nicht angezeigt werden.",
"suggestions.dismiss": "Empfehlung ausblenden",
"tabs_bar.all": "All",
"tabs_bar.all": "Alle",
"tabs_bar.chats": "Chats",
"tabs_bar.dashboard": "Steuerung",
"tabs_bar.fediverse": "Fediverse",
"tabs_bar.home": "Start",
"tabs_bar.more": "More",
"tabs_bar.more": "Mehr",
"tabs_bar.notifications": "Benachrichtigungen",
"tabs_bar.post": "Neuer Beitrag",
"tabs_bar.profile": "Profile",
"tabs_bar.profile": "Profil",
"tabs_bar.search": "Suche",
"tabs_bar.settings": "Settings",
"tabs_bar.theme_toggle_dark": "Switch to dark theme",
"tabs_bar.theme_toggle_light": "Switch to light theme",
"tabs_bar.settings": "Einstellungen",
"tabs_bar.theme_toggle_dark": "Zum dunklen Modus wechseln",
"tabs_bar.theme_toggle_light": "Zum hellen Modus wechseln",
"time_remaining.days": "{number, plural, one {# Tag} other {# Tage}} verbleibend",
"time_remaining.hours": "{number, plural, one {# Stunde} other {# Stunden}} verbleibend",
"time_remaining.minutes": "{number, plural, one {# Minute} other {# Minuten}} verbleibend",
@ -1049,10 +1049,10 @@
"unauthorized_modal.title": "Sign up for {site_title}",
"upload_area.title": "Zum Hochladen hereinziehen",
"upload_button.label": "Mediendatei hinzufügen (JPEG, PNG, GIF, WebM, MP4, MOV)",
"upload_error.image_size_limit": "Image exceeds the current file size limit ({limit})",
"upload_error.image_size_limit": "Bild überschreitet das Limit von ({limit})",
"upload_error.limit": "Dateiupload-Limit erreicht.",
"upload_error.poll": "Dateiuploads sind in Kombination mit Umfragen nicht erlaubt.",
"upload_error.video_size_limit": "Video exceeds the current file size limit ({limit})",
"upload_error.video_size_limit": "Video überschreitet das Limit von ({limit})",
"upload_form.description": "Für Menschen mit Sehbehinderung beschreiben",
"upload_form.preview": "Vorschau",
"upload_form.undo": "Löschen",

Wyświetl plik

@ -319,10 +319,11 @@ export default function compose(state = initialState, action: AnyAction) {
}));
case COMPOSE_QUOTE:
return updateCompose(state, 'compose-modal', compose => compose.withMutations(map => {
const author = action.status.getIn(['account', 'acct']);
const defaultCompose = state.get('default')!;
map.set('quote', action.status.get('id'));
map.set('to', ImmutableOrderedSet());
map.set('to', ImmutableOrderedSet([author]));
map.set('text', '');
map.set('privacy', privacyPreference(action.status.visibility, defaultCompose.privacy));
map.set('focusDate', new Date());

Wyświetl plik

@ -49,7 +49,8 @@ export const TRUTHSOCIAL = 'TruthSocial';
* Rebased, the recommended backend for Soapbox.
* @see {@link https://gitlab.com/soapbox-pub/rebased}
*/
export const SOAPBOX = 'soapbox';
// NOTE: Rebased is named 'soapbox' for legacy reasons.
export const REBASED = 'soapbox';
/**
* glitch-soc, fork of Mastodon with a number of experimental features.
@ -105,7 +106,7 @@ const getInstanceFeatures = (instance: Instance) => {
* @see PATCH /api/v1/accounts/update_credentials
*/
accountLocation: any([
v.software === PLEROMA && v.build === SOAPBOX && gte(v.version, '2.4.50'),
v.software === PLEROMA && v.build === REBASED && gte(v.version, '2.4.50'),
v.software === TRUTHSOCIAL,
]),
@ -179,7 +180,7 @@ const getInstanceFeatures = (instance: Instance) => {
* @see POST /api/v1/accounts
* @see PATCH /api/v1/accounts/update_credentials
*/
birthdays: v.software === PLEROMA && v.build === SOAPBOX && gte(v.version, '2.4.50'),
birthdays: v.software === PLEROMA && v.build === REBASED && gte(v.version, '2.4.50'),
/** Whether people who blocked you are visible through the API. */
blockersVisible: features.includes('blockers_visible'),
@ -380,7 +381,7 @@ const getInstanceFeatures = (instance: Instance) => {
*/
mastodonAdmin: any([
v.software === MASTODON && gte(v.compatVersion, '2.9.1'),
v.software === PLEROMA && v.build === SOAPBOX && gte(v.version, '2.4.50'),
v.software === PLEROMA && v.build === REBASED && gte(v.version, '2.4.50'),
]),
/**
@ -504,7 +505,7 @@ const getInstanceFeatures = (instance: Instance) => {
* @see POST /api/v1/statuses
*/
quotePosts: any([
v.software === PLEROMA && [SOAPBOX, AKKOMA].includes(v.build!) && gte(v.version, '2.4.50'),
v.software === PLEROMA && [REBASED, AKKOMA].includes(v.build!) && gte(v.version, '2.4.50'),
instance.feature_quote === true,
]),
@ -520,7 +521,7 @@ const getInstanceFeatures = (instance: Instance) => {
*/
removeFromFollowers: any([
v.software === MASTODON && gte(v.compatVersion, '3.5.0'),
v.software === PLEROMA && v.build === SOAPBOX && gte(v.version, '2.4.50'),
v.software === PLEROMA && v.build === REBASED && gte(v.version, '2.4.50'),
]),
reportMultipleStatuses: any([

Wyświetl plik

@ -306,28 +306,6 @@
}
}
.chat {
&__attachment-icon {
float: right;
}
&__last-message {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-height: 19px;
a {
color: var(--highlight-text-color);
}
&.attachment {
font-style: italic;
}
}
}
.chat-message__media {
height: 120px;
}