@@ -81,6 +81,7 @@
|
|||||||
"cryptocurrency-icons": "^0.18.1",
|
"cryptocurrency-icons": "^0.18.1",
|
||||||
"cssnano": "^7.1.2",
|
"cssnano": "^7.1.2",
|
||||||
"detect-passive-events": "^2.0.3",
|
"detect-passive-events": "^2.0.3",
|
||||||
|
"dompurify": "^3.3.2",
|
||||||
"emoji-datasource": "15.0.1",
|
"emoji-datasource": "15.0.1",
|
||||||
"emoji-mart": "^5.6.0",
|
"emoji-mart": "^5.6.0",
|
||||||
"exifr": "^7.1.3",
|
"exifr": "^7.1.3",
|
||||||
@@ -91,7 +92,6 @@
|
|||||||
"html-react-parser": "^5.2.17",
|
"html-react-parser": "^5.2.17",
|
||||||
"intl-messageformat": "^11.1.2",
|
"intl-messageformat": "^11.1.2",
|
||||||
"intl-pluralrules": "^2.0.1",
|
"intl-pluralrules": "^2.0.1",
|
||||||
"dompurify": "^3.3.2",
|
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"lexical": "^0.41.0",
|
"lexical": "^0.41.0",
|
||||||
"line-awesome": "^1.3.0",
|
"line-awesome": "^1.3.0",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
||||||
import { useIntl, defineMessages } from 'react-intl';
|
import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
|
||||||
import { type Components, Virtuoso, type VirtuosoHandle } from 'react-virtuoso';
|
import { type Components, Virtuoso, type VirtuosoHandle } from 'react-virtuoso';
|
||||||
|
|
||||||
import Avatar from '@/components/ui/avatar';
|
import Avatar from '@/components/ui/avatar';
|
||||||
@@ -22,16 +22,6 @@ import type { Chat } from 'pl-api';
|
|||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
today: { id: 'chats.dividers.today', defaultMessage: 'Today' },
|
today: { id: 'chats.dividers.today', defaultMessage: 'Today' },
|
||||||
blockedBy: { id: 'chat_message_list.blocked_by', defaultMessage: 'You are blocked by' },
|
|
||||||
networkFailureTitle: { id: 'chat_message_list.network_failure.title', defaultMessage: 'Whoops!' },
|
|
||||||
networkFailureSubtitle: {
|
|
||||||
id: 'chat_message_list.network_failure.subtitle',
|
|
||||||
defaultMessage: 'We encountered a network failure.',
|
|
||||||
},
|
|
||||||
networkFailureAction: {
|
|
||||||
id: 'chat_message_list.network_failure.action',
|
|
||||||
defaultMessage: 'Try again',
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
type TimeFormat = 'today' | 'date';
|
type TimeFormat = 'today' | 'date';
|
||||||
@@ -219,7 +209,12 @@ const ChatMessageList: React.FC<IChatMessageList> = React.memo(({ chat }) => {
|
|||||||
/>
|
/>
|
||||||
<Text align='center'>
|
<Text align='center'>
|
||||||
<>
|
<>
|
||||||
<Text tag='span'>{intl.formatMessage(messages.blockedBy)}</Text>{' '}
|
<Text tag='span'>
|
||||||
|
<FormattedMessage
|
||||||
|
id='chat_message_list.blocked_by'
|
||||||
|
defaultMessage='You are blocked by'
|
||||||
|
/>
|
||||||
|
</Text>{' '}
|
||||||
<Text tag='span' theme='primary'>
|
<Text tag='span' theme='primary'>
|
||||||
@{chat.account.acct}
|
@{chat.account.acct}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -236,16 +231,25 @@ const ChatMessageList: React.FC<IChatMessageList> = React.memo(({ chat }) => {
|
|||||||
<Stack space={4}>
|
<Stack space={4}>
|
||||||
<Stack space={1}>
|
<Stack space={1}>
|
||||||
<Text size='lg' weight='bold' align='center'>
|
<Text size='lg' weight='bold' align='center'>
|
||||||
{intl.formatMessage(messages.networkFailureTitle)}
|
<FormattedMessage
|
||||||
|
id='chat_message_list.network_failure.title'
|
||||||
|
defaultMessage='Whoops!'
|
||||||
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
<Text theme='muted' align='center'>
|
<Text theme='muted' align='center'>
|
||||||
{intl.formatMessage(messages.networkFailureSubtitle)}
|
<FormattedMessage
|
||||||
|
id='chat_message_list.network_failure.subtitle'
|
||||||
|
defaultMessage='We encountered a network failure.'
|
||||||
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<div className='mx-auto'>
|
<div className='mx-auto'>
|
||||||
<Button theme='primary' onClick={() => refetch()}>
|
<Button theme='primary' onClick={() => refetch()}>
|
||||||
{intl.formatMessage(messages.networkFailureAction)}
|
<FormattedMessage
|
||||||
|
id='chat_message_list.network_failure.action'
|
||||||
|
defaultMessage='Try again'
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,27 +1,21 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import Stack from '@/components/ui/stack';
|
import Stack from '@/components/ui/stack';
|
||||||
import Text from '@/components/ui/text';
|
import Text from '@/components/ui/text';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const Blankslate = () => (
|
||||||
title: { id: 'chat_search.blankslate.title', defaultMessage: 'Start a chat' },
|
<Stack justifyContent='center' alignItems='center' space={2} className='mx-auto h-full w-2/3'>
|
||||||
body: { id: 'chat_search.blankslate.body', defaultMessage: 'Search for someone to chat with.' },
|
<Text weight='bold' size='lg' align='center'>
|
||||||
});
|
<FormattedMessage id='chat_search.blankslate.title' defaultMessage='Start a chat' />
|
||||||
|
</Text>
|
||||||
const Blankslate = () => {
|
<Text theme='muted' align='center'>
|
||||||
const intl = useIntl();
|
<FormattedMessage
|
||||||
|
id='chat_search.blankslate.body'
|
||||||
return (
|
defaultMessage='Search for someone to chat with.'
|
||||||
<Stack justifyContent='center' alignItems='center' space={2} className='mx-auto h-full w-2/3'>
|
/>
|
||||||
<Text weight='bold' size='lg' align='center'>
|
</Text>
|
||||||
{intl.formatMessage(messages.title)}
|
</Stack>
|
||||||
</Text>
|
);
|
||||||
<Text theme='muted' align='center'>
|
|
||||||
{intl.formatMessage(messages.body)}
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export { Blankslate as default };
|
export { Blankslate as default };
|
||||||
|
|||||||
@@ -1,31 +1,25 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import Stack from '@/components/ui/stack';
|
import Stack from '@/components/ui/stack';
|
||||||
import Text from '@/components/ui/text';
|
import Text from '@/components/ui/text';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const EmptyResultsBlankslate = () => (
|
||||||
title: { id: 'chat_search.empty_results_blankslate.title', defaultMessage: 'No matches found' },
|
<Stack justifyContent='center' alignItems='center' space={2} className='mx-auto h-full w-2/3'>
|
||||||
body: {
|
<Text weight='bold' size='lg' align='center' data-testid='no-results'>
|
||||||
id: 'chat_search.empty_results_blankslate.body',
|
<FormattedMessage
|
||||||
defaultMessage: 'Try searching for another name.',
|
id='chat_search.empty_results_blankslate.title'
|
||||||
},
|
defaultMessage='No matches found'
|
||||||
});
|
/>
|
||||||
|
</Text>
|
||||||
|
|
||||||
const EmptyResultsBlankslate = () => {
|
<Text theme='muted' align='center'>
|
||||||
const intl = useIntl();
|
<FormattedMessage
|
||||||
|
id='chat_search.empty_results_blankslate.body'
|
||||||
return (
|
defaultMessage='Try searching for another name.'
|
||||||
<Stack justifyContent='center' alignItems='center' space={2} className='mx-auto h-full w-2/3'>
|
/>
|
||||||
<Text weight='bold' size='lg' align='center' data-testid='no-results'>
|
</Text>
|
||||||
{intl.formatMessage(messages.title)}
|
</Stack>
|
||||||
</Text>
|
);
|
||||||
|
|
||||||
<Text theme='muted' align='center'>
|
|
||||||
{intl.formatMessage(messages.body)}
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export { EmptyResultsBlankslate as default };
|
export { EmptyResultsBlankslate as default };
|
||||||
|
|||||||
@@ -1,21 +1,9 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import Select from '@/components/ui/select';
|
import Select from '@/components/ui/select';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
days: {
|
|
||||||
id: 'intervals.full.days',
|
|
||||||
defaultMessage: '{number, plural, one {# day} other {# days}}',
|
|
||||||
},
|
|
||||||
hours: {
|
|
||||||
id: 'intervals.full.hours',
|
|
||||||
defaultMessage: '{number, plural, one {# hour} other {# hours}}',
|
|
||||||
},
|
|
||||||
minutes: {
|
|
||||||
id: 'intervals.full.minutes',
|
|
||||||
defaultMessage: '{number, plural, one {# minute} other {# minutes}}',
|
|
||||||
},
|
|
||||||
daysTitle: { id: 'compose_form.poll.duration.days', defaultMessage: 'Days' },
|
daysTitle: { id: 'compose_form.poll.duration.days', defaultMessage: 'Days' },
|
||||||
hoursTitle: { id: 'compose_form.poll.duration.hours', defaultMessage: 'Hours' },
|
hoursTitle: { id: 'compose_form.poll.duration.hours', defaultMessage: 'Hours' },
|
||||||
minutesTitle: { id: 'compose_form.poll.duration.minutes', defaultMessage: 'Minutes' },
|
minutesTitle: { id: 'compose_form.poll.duration.minutes', defaultMessage: 'Minutes' },
|
||||||
@@ -59,7 +47,11 @@ const DurationSelector = ({ onDurationChange, value }: IDurationSelector) => {
|
|||||||
>
|
>
|
||||||
{[...Array(8).fill(undefined)].map((_, number) => (
|
{[...Array(8).fill(undefined)].map((_, number) => (
|
||||||
<option value={number} key={number}>
|
<option value={number} key={number}>
|
||||||
{intl.formatMessage(messages.days, { number })}
|
<FormattedMessage
|
||||||
|
id='intervals.full.days'
|
||||||
|
defaultMessage='{number, plural, one {# day} other {# days}}'
|
||||||
|
values={{ number }}
|
||||||
|
/>
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
@@ -77,7 +69,11 @@ const DurationSelector = ({ onDurationChange, value }: IDurationSelector) => {
|
|||||||
>
|
>
|
||||||
{[...Array(24).fill(undefined)].map((_, number) => (
|
{[...Array(24).fill(undefined)].map((_, number) => (
|
||||||
<option value={number} key={number}>
|
<option value={number} key={number}>
|
||||||
{intl.formatMessage(messages.hours, { number })}
|
<FormattedMessage
|
||||||
|
id='intervals.full.hours'
|
||||||
|
defaultMessage='{number, plural, one {# hour} other {# hours}}'
|
||||||
|
values={{ number }}
|
||||||
|
/>
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
@@ -95,7 +91,11 @@ const DurationSelector = ({ onDurationChange, value }: IDurationSelector) => {
|
|||||||
>
|
>
|
||||||
{[0, 15, 30, 45].map((number) => (
|
{[0, 15, 30, 45].map((number) => (
|
||||||
<option value={number} key={number}>
|
<option value={number} key={number}>
|
||||||
{intl.formatMessage(messages.minutes, { number })}
|
<FormattedMessage
|
||||||
|
id='intervals.full.minutes'
|
||||||
|
defaultMessage='{number, plural, one {# minute} other {# minutes}}'
|
||||||
|
values={{ number }}
|
||||||
|
/>
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
|
|||||||
@@ -21,21 +21,6 @@ const messages = defineMessages({
|
|||||||
id: 'compose_form.poll.option_placeholder',
|
id: 'compose_form.poll.option_placeholder',
|
||||||
defaultMessage: 'Answer #{number}',
|
defaultMessage: 'Answer #{number}',
|
||||||
},
|
},
|
||||||
pollDuration: { id: 'compose_form.poll.duration', defaultMessage: 'Poll duration' },
|
|
||||||
removePoll: { id: 'compose_form.poll.remove', defaultMessage: 'Remove poll' },
|
|
||||||
switchToMultiple: {
|
|
||||||
id: 'compose_form.poll.switch_to_multiple',
|
|
||||||
defaultMessage: 'Change poll to allow multiple answers',
|
|
||||||
},
|
|
||||||
switchToSingle: {
|
|
||||||
id: 'compose_form.poll.switch_to_single',
|
|
||||||
defaultMessage: 'Change poll to allow for a single answer',
|
|
||||||
},
|
|
||||||
multiSelect: { id: 'compose_form.poll.multiselect', defaultMessage: 'Multi-select' },
|
|
||||||
multiSelectDetail: {
|
|
||||||
id: 'compose_form.poll.multiselect_detail',
|
|
||||||
defaultMessage: 'Allow users to select multiple answers',
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IOption {
|
interface IOption {
|
||||||
@@ -137,7 +122,6 @@ interface IPollForm {
|
|||||||
|
|
||||||
const PollForm: React.FC<IPollForm> = ({ composeId }) => {
|
const PollForm: React.FC<IPollForm> = ({ composeId }) => {
|
||||||
const { updateCompose } = useComposeActions();
|
const { updateCompose } = useComposeActions();
|
||||||
const intl = useIntl();
|
|
||||||
const { configuration } = useInstance();
|
const { configuration } = useInstance();
|
||||||
|
|
||||||
const { poll, language, modifiedLanguage } = useCompose(composeId);
|
const { poll, language, modifiedLanguage } = useCompose(composeId);
|
||||||
@@ -224,10 +208,15 @@ const PollForm: React.FC<IPollForm> = ({ composeId }) => {
|
|||||||
<label className='text-start'>
|
<label className='text-start'>
|
||||||
<HStack alignItems='center' justifyContent='between'>
|
<HStack alignItems='center' justifyContent='between'>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text weight='medium'>{intl.formatMessage(messages.multiSelect)}</Text>
|
<Text weight='medium'>
|
||||||
|
<FormattedMessage id='compose_form.poll.multiselect' defaultMessage='Multi-select' />
|
||||||
|
</Text>
|
||||||
|
|
||||||
<Text theme='muted' size='sm'>
|
<Text theme='muted' size='sm'>
|
||||||
{intl.formatMessage(messages.multiSelectDetail)}
|
<FormattedMessage
|
||||||
|
id='compose_form.poll.multiselect_detail'
|
||||||
|
defaultMessage='Allow users to select multiple answers'
|
||||||
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
@@ -239,7 +228,9 @@ const PollForm: React.FC<IPollForm> = ({ composeId }) => {
|
|||||||
|
|
||||||
{/* Duration */}
|
{/* Duration */}
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Text weight='medium'>{intl.formatMessage(messages.pollDuration)}</Text>
|
<Text weight='medium'>
|
||||||
|
<FormattedMessage id='compose_form.poll.duration' defaultMessage='Poll duration' />
|
||||||
|
</Text>
|
||||||
|
|
||||||
<DurationSelector
|
<DurationSelector
|
||||||
onDurationChange={handleSelectDuration}
|
onDurationChange={handleSelectDuration}
|
||||||
@@ -250,7 +241,7 @@ const PollForm: React.FC<IPollForm> = ({ composeId }) => {
|
|||||||
{/* Remove Poll */}
|
{/* Remove Poll */}
|
||||||
<div className='text-center'>
|
<div className='text-center'>
|
||||||
<button type='button' className='text-danger-500' onClick={onRemovePoll}>
|
<button type='button' className='text-danger-500' onClick={onRemovePoll}>
|
||||||
{intl.formatMessage(messages.removePoll)}
|
<FormattedMessage id='compose_form.poll.remove' defaultMessage='Remove poll' />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -671,8 +671,6 @@
|
|||||||
"compose_form.poll.option_placeholder": "Answer #{number}",
|
"compose_form.poll.option_placeholder": "Answer #{number}",
|
||||||
"compose_form.poll.remove": "Remove poll",
|
"compose_form.poll.remove": "Remove poll",
|
||||||
"compose_form.poll.remove_option": "Remove this answer",
|
"compose_form.poll.remove_option": "Remove this answer",
|
||||||
"compose_form.poll.switch_to_multiple": "Change poll to allow multiple answers",
|
|
||||||
"compose_form.poll.switch_to_single": "Change poll to allow for a single answer",
|
|
||||||
"compose_form.poll_placeholder": "Add a poll topic…",
|
"compose_form.poll_placeholder": "Add a poll topic…",
|
||||||
"compose_form.preview": "Preview post",
|
"compose_form.preview": "Preview post",
|
||||||
"compose_form.preview.close": "Hide preview",
|
"compose_form.preview.close": "Hide preview",
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import Stack from '@/components/ui/stack';
|
import Stack from '@/components/ui/stack';
|
||||||
import Text from '@/components/ui/text';
|
import Text from '@/components/ui/text';
|
||||||
import { useAppSelector } from '@/hooks/use-app-selector';
|
import { useAppSelector } from '@/hooks/use-app-selector';
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
accountEntity: { id: 'report.confirmation.entity.account', defaultMessage: 'account' },
|
|
||||||
title: { id: 'report.confirmation.title', defaultMessage: 'Thanks for submitting your report.' },
|
|
||||||
content: {
|
|
||||||
id: 'report.confirmation.content',
|
|
||||||
defaultMessage:
|
|
||||||
'If we find that this {entity} is violating the {link} we will take further action on the matter.',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const termsOfServiceText = <FormattedMessage id='shared.tos' defaultMessage='Terms of Service' />;
|
const termsOfServiceText = <FormattedMessage id='shared.tos' defaultMessage='Terms of Service' />;
|
||||||
|
|
||||||
const renderTermsOfServiceLink = (href: string) => (
|
const renderTermsOfServiceLink = (href: string) => (
|
||||||
@@ -28,11 +18,8 @@ const renderTermsOfServiceLink = (href: string) => (
|
|||||||
);
|
);
|
||||||
|
|
||||||
const ConfirmationStep: React.FC = () => {
|
const ConfirmationStep: React.FC = () => {
|
||||||
const intl = useIntl();
|
|
||||||
const links = useAppSelector((state) => state.frontendConfig.links);
|
const links = useAppSelector((state) => state.frontendConfig.links);
|
||||||
|
|
||||||
const entity = intl.formatMessage(messages.accountEntity);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack space={1}>
|
<Stack space={1}>
|
||||||
<Text weight='semibold' tag='h1' size='xl'>
|
<Text weight='semibold' tag='h1' size='xl'>
|
||||||
@@ -40,7 +27,6 @@ const ConfirmationStep: React.FC = () => {
|
|||||||
id='report.confirmation.title'
|
id='report.confirmation.title'
|
||||||
defaultMessage='Thanks for submitting your report.'
|
defaultMessage='Thanks for submitting your report.'
|
||||||
/>
|
/>
|
||||||
{intl.formatMessage(messages.title)}
|
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Text>
|
<Text>
|
||||||
@@ -48,7 +34,9 @@ const ConfirmationStep: React.FC = () => {
|
|||||||
id='report.confirmation.content'
|
id='report.confirmation.content'
|
||||||
defaultMessage='If we find that this {entity} is violating the {link} we will take further action on the matter.'
|
defaultMessage='If we find that this {entity} is violating the {link} we will take further action on the matter.'
|
||||||
values={{
|
values={{
|
||||||
entity,
|
entity: (
|
||||||
|
<FormattedMessage id='report.confirmation.entity.account' defaultMessage='account' />
|
||||||
|
),
|
||||||
link: links?.termsOfService
|
link: links?.termsOfService
|
||||||
? renderTermsOfServiceLink(links.termsOfService)
|
? renderTermsOfServiceLink(links.termsOfService)
|
||||||
: termsOfServiceText,
|
: termsOfServiceText,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import Button from '@/components/ui/button';
|
import Button from '@/components/ui/button';
|
||||||
import FormGroup from '@/components/ui/form-group';
|
import FormGroup from '@/components/ui/form-group';
|
||||||
@@ -14,26 +14,6 @@ import { getDomain } from '@/utils/accounts';
|
|||||||
|
|
||||||
import type { Account } from 'pl-api';
|
import type { Account } from 'pl-api';
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
addAdditionalStatuses: {
|
|
||||||
id: 'report.other_actions.add_additional',
|
|
||||||
defaultMessage: 'Would you like to add additional statuses to this report?',
|
|
||||||
},
|
|
||||||
addMore: { id: 'report.other_actions.add_more', defaultMessage: 'Add more' },
|
|
||||||
furtherActions: {
|
|
||||||
id: 'report.other_actions.further_actions',
|
|
||||||
defaultMessage: 'Further actions:',
|
|
||||||
},
|
|
||||||
hideAdditionalStatuses: {
|
|
||||||
id: 'report.other_actions.hide_additional',
|
|
||||||
defaultMessage: 'Hide additional statuses',
|
|
||||||
},
|
|
||||||
otherStatuses: {
|
|
||||||
id: 'report.other_actions.other_statuses',
|
|
||||||
defaultMessage: 'Include other statuses?',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
interface IOtherActionsStep {
|
interface IOtherActionsStep {
|
||||||
account: Pick<Account, 'id' | 'acct' | 'local' | 'url'>;
|
account: Pick<Account, 'id' | 'acct' | 'local' | 'url'>;
|
||||||
selectedStatusIds: string[];
|
selectedStatusIds: string[];
|
||||||
@@ -56,7 +36,6 @@ const OtherActionsStep = ({
|
|||||||
isSubmitting,
|
isSubmitting,
|
||||||
}: IOtherActionsStep) => {
|
}: IOtherActionsStep) => {
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
const intl = useIntl();
|
|
||||||
|
|
||||||
const { entries } = useAccountTimeline(account.id, { exclude_replies: false });
|
const { entries } = useAccountTimeline(account.id, { exclude_replies: false });
|
||||||
|
|
||||||
@@ -100,10 +79,20 @@ const OtherActionsStep = ({
|
|||||||
<Stack space={4}>
|
<Stack space={4}>
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Text tag='h1' size='xl' weight='semibold'>
|
<Text tag='h1' size='xl' weight='semibold'>
|
||||||
{intl.formatMessage(messages.otherStatuses)}
|
<FormattedMessage
|
||||||
|
id='report.other_actions.other_statuses'
|
||||||
|
defaultMessage='Include other statuses?'
|
||||||
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<FormGroup labelText={intl.formatMessage(messages.addAdditionalStatuses)}>
|
<FormGroup
|
||||||
|
labelText={
|
||||||
|
<FormattedMessage
|
||||||
|
id='report.other_actions.add_additional'
|
||||||
|
defaultMessage='Would you like to add additional statuses to this report?'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
{showAdditionalStatuses ? (
|
{showAdditionalStatuses ? (
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<div className='⁂-status-list'>
|
<div className='⁂-status-list'>
|
||||||
@@ -126,7 +115,10 @@ const OtherActionsStep = ({
|
|||||||
setShowAdditionalStatuses(false);
|
setShowAdditionalStatuses(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(messages.hideAdditionalStatuses)}
|
<FormattedMessage
|
||||||
|
id='report.other_actions.hide_additional'
|
||||||
|
defaultMessage='Hide additional statuses'
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -139,7 +131,7 @@ const OtherActionsStep = ({
|
|||||||
setShowAdditionalStatuses(true);
|
setShowAdditionalStatuses(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(messages.addMore)}
|
<FormattedMessage id='report.other_actions.add_more' defaultMessage='Add more' />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
@@ -147,7 +139,10 @@ const OtherActionsStep = ({
|
|||||||
|
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Text tag='h1' size='xl' weight='semibold'>
|
<Text tag='h1' size='xl' weight='semibold'>
|
||||||
{intl.formatMessage(messages.furtherActions)}
|
<FormattedMessage
|
||||||
|
id='report.other_actions.further_actions'
|
||||||
|
defaultMessage='Further actions:'
|
||||||
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import FormGroup from '@/components/ui/form-group';
|
import FormGroup from '@/components/ui/form-group';
|
||||||
import Stack from '@/components/ui/stack';
|
import Stack from '@/components/ui/stack';
|
||||||
@@ -12,7 +12,6 @@ import type { Account } from 'pl-api';
|
|||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' },
|
placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' },
|
||||||
reasonForReporting: { id: 'report.reason.title', defaultMessage: 'Reason for reporting' },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IReasonStep {
|
interface IReasonStep {
|
||||||
@@ -80,7 +79,7 @@ const ReasonStep: React.FC<IReasonStep> = ({ comment, setComment, ruleIds, setRu
|
|||||||
{shouldRequireRule && (
|
{shouldRequireRule && (
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Text size='xl' weight='semibold' tag='h1'>
|
<Text size='xl' weight='semibold' tag='h1'>
|
||||||
{intl.formatMessage(messages.reasonForReporting)}
|
<FormattedMessage id='report.reason.title' defaultMessage='Reason for reporting' />
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<div className='relative'>
|
<div className='relative'>
|
||||||
|
|||||||
@@ -15,9 +15,6 @@ import { useFeatures } from '@/hooks/use-features';
|
|||||||
import toast from '@/toast';
|
import toast from '@/toast';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
passwordFieldLabel: { id: 'security.fields.password.label', defaultMessage: 'Password' },
|
|
||||||
deleteHeader: { id: 'column.delete_account', defaultMessage: 'Delete account' },
|
|
||||||
deleteSubmit: { id: 'security.submit.delete', defaultMessage: 'Delete account' },
|
|
||||||
deleteAccountSuccess: {
|
deleteAccountSuccess: {
|
||||||
id: 'security.delete_account.success',
|
id: 'security.delete_account.success',
|
||||||
defaultMessage: 'Account successfully deleted.',
|
defaultMessage: 'Account successfully deleted.',
|
||||||
@@ -61,7 +58,9 @@ const DeleteAccountPage = () => {
|
|||||||
return (
|
return (
|
||||||
<Card variant='rounded'>
|
<Card variant='rounded'>
|
||||||
<CardHeader backHref='/settings'>
|
<CardHeader backHref='/settings'>
|
||||||
<CardTitle title={intl.formatMessage(messages.deleteHeader)} />
|
<CardTitle
|
||||||
|
title={<FormattedMessage id='column.delete_account' defaultMessage='Delete account' />}
|
||||||
|
/>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardBody>
|
<CardBody>
|
||||||
@@ -94,7 +93,11 @@ const DeleteAccountPage = () => {
|
|||||||
|
|
||||||
<Form onSubmit={handleSubmit}>
|
<Form onSubmit={handleSubmit}>
|
||||||
{!features.deleteAccountWithoutPassword && (
|
{!features.deleteAccountWithoutPassword && (
|
||||||
<FormGroup labelText={intl.formatMessage(messages.passwordFieldLabel)}>
|
<FormGroup
|
||||||
|
labelText={
|
||||||
|
<FormattedMessage id='security.fields.password.label' defaultMessage='Password' />
|
||||||
|
}
|
||||||
|
>
|
||||||
<Input
|
<Input
|
||||||
type='password'
|
type='password'
|
||||||
name='password'
|
name='password'
|
||||||
@@ -106,7 +109,7 @@ const DeleteAccountPage = () => {
|
|||||||
|
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<Button type='submit' theme='danger' disabled={isLoading}>
|
<Button type='submit' theme='danger' disabled={isLoading}>
|
||||||
{intl.formatMessage(messages.deleteSubmit)}
|
<FormattedMessage id='security.submit.delete' defaultMessage='Delete account' />
|
||||||
</Button>
|
</Button>
|
||||||
</FormActions>
|
</FormActions>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { changeEmail } from '@/actions/security';
|
import { changeEmail } from '@/actions/security';
|
||||||
import Button from '@/components/ui/button';
|
import Button from '@/components/ui/button';
|
||||||
@@ -18,11 +18,7 @@ const messages = defineMessages({
|
|||||||
defaultMessage: 'Email successfully updated.',
|
defaultMessage: 'Email successfully updated.',
|
||||||
},
|
},
|
||||||
updateEmailFail: { id: 'security.update_email.fail', defaultMessage: 'Update email failed.' },
|
updateEmailFail: { id: 'security.update_email.fail', defaultMessage: 'Update email failed.' },
|
||||||
emailFieldLabel: { id: 'security.fields.email.label', defaultMessage: 'Email address' },
|
|
||||||
emailFieldPlaceholder: { id: 'edit_email.placeholder', defaultMessage: 'me@example.com' },
|
emailFieldPlaceholder: { id: 'edit_email.placeholder', defaultMessage: 'me@example.com' },
|
||||||
passwordFieldLabel: { id: 'security.fields.password.label', defaultMessage: 'Password' },
|
|
||||||
submit: { id: 'security.submit', defaultMessage: 'Save changes' },
|
|
||||||
cancel: { id: 'common.cancel', defaultMessage: 'Cancel' },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialState = { email: '', password: '' };
|
const initialState = { email: '', password: '' };
|
||||||
@@ -64,7 +60,11 @@ const EditEmailPage = () => {
|
|||||||
return (
|
return (
|
||||||
<Column label={intl.formatMessage(messages.header)} backHref='/settings'>
|
<Column label={intl.formatMessage(messages.header)} backHref='/settings'>
|
||||||
<Form onSubmit={handleSubmit}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<FormGroup labelText={intl.formatMessage(messages.emailFieldLabel)}>
|
<FormGroup
|
||||||
|
labelText={
|
||||||
|
<FormattedMessage id='security.fields.email.label' defaultMessage='Email address' />
|
||||||
|
}
|
||||||
|
>
|
||||||
<Input
|
<Input
|
||||||
type='text'
|
type='text'
|
||||||
placeholder={intl.formatMessage(messages.emailFieldPlaceholder)}
|
placeholder={intl.formatMessage(messages.emailFieldPlaceholder)}
|
||||||
@@ -75,16 +75,20 @@ const EditEmailPage = () => {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup labelText={intl.formatMessage(messages.passwordFieldLabel)}>
|
<FormGroup
|
||||||
|
labelText={
|
||||||
|
<FormattedMessage id='security.fields.password.label' defaultMessage='Password' />
|
||||||
|
}
|
||||||
|
>
|
||||||
<Input type='password' name='password' onChange={handleInputChange} value={password} />
|
<Input type='password' name='password' onChange={handleInputChange} value={password} />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<Button to='/settings' theme='tertiary'>
|
<Button to='/settings' theme='tertiary'>
|
||||||
{intl.formatMessage(messages.cancel)}
|
<FormattedMessage id='common.cancel' defaultMessage='Cancel' />
|
||||||
</Button>
|
</Button>
|
||||||
<Button type='submit' theme='primary' disabled={isLoading}>
|
<Button type='submit' theme='primary' disabled={isLoading}>
|
||||||
{intl.formatMessage(messages.submit)}
|
<FormattedMessage id='security.submit' defaultMessage='Save changes' />
|
||||||
</Button>
|
</Button>
|
||||||
</FormActions>
|
</FormActions>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { changePassword } from '@/actions/security';
|
import { changePassword } from '@/actions/security';
|
||||||
import Button from '@/components/ui/button';
|
import Button from '@/components/ui/button';
|
||||||
@@ -24,21 +24,7 @@ const messages = defineMessages({
|
|||||||
id: 'security.update_password.password_confirmation_no_match',
|
id: 'security.update_password.password_confirmation_no_match',
|
||||||
defaultMessage: 'Passwords do not match.',
|
defaultMessage: 'Passwords do not match.',
|
||||||
},
|
},
|
||||||
oldPasswordFieldLabel: {
|
|
||||||
id: 'security.fields.old_password.label',
|
|
||||||
defaultMessage: 'Current password',
|
|
||||||
},
|
|
||||||
newPasswordFieldLabel: {
|
|
||||||
id: 'security.fields.new_password.label',
|
|
||||||
defaultMessage: 'New password',
|
|
||||||
},
|
|
||||||
confirmationFieldLabel: {
|
|
||||||
id: 'security.fields.password_confirmation.label',
|
|
||||||
defaultMessage: 'New password (again)',
|
|
||||||
},
|
|
||||||
header: { id: 'edit_password.header', defaultMessage: 'Change password' },
|
header: { id: 'edit_password.header', defaultMessage: 'Change password' },
|
||||||
submit: { id: 'security.submit', defaultMessage: 'Save changes' },
|
|
||||||
cancel: { id: 'common.cancel', defaultMessage: 'Cancel' },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialState = { currentPassword: '', newPassword: '', newPasswordConfirmation: '' };
|
const initialState = { currentPassword: '', newPassword: '', newPasswordConfirmation: '' };
|
||||||
@@ -89,7 +75,14 @@ const EditPasswordPage = () => {
|
|||||||
return (
|
return (
|
||||||
<Column label={intl.formatMessage(messages.header)} backHref='/settings'>
|
<Column label={intl.formatMessage(messages.header)} backHref='/settings'>
|
||||||
<Form onSubmit={handleSubmit}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<FormGroup labelText={intl.formatMessage(messages.oldPasswordFieldLabel)}>
|
<FormGroup
|
||||||
|
labelText={
|
||||||
|
<FormattedMessage
|
||||||
|
id='security.fields.old_password.label'
|
||||||
|
defaultMessage='Current password'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Input
|
<Input
|
||||||
type='password'
|
type='password'
|
||||||
name='currentPassword'
|
name='currentPassword'
|
||||||
@@ -98,7 +91,14 @@ const EditPasswordPage = () => {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup labelText={intl.formatMessage(messages.newPasswordFieldLabel)}>
|
<FormGroup
|
||||||
|
labelText={
|
||||||
|
<FormattedMessage
|
||||||
|
id='security.fields.new_password.label'
|
||||||
|
defaultMessage='New password'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Input
|
<Input
|
||||||
type='password'
|
type='password'
|
||||||
name='newPassword'
|
name='newPassword'
|
||||||
@@ -107,7 +107,14 @@ const EditPasswordPage = () => {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup labelText={intl.formatMessage(messages.confirmationFieldLabel)}>
|
<FormGroup
|
||||||
|
labelText={
|
||||||
|
<FormattedMessage
|
||||||
|
id='security.fields.password_confirmation.label'
|
||||||
|
defaultMessage='New password (again)'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Input
|
<Input
|
||||||
type='password'
|
type='password'
|
||||||
name='newPasswordConfirmation'
|
name='newPasswordConfirmation'
|
||||||
@@ -118,7 +125,7 @@ const EditPasswordPage = () => {
|
|||||||
|
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<Button to='/settings' theme='tertiary'>
|
<Button to='/settings' theme='tertiary'>
|
||||||
{intl.formatMessage(messages.cancel)}
|
<FormattedMessage id='common.cancel' defaultMessage='Cancel' />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@@ -126,7 +133,7 @@ const EditPasswordPage = () => {
|
|||||||
theme='primary'
|
theme='primary'
|
||||||
disabled={isLoading || newPassword !== newPasswordConfirmation}
|
disabled={isLoading || newPassword !== newPasswordConfirmation}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(messages.submit)}
|
<FormattedMessage id='security.submit' defaultMessage='Save changes' />
|
||||||
</Button>
|
</Button>
|
||||||
</FormActions>
|
</FormActions>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ const messages = defineMessages({
|
|||||||
id: 'edit_profile.fields.location_placeholder',
|
id: 'edit_profile.fields.location_placeholder',
|
||||||
defaultMessage: 'Location',
|
defaultMessage: 'Location',
|
||||||
},
|
},
|
||||||
cancel: { id: 'common.cancel', defaultMessage: 'Cancel' },
|
|
||||||
mentionPolicyNone: { id: 'edit_profile.fields.mention_policy.none', defaultMessage: 'Everybody' },
|
mentionPolicyNone: { id: 'edit_profile.fields.mention_policy.none', defaultMessage: 'Everybody' },
|
||||||
mentionPolicyOnlyKnown: {
|
mentionPolicyOnlyKnown: {
|
||||||
id: 'edit_profile.fields.mention_policy.only_known',
|
id: 'edit_profile.fields.mention_policy.only_known',
|
||||||
@@ -825,7 +824,7 @@ const EditProfilePage: React.FC = () => {
|
|||||||
|
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<Button to='/settings' theme='tertiary'>
|
<Button to='/settings' theme='tertiary'>
|
||||||
{intl.formatMessage(messages.cancel)}
|
<FormattedMessage id='common.cancel' defaultMessage='Cancel' />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button theme='primary' type='submit' disabled={isLoading}>
|
<Button theme='primary' type='submit' disabled={isLoading}>
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ const messages = defineMessages({
|
|||||||
defaultMessage: 'Filter deleted successfully',
|
defaultMessage: 'Filter deleted successfully',
|
||||||
},
|
},
|
||||||
deleteError: { id: 'column.filters.delete.error', defaultMessage: 'Error deleting filter' },
|
deleteError: { id: 'column.filters.delete.error', defaultMessage: 'Error deleting filter' },
|
||||||
edit: { id: 'column.filters.edit', defaultMessage: 'Edit filter' },
|
|
||||||
delete: { id: 'column.filters.delete', defaultMessage: 'Delete' },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const contexts = {
|
const contexts = {
|
||||||
@@ -142,10 +140,10 @@ const FiltersPage = () => {
|
|||||||
</Stack>
|
</Stack>
|
||||||
<HStack space={2} justifyContent='end'>
|
<HStack space={2} justifyContent='end'>
|
||||||
<Button theme='primary' to='/filters/$filterId' params={{ filterId: filter.id }}>
|
<Button theme='primary' to='/filters/$filterId' params={{ filterId: filter.id }}>
|
||||||
{intl.formatMessage(messages.edit)}
|
<FormattedMessage id='column.filters.edit' defaultMessage='Edit filter' />
|
||||||
</Button>
|
</Button>
|
||||||
<Button theme='danger' onClick={handleFilterDelete(filter.id)}>
|
<Button theme='danger' onClick={handleFilterDelete(filter.id)}>
|
||||||
{intl.formatMessage(messages.delete)}
|
<FormattedMessage id='column.filters.delete' defaultMessage='Delete' />
|
||||||
</Button>
|
</Button>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -43,4 +43,4 @@
|
|||||||
&--current button {
|
&--current button {
|
||||||
@apply border-transparent bg-danger-100 dark:bg-danger-900 text-danger-600 dark:text-danger-200 hover:bg-danger-600 hover:text-gray-100 dark:hover:text-gray-100 dark:hover:bg-danger-500 focus:ring-danger-500;
|
@apply border-transparent bg-danger-100 dark:bg-danger-900 text-danger-600 dark:text-danger-200 hover:bg-danger-600 hover:text-gray-100 dark:hover:text-gray-100 dark:hover:bg-danger-500 focus:ring-danger-500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
.⁂-detailed-status {
|
.⁂-detailed-status {
|
||||||
.⁂-status-reactions-bar {
|
.⁂-status-reactions-bar {
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.⁂-status-reactions-bar {
|
.⁂-status-reactions-bar {
|
||||||
|
|||||||
Reference in New Issue
Block a user