Merge remote-tracking branch 'soapbox/develop' into rss-button
This commit is contained in:
@@ -1,53 +0,0 @@
|
||||
import classNames from 'clsx';
|
||||
import React from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import { Text } from 'soapbox/components/ui';
|
||||
import DropdownMenu from 'soapbox/containers/dropdown_menu_container';
|
||||
|
||||
import type { Menu } from 'soapbox/components/dropdown_menu';
|
||||
|
||||
const messages = defineMessages({
|
||||
collapse: { id: 'accordion.collapse', defaultMessage: 'Collapse' },
|
||||
expand: { id: 'accordion.expand', defaultMessage: 'Expand' },
|
||||
});
|
||||
|
||||
interface IAccordion {
|
||||
headline: React.ReactNode,
|
||||
children?: React.ReactNode,
|
||||
menu?: Menu,
|
||||
expanded?: boolean,
|
||||
onToggle?: (value: boolean) => void,
|
||||
}
|
||||
|
||||
const Accordion: React.FC<IAccordion> = ({ headline, children, menu, expanded = false, onToggle = () => {} }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const handleToggle = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
onToggle(!expanded);
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classNames('accordion', { 'accordion--expanded': expanded })}>
|
||||
{menu && (
|
||||
<div className='accordion__menu'>
|
||||
<DropdownMenu items={menu} src={require('@tabler/icons/dots-vertical.svg')} />
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
type='button'
|
||||
className='accordion__title'
|
||||
onClick={handleToggle}
|
||||
title={intl.formatMessage(expanded ? messages.collapse : messages.expand)}
|
||||
>
|
||||
<Text weight='bold'>{headline}</Text>
|
||||
</button>
|
||||
<div className='accordion__content'>
|
||||
<Text>{children}</Text>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Accordion;
|
||||
@@ -2,9 +2,9 @@ import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
import { Column } from 'soapbox/components/ui';
|
||||
import DropdownMenu from 'soapbox/containers/dropdown_menu_container';
|
||||
import DropdownMenu from 'soapbox/containers/dropdown-menu-container';
|
||||
|
||||
import ColumnHeader from './column_header';
|
||||
import ColumnHeader from './column-header';
|
||||
|
||||
// Yes, there are 3 types of columns at this point, but this one is better, I swear
|
||||
export default class BetterColumn extends React.PureComponent {
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import IconButton from 'soapbox/components/icon_button';
|
||||
import IconButton from 'soapbox/components/icon-button';
|
||||
|
||||
const messages = defineMessages({
|
||||
error: { id: 'bundle_modal_error.message', defaultMessage: 'Something went wrong while loading this page.' },
|
||||
@@ -32,7 +32,7 @@ const BundleModalError: React.FC<IBundleModalError> = ({ onRetry, onClose }) =>
|
||||
<div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className='error-modal__nav onboarding-modal__skip'
|
||||
className='error-modal__nav'
|
||||
>
|
||||
{intl.formatMessage(messages.close)}
|
||||
</button>
|
||||
@@ -3,10 +3,10 @@ import React from 'react';
|
||||
const emptyComponent = () => null;
|
||||
const noop = () => { };
|
||||
|
||||
interface BundleProps {
|
||||
export interface BundleProps {
|
||||
fetchComponent: () => Promise<any>,
|
||||
loading: React.ComponentType,
|
||||
error: React.ComponentType<{ onRetry: (props: BundleProps) => void }>,
|
||||
error: React.ComponentType<{ onRetry: (props?: BundleProps) => void }>,
|
||||
children: (mod: any) => React.ReactNode,
|
||||
renderDelay?: number,
|
||||
onFetch: () => void,
|
||||
@@ -57,7 +57,7 @@ class Bundle extends React.PureComponent<BundleProps, BundleState> {
|
||||
}
|
||||
}
|
||||
|
||||
load = (props: BundleProps) => {
|
||||
load = (props?: BundleProps) => {
|
||||
const { fetchComponent, onFetch, onFetchSuccess, onFetchFail, renderDelay } = props || this.props;
|
||||
const cachedMod = Bundle.cache.get(fetchComponent);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
|
||||
// import classNames from 'clsx';
|
||||
// import Icon from 'soapbox/components/icon';
|
||||
import SubNavigation from 'soapbox/components/sub_navigation';
|
||||
import SubNavigation from 'soapbox/components/sub-navigation';
|
||||
|
||||
interface IColumnHeader {
|
||||
icon?: string,
|
||||
@@ -3,7 +3,7 @@ import React from 'react';
|
||||
import Pullable from 'soapbox/components/pullable';
|
||||
import { Column } from 'soapbox/components/ui';
|
||||
|
||||
import ColumnHeader from './column_header';
|
||||
import ColumnHeader from './column-header';
|
||||
|
||||
import type { IColumn } from 'soapbox/components/ui/column/column';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { fetchPatronInstance } from 'soapbox/actions/patron';
|
||||
import { Widget, Button, ProgressBar, Text } from 'soapbox/components/ui';
|
||||
import { Widget, Button, ProgressBar, Text, Stack } from 'soapbox/components/ui';
|
||||
import { useAppSelector, useAppDispatch } from 'soapbox/hooks';
|
||||
|
||||
/** Open link in a new tab. */
|
||||
@@ -42,7 +42,7 @@ const FundingPanel: React.FC = () => {
|
||||
let ratioText;
|
||||
|
||||
if (goalReached) {
|
||||
ratioText = <><strong>{moneyFormat(goal)}</strong> per month<span className='funding-panel__reached'>— reached!</span></>;
|
||||
ratioText = <><strong>{moneyFormat(goal)}</strong> per month <span>— reached!</span></>;
|
||||
} else {
|
||||
ratioText = <><strong>{moneyFormat(amount)} out of {moneyFormat(goal)}</strong> per month</>;
|
||||
}
|
||||
@@ -56,18 +56,19 @@ const FundingPanel: React.FC = () => {
|
||||
title={<FormattedMessage id='patron.title' defaultMessage='Funding Goal' />}
|
||||
onActionClick={handleDonateClick}
|
||||
>
|
||||
<div className='funding-panel__ratio'>
|
||||
<Text>{ratioText}</Text>
|
||||
</div>
|
||||
<ProgressBar progress={amount / goal} />
|
||||
<div className='funding-panel__description'>
|
||||
<Text>{goalText}</Text>
|
||||
</div>
|
||||
<div>
|
||||
<Button theme='secondary' onClick={handleDonateClick}>
|
||||
<FormattedMessage id='patron.donate' defaultMessage='Donate' />
|
||||
</Button>
|
||||
</div>
|
||||
<Stack space={4}>
|
||||
<Stack space={2}>
|
||||
<Text>{ratioText}</Text>
|
||||
<ProgressBar progress={amount / goal} />
|
||||
</Stack>
|
||||
|
||||
<Stack space={2}>
|
||||
<Text theme='muted'>{goalText}</Text>
|
||||
<Button block theme='primary' onClick={handleDonateClick}>
|
||||
<FormattedMessage id='patron.donate' defaultMessage='Donate' />
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Widget>
|
||||
);
|
||||
};
|
||||
@@ -3,7 +3,7 @@
|
||||
import React from 'react';
|
||||
import { useIntl, defineMessages } from 'react-intl';
|
||||
|
||||
import { pinHost, unpinHost } from 'soapbox/actions/remote_timeline';
|
||||
import { pinHost, unpinHost } from 'soapbox/actions/remote-timeline';
|
||||
import { Widget } from 'soapbox/components/ui';
|
||||
import { useAppSelector, useAppDispatch, useSettings } from 'soapbox/hooks';
|
||||
import { makeGetRemoteInstance } from 'soapbox/selectors';
|
||||
@@ -5,8 +5,8 @@ import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
|
||||
|
||||
import { openModal } from 'soapbox/actions/modals';
|
||||
import { Widget } from 'soapbox/components/ui';
|
||||
import DropdownMenu from 'soapbox/containers/dropdown_menu_container';
|
||||
import InstanceRestrictions from 'soapbox/features/federation_restrictions/components/instance_restrictions';
|
||||
import DropdownMenu from 'soapbox/containers/dropdown-menu-container';
|
||||
import InstanceRestrictions from 'soapbox/features/federation-restrictions/components/instance-restrictions';
|
||||
import { useAppSelector, useAppDispatch, useOwnAccount } from 'soapbox/hooks';
|
||||
import { makeGetRemoteInstance } from 'soapbox/selectors';
|
||||
|
||||
@@ -11,7 +11,7 @@ const ModalLoading = () => (
|
||||
</div>
|
||||
<div className='error-modal__footer'>
|
||||
<div>
|
||||
<button className='error-modal__nav onboarding-modal__skip' />
|
||||
<button className='error-modal__nav' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,7 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
import Base from 'soapbox/components/modal_root';
|
||||
import Base from 'soapbox/components/modal-root';
|
||||
import {
|
||||
MediaModal,
|
||||
VideoModal,
|
||||
@@ -34,10 +33,11 @@ import {
|
||||
AccountModerationModal,
|
||||
} from 'soapbox/features/ui/util/async-components';
|
||||
|
||||
import BundleContainer from '../containers/bundle_container';
|
||||
import BundleContainer from '../containers/bundle-container';
|
||||
|
||||
import BundleModalError from './bundle_modal_error';
|
||||
import ModalLoading from './modal_loading';
|
||||
import { BundleProps } from './bundle';
|
||||
import BundleModalError from './bundle-modal-error';
|
||||
import ModalLoading from './modal-loading';
|
||||
|
||||
const MODAL_COMPONENTS = {
|
||||
'MEDIA': MediaModal,
|
||||
@@ -71,19 +71,21 @@ const MODAL_COMPONENTS = {
|
||||
'ACCOUNT_MODERATION': AccountModerationModal,
|
||||
};
|
||||
|
||||
export default class ModalRoot extends React.PureComponent {
|
||||
export type ModalType = keyof typeof MODAL_COMPONENTS | null;
|
||||
|
||||
static propTypes = {
|
||||
type: PropTypes.string,
|
||||
props: PropTypes.object,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
interface IModalRoot {
|
||||
type: ModalType,
|
||||
props?: Record<string, any> | null,
|
||||
onClose: (type?: ModalType) => void,
|
||||
}
|
||||
|
||||
export default class ModalRoot extends React.PureComponent<IModalRoot> {
|
||||
|
||||
getSnapshotBeforeUpdate() {
|
||||
return { visible: !!this.props.type };
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, { visible }) {
|
||||
componentDidUpdate(prevProps: IModalRoot, prevState: any, { visible }: any) {
|
||||
if (visible) {
|
||||
document.body.classList.add('with-modals');
|
||||
} else {
|
||||
@@ -91,15 +93,15 @@ export default class ModalRoot extends React.PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
renderLoading = modalId => () => {
|
||||
renderLoading = (modalId: string) => () => {
|
||||
return !['MEDIA', 'VIDEO', 'BOOST', 'CONFIRM', 'ACTIONS'].includes(modalId) ? <ModalLoading /> : null;
|
||||
}
|
||||
|
||||
renderError = (props) => {
|
||||
renderError: React.ComponentType<{ onRetry: (props?: BundleProps) => void }> = (props) => {
|
||||
return <BundleModalError {...props} onClose={this.onClickClose} />;
|
||||
}
|
||||
|
||||
onClickClose = (_) => {
|
||||
onClickClose = (_?: ModalType) => {
|
||||
const { onClose, type } = this.props;
|
||||
onClose(type);
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation
|
||||
import snackbar from 'soapbox/actions/snackbar';
|
||||
import Account from 'soapbox/components/account';
|
||||
import List, { ListItem } from 'soapbox/components/list';
|
||||
import MissingIndicator from 'soapbox/components/missing_indicator';
|
||||
import MissingIndicator from 'soapbox/components/missing-indicator';
|
||||
import OutlineBox from 'soapbox/components/outline-box';
|
||||
import { Button, Text, HStack, Modal, Stack, Toggle } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
|
||||
|
||||
@@ -4,13 +4,13 @@ import { FormattedMessage } from 'react-intl';
|
||||
import { spring } from 'react-motion';
|
||||
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import StatusContent from 'soapbox/components/status_content';
|
||||
import StatusContent from 'soapbox/components/status-content';
|
||||
import { Stack } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
|
||||
import Motion from '../util/optional_motion';
|
||||
import Motion from '../../util/optional-motion';
|
||||
|
||||
import type { Menu, MenuItem } from 'soapbox/components/dropdown_menu';
|
||||
import type { Menu, MenuItem } from 'soapbox/components/dropdown-menu';
|
||||
import type { Status as StatusEntity } from 'soapbox/types/entities';
|
||||
|
||||
interface IActionsModal {
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||
import { Modal, Spinner } from 'soapbox/components/ui';
|
||||
import Account from 'soapbox/features/birthdays/account';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
@@ -3,7 +3,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import { Modal, Stack, Text } from 'soapbox/components/ui';
|
||||
import ReplyIndicator from 'soapbox/features/compose/components/reply_indicator';
|
||||
import ReplyIndicator from 'soapbox/features/compose/components/reply-indicator';
|
||||
|
||||
import type { Status as StatusEntity } from 'soapbox/types/entities';
|
||||
|
||||
@@ -3,11 +3,11 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import { cancelReplyCompose } from 'soapbox/actions/compose';
|
||||
import { openModal, closeModal } from 'soapbox/actions/modals';
|
||||
import { checkComposeContent } from 'soapbox/components/modal_root';
|
||||
import { checkComposeContent } from 'soapbox/components/modal-root';
|
||||
import { Modal } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useCompose } from 'soapbox/hooks';
|
||||
|
||||
import ComposeForm from '../../compose/components/compose-form';
|
||||
import ComposeForm from '../../../compose/components/compose-form';
|
||||
|
||||
const messages = defineMessages({
|
||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Modal } from 'soapbox/components/ui';
|
||||
import DetailedCryptoAddress from 'soapbox/features/crypto_donate/components/detailed_crypto_address';
|
||||
import DetailedCryptoAddress from 'soapbox/features/crypto-donate/components/detailed-crypto-address';
|
||||
|
||||
import type { ICryptoAddress } from '../../crypto_donate/components/crypto_address';
|
||||
import type { ICryptoAddress } from '../../../crypto-donate/components/crypto-address';
|
||||
|
||||
const CryptoDonateModal: React.FC<ICryptoAddress & { onClose: () => void }> = ({ onClose, ...props }) => {
|
||||
|
||||
@@ -2,9 +2,9 @@ import { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||
import { Modal, Spinner } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
import { makeGetAccount } from 'soapbox/selectors';
|
||||
|
||||
@@ -3,7 +3,7 @@ import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { fetchFavourites } from 'soapbox/actions/interactions';
|
||||
import { Modal, Spinner, Stack } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
interface IFavouritesModal {
|
||||
|
||||
@@ -4,13 +4,13 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import ReactSwipeableViews from 'react-swipeable-views';
|
||||
|
||||
import ExtendedVideoPlayer from 'soapbox/components/extended_video_player';
|
||||
import ExtendedVideoPlayer from 'soapbox/components/extended-video-player';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import IconButton from 'soapbox/components/icon_button';
|
||||
import IconButton from 'soapbox/components/icon-button';
|
||||
import Audio from 'soapbox/features/audio';
|
||||
import Video from 'soapbox/features/video';
|
||||
|
||||
import ImageLoader from './image-loader';
|
||||
import ImageLoader from '../image-loader';
|
||||
|
||||
import type { List as ImmutableList } from 'immutable';
|
||||
import type { Account, Attachment, Status } from 'soapbox/types/entities';
|
||||
@@ -225,7 +225,6 @@ const MediaModal: React.FC<IMediaModal> = (props) => {
|
||||
muted
|
||||
controls={false}
|
||||
width={width}
|
||||
link={link}
|
||||
height={height}
|
||||
key={attachment.preview_url}
|
||||
alt={attachment.description}
|
||||
@@ -298,4 +297,4 @@ const MediaModal: React.FC<IMediaModal> = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default MediaModal;
|
||||
export default MediaModal;
|
||||
@@ -3,9 +3,9 @@ import React, { useCallback, useEffect } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { fetchStatusWithContext } from 'soapbox/actions/statuses';
|
||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||
import { Modal, Spinner } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
import { makeGetStatus } from 'soapbox/selectors';
|
||||
|
||||
@@ -3,11 +3,11 @@ import React, { useEffect, useState } from 'react';
|
||||
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import { fetchFavourites, fetchReactions } from 'soapbox/actions/interactions';
|
||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||
import { Emoji, Modal, Spinner, Tabs } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
import { ReactionRecord } from 'soapbox/reducers/user_lists';
|
||||
import { ReactionRecord } from 'soapbox/reducers/user-lists';
|
||||
|
||||
import type { Item } from 'soapbox/components/ui/tabs/tabs';
|
||||
|
||||
@@ -3,9 +3,9 @@ import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { fetchReblogs } from 'soapbox/actions/interactions';
|
||||
import { fetchStatus } from 'soapbox/actions/statuses';
|
||||
import ScrollableList from 'soapbox/components/scrollable_list';
|
||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||
import { Modal, Spinner } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
interface IReblogsModal {
|
||||
@@ -6,7 +6,7 @@ import { useAppSelector, useCompose } from 'soapbox/hooks';
|
||||
import { statusToMentionsAccountIdsArray } from 'soapbox/reducers/compose';
|
||||
import { makeGetStatus } from 'soapbox/selectors';
|
||||
|
||||
import Account from '../../reply_mentions/account';
|
||||
import Account from '../../../reply-mentions/account';
|
||||
|
||||
import type { Account as AccountEntity, Status as StatusEntity } from 'soapbox/types/entities';
|
||||
|
||||
@@ -5,9 +5,9 @@ import { blockAccount } from 'soapbox/actions/accounts';
|
||||
import { submitReport, submitReportSuccess, submitReportFail } from 'soapbox/actions/reports';
|
||||
import { expandAccountTimeline } from 'soapbox/actions/timelines';
|
||||
import AttachmentThumbs from 'soapbox/components/attachment-thumbs';
|
||||
import StatusContent from 'soapbox/components/status_content';
|
||||
import StatusContent from 'soapbox/components/status-content';
|
||||
import { Modal, ProgressBar, Stack, Text } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
import { useAccount, useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
import ConfirmationStep from './steps/confirmation-step';
|
||||
@@ -179,6 +179,7 @@ const ReportModal = ({ onClose }: IReportModal) => {
|
||||
<Modal
|
||||
title={<FormattedMessage id='report.target' defaultMessage='Reporting {target}' values={{ target: <strong>@{account.acct}</strong> }} />}
|
||||
onClose={onClose}
|
||||
cancelText={<FormattedMessage id='common.cancel' defaultMessage='Cancel' />}
|
||||
cancelAction={currentStep === Steps.THREE ? undefined : onClose}
|
||||
confirmationAction={handleNextStep}
|
||||
confirmationText={confirmationText}
|
||||
|
||||
@@ -7,7 +7,7 @@ import Toggle from 'react-toggle';
|
||||
import { changeReportBlock, changeReportForward } from 'soapbox/actions/reports';
|
||||
import { fetchRules } from 'soapbox/actions/rules';
|
||||
import { Button, FormGroup, HStack, Stack, Text } from 'soapbox/components/ui';
|
||||
import StatusCheckBox from 'soapbox/features/report/components/status_check_box';
|
||||
import StatusCheckBox from 'soapbox/features/report/components/status-check-box';
|
||||
import { useAppSelector, useFeatures } from 'soapbox/hooks';
|
||||
import { isRemote, getDomain } from 'soapbox/utils/accounts';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
import OtpInput from 'react-otp-input';
|
||||
|
||||
import { verifyCredentials } from 'soapbox/actions/auth';
|
||||
@@ -10,6 +10,37 @@ import { FormGroup, PhoneInput, Modal, Stack, Text } from 'soapbox/components/ui
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
import { getAccessToken } from 'soapbox/utils/auth';
|
||||
|
||||
const messages = defineMessages({
|
||||
verificationInvalid: {
|
||||
id: 'sms_verification.invalid',
|
||||
defaultMessage: 'Please enter a valid phone number.',
|
||||
},
|
||||
verificationSuccess: {
|
||||
id: 'sms_verification.success',
|
||||
defaultMessage: 'A verification code has been sent to your phone number.',
|
||||
},
|
||||
verificationFail: {
|
||||
id: 'sms_verification.fail',
|
||||
defaultMessage: 'Failed to send SMS message to your phone number.',
|
||||
},
|
||||
verificationExpired: {
|
||||
id: 'sms_verification.expired',
|
||||
defaultMessage: 'Your SMS token has expired.',
|
||||
},
|
||||
verifySms: {
|
||||
id: 'sms_verification.modal.verify_sms',
|
||||
defaultMessage: 'Verify SMS',
|
||||
},
|
||||
verifyNumber: {
|
||||
id: 'sms_verification.modal.verify_number',
|
||||
defaultMessage: 'Verify phone number',
|
||||
},
|
||||
verifyCode: {
|
||||
id: 'sms_verification.modal.verify_code',
|
||||
defaultMessage: 'Verify code',
|
||||
},
|
||||
});
|
||||
|
||||
interface IVerifySmsModal {
|
||||
onClose: (type: string) => void,
|
||||
}
|
||||
@@ -47,10 +78,7 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
||||
setStatus(Statuses.IDLE);
|
||||
dispatch(
|
||||
snackbar.error(
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.invalid',
|
||||
defaultMessage: 'Please enter a valid phone number.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationInvalid),
|
||||
),
|
||||
);
|
||||
return;
|
||||
@@ -59,10 +87,7 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
||||
dispatch(reRequestPhoneVerification(phone!)).then(() => {
|
||||
dispatch(
|
||||
snackbar.success(
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.success',
|
||||
defaultMessage: 'A verification code has been sent to your phone number.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationSuccess),
|
||||
),
|
||||
);
|
||||
})
|
||||
@@ -70,10 +95,7 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
||||
.catch(() => {
|
||||
dispatch(
|
||||
snackbar.error(
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.fail',
|
||||
defaultMessage: 'Failed to send SMS message to your phone number.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationFail),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -102,20 +124,11 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
||||
const confirmationText = useMemo(() => {
|
||||
switch (status) {
|
||||
case Statuses.IDLE:
|
||||
return intl.formatMessage({
|
||||
id: 'sms_verification.modal.verify_sms',
|
||||
defaultMessage: 'Verify SMS',
|
||||
});
|
||||
return intl.formatMessage(messages.verifySms);
|
||||
case Statuses.READY:
|
||||
return intl.formatMessage({
|
||||
id: 'sms_verification.modal.verify_number',
|
||||
defaultMessage: 'Verify phone number',
|
||||
});
|
||||
return intl.formatMessage(messages.verifyNumber);
|
||||
case Statuses.REQUESTED:
|
||||
return intl.formatMessage({
|
||||
id: 'sms_verification.modal.verify_code',
|
||||
defaultMessage: 'Verify code',
|
||||
});
|
||||
return intl.formatMessage(messages.verifyCode);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@@ -126,12 +139,13 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
||||
case Statuses.IDLE:
|
||||
return (
|
||||
<Text theme='muted'>
|
||||
{intl.formatMessage({
|
||||
id: 'sms_verification.modal.verify_help_text',
|
||||
defaultMessage: 'Verify your phone number to start using {instance}.',
|
||||
}, {
|
||||
instance: title,
|
||||
})}
|
||||
<FormattedMessage
|
||||
id='sms_verification.modal.verify_help_text'
|
||||
defaultMessage='Verify your phone number to start using {instance}.'
|
||||
values={{
|
||||
instance: title,
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
);
|
||||
case Statuses.READY:
|
||||
@@ -149,10 +163,10 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
||||
return (
|
||||
<>
|
||||
<Text theme='muted' size='sm' align='center'>
|
||||
{intl.formatMessage({
|
||||
id: 'sms_verification.modal.enter_code',
|
||||
defaultMessage: 'We sent you a 6-digit code via SMS. Enter it below.',
|
||||
})}
|
||||
<FormattedMessage
|
||||
id='sms_verification.modal.enter_code'
|
||||
defaultMessage='We sent you a 6-digit code via SMS. Enter it below.'
|
||||
/>
|
||||
</Text>
|
||||
|
||||
<OtpInput
|
||||
@@ -184,10 +198,7 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
||||
})
|
||||
.catch(() => dispatch(
|
||||
snackbar.error(
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.invalid',
|
||||
defaultMessage: 'Your SMS token has expired.',
|
||||
}),
|
||||
intl.formatMessage(messages.verificationExpired),
|
||||
),
|
||||
));
|
||||
};
|
||||
@@ -201,10 +212,10 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
||||
return (
|
||||
<Modal
|
||||
title={
|
||||
intl.formatMessage({
|
||||
id: 'sms_verification.modal.verify_title',
|
||||
defaultMessage: 'Verify your phone number',
|
||||
})
|
||||
<FormattedMessage
|
||||
id='sms_verification.modal.verify_title'
|
||||
defaultMessage='Verify your phone number'
|
||||
/>
|
||||
}
|
||||
onClose={() => onClose('VERIFY_SMS')}
|
||||
cancelAction={status === Statuses.IDLE ? () => onClose('VERIFY_SMS') : undefined}
|
||||
@@ -212,10 +223,12 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
||||
confirmationAction={onConfirmationClick}
|
||||
confirmationText={confirmationText}
|
||||
secondaryAction={status === Statuses.REQUESTED ? resendVerificationCode : undefined}
|
||||
secondaryText={status === Statuses.REQUESTED ? intl.formatMessage({
|
||||
id: 'sms_verification.modal.resend_code',
|
||||
defaultMessage: 'Resend verification code?',
|
||||
}) : undefined}
|
||||
secondaryText={status === Statuses.REQUESTED ? (
|
||||
<FormattedMessage
|
||||
id='sms_verification.modal.resend_code'
|
||||
defaultMessage='Resend verification code?'
|
||||
/>
|
||||
) : undefined}
|
||||
secondaryDisabled={requestedAnother}
|
||||
>
|
||||
<Stack space={4}>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import classNames from 'clsx';
|
||||
import React from 'react';
|
||||
|
||||
import StatusContent from 'soapbox/components/status-content';
|
||||
import StatusReplyMentions from 'soapbox/components/status-reply-mentions';
|
||||
import StatusContent from 'soapbox/components/status_content';
|
||||
import { Card, HStack } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import PlaceholderCard from 'soapbox/features/placeholder/components/placeholder_card';
|
||||
import PlaceholderMediaGallery from 'soapbox/features/placeholder/components/placeholder_media_gallery';
|
||||
import QuotedStatus from 'soapbox/features/status/containers/quoted_status_container';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
import PlaceholderCard from 'soapbox/features/placeholder/components/placeholder-card';
|
||||
import PlaceholderMediaGallery from 'soapbox/features/placeholder/components/placeholder-media-gallery';
|
||||
import QuotedStatus from 'soapbox/features/status/containers/quoted-status-container';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
import { buildStatus } from '../util/pending_status_builder';
|
||||
import { buildStatus } from '../util/pending-status-builder';
|
||||
|
||||
import PollPreview from './poll_preview';
|
||||
import PollPreview from './poll-preview';
|
||||
|
||||
import type { Account as AccountEntity, Status as StatusEntity } from 'soapbox/types/entities';
|
||||
|
||||
@@ -4,8 +4,8 @@ import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { fetchPinnedAccounts } from 'soapbox/actions/accounts';
|
||||
import { Widget } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
import BundleContainer from 'soapbox/features/ui/containers/bundle-container';
|
||||
import { WhoToFollowPanel } from 'soapbox/features/ui/util/async-components';
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
@@ -4,11 +4,11 @@ import { FormattedList, FormattedMessage } from 'react-intl';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { fetchAccountFamiliarFollowers } from 'soapbox/actions/familiar_followers';
|
||||
import { fetchAccountFamiliarFollowers } from 'soapbox/actions/familiar-followers';
|
||||
import { openModal } from 'soapbox/actions/modals';
|
||||
import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper';
|
||||
import HoverRefWrapper from 'soapbox/components/hover-ref-wrapper';
|
||||
import { Text } from 'soapbox/components/ui';
|
||||
import VerificationBadge from 'soapbox/components/verification_badge';
|
||||
import VerificationBadge from 'soapbox/components/verification-badge';
|
||||
import { useAppSelector, useFeatures } from 'soapbox/hooks';
|
||||
import { makeGetAccount } from 'soapbox/selectors';
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from 'react';
|
||||
import { defineMessages, useIntl, FormattedMessage, FormatDateOptions } from 'react-intl';
|
||||
|
||||
import { Widget, Stack, HStack, Icon, Text } from 'soapbox/components/ui';
|
||||
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
|
||||
import BundleContainer from 'soapbox/features/ui/containers/bundle-container';
|
||||
import { CryptoAddress } from 'soapbox/features/ui/util/async-components';
|
||||
|
||||
import type { Account, Field } from 'soapbox/types/entities';
|
||||
@@ -5,14 +5,14 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||
|
||||
import Badge from 'soapbox/components/badge';
|
||||
import { Icon, HStack, Stack, Text } from 'soapbox/components/ui';
|
||||
import VerificationBadge from 'soapbox/components/verification_badge';
|
||||
import VerificationBadge from 'soapbox/components/verification-badge';
|
||||
import { useSoapboxConfig } from 'soapbox/hooks';
|
||||
import { isLocal } from 'soapbox/utils/accounts';
|
||||
import { badgeToTag, getBadges as getAccountBadges } from 'soapbox/utils/badges';
|
||||
import { capitalize } from 'soapbox/utils/strings';
|
||||
|
||||
import ProfileFamiliarFollowers from './profile_familiar_followers';
|
||||
import ProfileStats from './profile_stats';
|
||||
import ProfileFamiliarFollowers from './profile-familiar-followers';
|
||||
import ProfileStats from './profile-stats';
|
||||
|
||||
import type { Account } from 'soapbox/types/entities';
|
||||
|
||||
@@ -5,11 +5,11 @@ import { useDispatch } from 'react-redux';
|
||||
|
||||
import { openModal } from 'soapbox/actions/modals';
|
||||
import { expandAccountMediaTimeline } from 'soapbox/actions/timelines';
|
||||
import { Spinner, Widget } from 'soapbox/components/ui';
|
||||
import { Spinner, Text, Widget } from 'soapbox/components/ui';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
import { getAccountGallery } from 'soapbox/selectors';
|
||||
|
||||
import MediaItem from '../../account_gallery/components/media_item';
|
||||
import MediaItem from '../../account-gallery/components/media-item';
|
||||
|
||||
import type { Account, Attachment } from 'soapbox/types/entities';
|
||||
|
||||
@@ -52,7 +52,7 @@ const ProfileMediaPanel: React.FC<IProfileMediaPanel> = ({ account }) => {
|
||||
|
||||
if (!nineAttachments.isEmpty()) {
|
||||
return (
|
||||
<div className='media-panel__list'>
|
||||
<div className='flex flex-wrap'>
|
||||
{nineAttachments.map((attachment, _index) => (
|
||||
<MediaItem
|
||||
key={`${attachment.getIn(['status', 'id'])}+${attachment.id}`}
|
||||
@@ -65,9 +65,9 @@ const ProfileMediaPanel: React.FC<IProfileMediaPanel> = ({ account }) => {
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className='media-panel__empty'>
|
||||
<Text size='sm' theme='muted'>
|
||||
<FormattedMessage id='media_panel.empty_message' defaultMessage='No media found.' />
|
||||
</div>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -75,7 +75,7 @@ const ProfileMediaPanel: React.FC<IProfileMediaPanel> = ({ account }) => {
|
||||
return (
|
||||
<Widget title={<FormattedMessage id='media_panel.title' defaultMessage='Media' />}>
|
||||
{account && (
|
||||
<div className='media-panel__content'>
|
||||
<div className='w-full py-2'>
|
||||
{loading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
@@ -5,7 +5,7 @@ import { defineMessages } from 'react-intl';
|
||||
|
||||
import { dequeueTimeline, scrollTopTimeline } from 'soapbox/actions/timelines';
|
||||
import ScrollTopButton from 'soapbox/components/scroll-top-button';
|
||||
import StatusList, { IStatusList } from 'soapbox/components/status_list';
|
||||
import StatusList, { IStatusList } from 'soapbox/components/status-list';
|
||||
import { useAppSelector, useAppDispatch } from 'soapbox/hooks';
|
||||
import { makeGetStatusIds } from 'soapbox/selectors';
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { spring } from 'react-motion';
|
||||
|
||||
import { Icon, Stack, Text } from 'soapbox/components/ui';
|
||||
|
||||
import Motion from '../../ui/util/optional_motion';
|
||||
import Motion from '../util/optional-motion';
|
||||
|
||||
interface IUploadArea {
|
||||
/** Whether the upload area is active. */
|
||||
@@ -3,9 +3,9 @@ import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import Avatar from 'soapbox/components/avatar';
|
||||
import StillImage from 'soapbox/components/still_image';
|
||||
import StillImage from 'soapbox/components/still-image';
|
||||
import { HStack, Stack, Text } from 'soapbox/components/ui';
|
||||
import VerificationBadge from 'soapbox/components/verification_badge';
|
||||
import VerificationBadge from 'soapbox/components/verification-badge';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
import { makeGetAccount } from 'soapbox/selectors';
|
||||
import { getAcct } from 'soapbox/utils/accounts';
|
||||
@@ -3,7 +3,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { Text, Widget } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
import PlaceholderSidebarSuggestions from 'soapbox/features/placeholder/components/placeholder-sidebar-suggestions';
|
||||
import { useDismissSuggestion, useSuggestions } from 'soapbox/queries/suggestions';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user