sforkowany z mirror/soapbox
Merge branch 'fc' into 'develop'
TypeScript conversions See merge request soapbox-pub/soapbox-fe!1285edit-profile-fix
commit
1ebd66f6c1
|
@ -20,7 +20,7 @@ interface IHoverRefWrapper {
|
||||||
/** Makes a profile hover card appear when the wrapped element is hovered. */
|
/** Makes a profile hover card appear when the wrapped element is hovered. */
|
||||||
export const HoverRefWrapper: React.FC<IHoverRefWrapper> = ({ accountId, children, inline = false }) => {
|
export const HoverRefWrapper: React.FC<IHoverRefWrapper> = ({ accountId, children, inline = false }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const ref = useRef<HTMLElement>();
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const Elem: keyof JSX.IntrinsicElements = inline ? 'span' : 'div';
|
const Elem: keyof JSX.IntrinsicElements = inline ? 'span' : 'div';
|
||||||
|
|
||||||
const handleMouseEnter = () => {
|
const handleMouseEnter = () => {
|
||||||
|
@ -41,7 +41,6 @@ export const HoverRefWrapper: React.FC<IHoverRefWrapper> = ({ accountId, childre
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Elem
|
<Elem
|
||||||
// @ts-ignore: not sure how to fix :\
|
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className='hover-ref-wrapper'
|
className='hover-ref-wrapper'
|
||||||
onMouseEnter={handleMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { usePopper } from 'react-popper';
|
import { usePopper } from 'react-popper';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
import { fetchRelationships } from 'soapbox/actions/accounts';
|
import { fetchRelationships } from 'soapbox/actions/accounts';
|
||||||
|
@ -16,14 +13,18 @@ import Badge from 'soapbox/components/badge';
|
||||||
import ActionButton from 'soapbox/features/ui/components/action_button';
|
import ActionButton from 'soapbox/features/ui/components/action_button';
|
||||||
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
|
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
|
||||||
import { UserPanel } from 'soapbox/features/ui/util/async-components';
|
import { UserPanel } from 'soapbox/features/ui/util/async-components';
|
||||||
|
import { useAppSelector, useAppDispatch } from 'soapbox/hooks';
|
||||||
import { makeGetAccount } from 'soapbox/selectors';
|
import { makeGetAccount } from 'soapbox/selectors';
|
||||||
|
|
||||||
import { showProfileHoverCard } from './hover_ref_wrapper';
|
import { showProfileHoverCard } from './hover_ref_wrapper';
|
||||||
import { Card, CardBody, Stack, Text } from './ui';
|
import { Card, CardBody, Stack, Text } from './ui';
|
||||||
|
|
||||||
|
import type { AppDispatch } from 'soapbox/store';
|
||||||
|
import type { Account } from 'soapbox/types/entities';
|
||||||
|
|
||||||
const getAccount = makeGetAccount();
|
const getAccount = makeGetAccount();
|
||||||
|
|
||||||
const getBadges = (account) => {
|
const getBadges = (account: Account): JSX.Element[] => {
|
||||||
const badges = [];
|
const badges = [];
|
||||||
|
|
||||||
if (account.admin) {
|
if (account.admin) {
|
||||||
|
@ -43,29 +44,34 @@ const getBadges = (account) => {
|
||||||
return badges;
|
return badges;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseEnter = (dispatch) => {
|
const handleMouseEnter = (dispatch: AppDispatch): React.MouseEventHandler => {
|
||||||
return e => {
|
return () => {
|
||||||
dispatch(updateProfileHoverCard());
|
dispatch(updateProfileHoverCard());
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseLeave = (dispatch) => {
|
const handleMouseLeave = (dispatch: AppDispatch): React.MouseEventHandler => {
|
||||||
return e => {
|
return () => {
|
||||||
dispatch(closeProfileHoverCard(true));
|
dispatch(closeProfileHoverCard(true));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ProfileHoverCard = ({ visible }) => {
|
interface IProfileHoverCard {
|
||||||
const dispatch = useDispatch();
|
visible: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Popup profile preview that appears when hovering avatars and display names. */
|
||||||
|
export const ProfileHoverCard: React.FC<IProfileHoverCard> = ({ visible = true }) => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const [popperElement, setPopperElement] = useState(null);
|
const [popperElement, setPopperElement] = useState<HTMLElement | null>(null);
|
||||||
|
|
||||||
const me = useSelector(state => state.get('me'));
|
const me = useAppSelector(state => state.me);
|
||||||
const accountId = useSelector(state => state.getIn(['profile_hover_card', 'accountId']));
|
const accountId: string | undefined = useAppSelector(state => state.profile_hover_card.get<string | undefined>('accountId', undefined));
|
||||||
const account = useSelector(state => accountId && getAccount(state, accountId));
|
const account = useAppSelector(state => accountId && getAccount(state, accountId));
|
||||||
const targetRef = useSelector(state => state.getIn(['profile_hover_card', 'ref', 'current']));
|
const targetRef = useAppSelector(state => state.profile_hover_card.getIn(['ref', 'current']) as Element | null);
|
||||||
const badges = account ? getBadges(account) : [];
|
const badges = account ? getBadges(account) : [];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -86,8 +92,8 @@ export const ProfileHoverCard = ({ visible }) => {
|
||||||
const { styles, attributes } = usePopper(targetRef, popperElement);
|
const { styles, attributes } = usePopper(targetRef, popperElement);
|
||||||
|
|
||||||
if (!account) return null;
|
if (!account) return null;
|
||||||
const accountBio = { __html: account.get('note_emojified') };
|
const accountBio = { __html: account.note_emojified };
|
||||||
const followedBy = me !== account.get('id') && account.getIn(['relationship', 'followed_by']);
|
const followedBy = me !== account.id && account.relationship.get('followed_by') === true;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -115,7 +121,7 @@ export const ProfileHoverCard = ({ visible }) => {
|
||||||
)}
|
)}
|
||||||
</BundleContainer>
|
</BundleContainer>
|
||||||
|
|
||||||
{account.getIn(['source', 'note'], '').length > 0 && (
|
{account.source.get('note', '').length > 0 && (
|
||||||
<Text size='sm' dangerouslySetInnerHTML={accountBio} />
|
<Text size='sm' dangerouslySetInnerHTML={accountBio} />
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
@ -134,14 +140,4 @@ export const ProfileHoverCard = ({ visible }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
ProfileHoverCard.propTypes = {
|
|
||||||
visible: PropTypes.bool,
|
|
||||||
accountId: PropTypes.string,
|
|
||||||
account: ImmutablePropTypes.record,
|
|
||||||
};
|
|
||||||
|
|
||||||
ProfileHoverCard.defaultProps = {
|
|
||||||
visible: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ProfileHoverCard;
|
export default ProfileHoverCard;
|
|
@ -1,4 +1,3 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
@ -75,9 +74,4 @@ const DeleteAccount = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
DeleteAccount.propTypes = {
|
|
||||||
intl: PropTypes.object,
|
|
||||||
dispatch: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DeleteAccount;
|
export default DeleteAccount;
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import PlaceholderAvatar from './placeholder_avatar';
|
|
||||||
import PlaceholderDisplayName from './placeholder_display_name';
|
|
||||||
|
|
||||||
export default class PlaceholderAccount extends React.Component {
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className='account'>
|
|
||||||
<div className='account__wrapper'>
|
|
||||||
<span className='account__display-name'>
|
|
||||||
<div className='account__avatar-wrapper'>
|
|
||||||
<PlaceholderAvatar size={36} />
|
|
||||||
</div>
|
|
||||||
<PlaceholderDisplayName minLength={3} maxLength={25} />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import PlaceholderAvatar from './placeholder_avatar';
|
||||||
|
import PlaceholderDisplayName from './placeholder_display_name';
|
||||||
|
|
||||||
|
/** Fake account to display while data is loading. */
|
||||||
|
const PlaceholderAccount: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className='account'>
|
||||||
|
<div className='account__wrapper'>
|
||||||
|
<span className='account__display-name'>
|
||||||
|
<div className='account__avatar-wrapper'>
|
||||||
|
<PlaceholderAvatar size={36} />
|
||||||
|
</div>
|
||||||
|
<PlaceholderDisplayName minLength={3} maxLength={25} />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PlaceholderAccount;
|
|
@ -1,7 +1,11 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
const PlaceholderAvatar = ({ size }) => {
|
interface IPlaceholderAvatar {
|
||||||
|
size: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fake avatar to display while data is loading. */
|
||||||
|
const PlaceholderAvatar: React.FC<IPlaceholderAvatar> = ({ size }) => {
|
||||||
const style = React.useMemo(() => {
|
const style = React.useMemo(() => {
|
||||||
if (!size) {
|
if (!size) {
|
||||||
return {};
|
return {};
|
||||||
|
@ -17,13 +21,8 @@ const PlaceholderAvatar = ({ size }) => {
|
||||||
<div
|
<div
|
||||||
className='rounded-full bg-slate-200 dark:bg-slate-700'
|
className='rounded-full bg-slate-200 dark:bg-slate-700'
|
||||||
style={style}
|
style={style}
|
||||||
alt=''
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
PlaceholderAvatar.propTypes = {
|
|
||||||
size: PropTypes.number.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default PlaceholderAvatar;
|
export default PlaceholderAvatar;
|
|
@ -3,7 +3,8 @@ import * as React from 'react';
|
||||||
|
|
||||||
import { randomIntFromInterval, generateText } from '../utils';
|
import { randomIntFromInterval, generateText } from '../utils';
|
||||||
|
|
||||||
const PlaceholderCard = () => (
|
/** Fake link preview to display while data is loading. */
|
||||||
|
const PlaceholderCard: React.FC = () => (
|
||||||
<div className={classNames('status-card', {
|
<div className={classNames('status-card', {
|
||||||
'animate-pulse': true,
|
'animate-pulse': true,
|
||||||
})}
|
})}
|
|
@ -1,32 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { randomIntFromInterval, generateText } from '../utils';
|
|
||||||
|
|
||||||
import PlaceholderAvatar from './placeholder_avatar';
|
|
||||||
import PlaceholderDisplayName from './placeholder_display_name';
|
|
||||||
|
|
||||||
export default class PlaceholderAccount extends React.Component {
|
|
||||||
|
|
||||||
render() {
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { randomIntFromInterval, generateText } from '../utils';
|
||||||
|
|
||||||
|
import PlaceholderAvatar from './placeholder_avatar';
|
||||||
|
import PlaceholderDisplayName from './placeholder_display_name';
|
||||||
|
|
||||||
|
/** Fake chat to display while data is loading. */
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PlaceholderChat;
|
|
@ -1,9 +1,14 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { randomIntFromInterval, generateText } from '../utils';
|
import { randomIntFromInterval, generateText } from '../utils';
|
||||||
|
|
||||||
const PlaceholderDisplayName = ({ minLength, maxLength }) => {
|
interface IPlaceholderDisplayName {
|
||||||
|
maxLength: number,
|
||||||
|
minLength: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fake display name to show when data is loading. */
|
||||||
|
const PlaceholderDisplayName: React.FC<IPlaceholderDisplayName> = ({ minLength, maxLength }) => {
|
||||||
const length = randomIntFromInterval(maxLength, minLength);
|
const length = randomIntFromInterval(maxLength, minLength);
|
||||||
const acctLength = randomIntFromInterval(maxLength, minLength);
|
const acctLength = randomIntFromInterval(maxLength, minLength);
|
||||||
|
|
||||||
|
@ -15,9 +20,4 @@ const PlaceholderDisplayName = ({ minLength, maxLength }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
PlaceholderDisplayName.propTypes = {
|
|
||||||
maxLength: PropTypes.number.isRequired,
|
|
||||||
minLength: PropTypes.number.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default PlaceholderDisplayName;
|
export default PlaceholderDisplayName;
|
|
@ -1,21 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { generateText, randomIntFromInterval } from '../utils';
|
|
||||||
|
|
||||||
export default class PlaceholderHashtag extends React.Component {
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const length = randomIntFromInterval(15, 30);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='placeholder-hashtag'>
|
|
||||||
<div className='trends__item'>
|
|
||||||
<div className='trends__item__name'>
|
|
||||||
{generateText(length)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { generateText, randomIntFromInterval } from '../utils';
|
||||||
|
|
||||||
|
/** Fake hashtag to display while data is loading. */
|
||||||
|
const PlaceholderHashtag: React.FC = () => {
|
||||||
|
const length = randomIntFromInterval(15, 30);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='placeholder-hashtag'>
|
||||||
|
<div className='trends__item'>
|
||||||
|
<div className='trends__item__name'>
|
||||||
|
{generateText(length)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PlaceholderHashtag;
|
|
@ -1,17 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import PlaceholderStatus from './placeholder_status';
|
|
||||||
|
|
||||||
export default class PlaceholderMaterialStatus extends React.Component {
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className='material-status' tabIndex={-1} aria-hidden>
|
|
||||||
<div className='material-status__status' tabIndex={0}>
|
|
||||||
<PlaceholderStatus {...this.props} focusable={false} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import PlaceholderStatus from './placeholder_status';
|
||||||
|
|
||||||
|
/** Fake material status to display while data is loading. */
|
||||||
|
const PlaceholderMaterialStatus: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className='material-status' tabIndex={-1} aria-hidden>
|
||||||
|
<div className='material-status__status' tabIndex={0}>
|
||||||
|
<PlaceholderStatus />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PlaceholderMaterialStatus;
|
|
@ -4,6 +4,7 @@ import PlaceholderAvatar from './placeholder_avatar';
|
||||||
import PlaceholderDisplayName from './placeholder_display_name';
|
import PlaceholderDisplayName from './placeholder_display_name';
|
||||||
import PlaceholderStatusContent from './placeholder_status_content';
|
import PlaceholderStatusContent from './placeholder_status_content';
|
||||||
|
|
||||||
|
/** Fake notification to display while data is loading. */
|
||||||
const PlaceholderNotification = () => (
|
const PlaceholderNotification = () => (
|
||||||
<div className='bg-white dark:bg-slate-800 px-4 py-6 sm:p-6'>
|
<div className='bg-white dark:bg-slate-800 px-4 py-6 sm:p-6'>
|
||||||
<div className='w-full animate-pulse'>
|
<div className='w-full animate-pulse'>
|
|
@ -9,7 +9,8 @@ interface IPlaceholderStatus {
|
||||||
thread?: boolean
|
thread?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const PlaceholderStatus = ({ thread = false }: IPlaceholderStatus) => (
|
/** Fake status to display while data is loading. */
|
||||||
|
const PlaceholderStatus: React.FC<IPlaceholderStatus> = ({ thread = false }) => (
|
||||||
<div
|
<div
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'status-placeholder bg-white dark:bg-slate-800': true,
|
'status-placeholder bg-white dark:bg-slate-800': true,
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { randomIntFromInterval, generateText } from '../utils';
|
import { randomIntFromInterval, generateText } from '../utils';
|
||||||
|
|
||||||
const PlaceholderStatusContent = ({ minLength, maxLength }) => {
|
interface IPlaceholderStatusContent {
|
||||||
|
maxLength: number,
|
||||||
|
minLength: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fake status content while data is loading. */
|
||||||
|
const PlaceholderStatusContent: React.FC<IPlaceholderStatusContent> = ({ minLength, maxLength }) => {
|
||||||
const length = randomIntFromInterval(maxLength, minLength);
|
const length = randomIntFromInterval(maxLength, minLength);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -13,9 +18,4 @@ const PlaceholderStatusContent = ({ minLength, maxLength }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
PlaceholderStatusContent.propTypes = {
|
|
||||||
maxLength: PropTypes.number.isRequired,
|
|
||||||
minLength: PropTypes.number.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default PlaceholderStatusContent;
|
export default PlaceholderStatusContent;
|
|
@ -1,16 +0,0 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const ColumnSubheading = ({ text }) => {
|
|
||||||
return (
|
|
||||||
<div className='column-subheading'>
|
|
||||||
{text}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
ColumnSubheading.propTypes = {
|
|
||||||
text: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ColumnSubheading;
|
|
|
@ -1,15 +1,22 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import spring from 'react-motion/lib/spring';
|
import { spring } from 'react-motion';
|
||||||
|
|
||||||
import { Icon, Stack, Text } from 'soapbox/components/ui';
|
import { Icon, Stack, Text } from 'soapbox/components/ui';
|
||||||
|
|
||||||
import Motion from '../../ui/util/optional_motion';
|
import Motion from '../../ui/util/optional_motion';
|
||||||
|
|
||||||
const UploadArea = ({ active, onClose }) => {
|
interface IUploadArea {
|
||||||
const handleKeyUp = (e) => {
|
/** Whether the upload area is active. */
|
||||||
|
active: boolean,
|
||||||
|
/** Callback when the upload area is closed. */
|
||||||
|
onClose: () => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Component to display when a file is dragged over the UI. */
|
||||||
|
const UploadArea: React.FC<IUploadArea> = ({ active, onClose }) => {
|
||||||
|
const handleKeyUp = (e: KeyboardEvent) => {
|
||||||
const keyCode = e.keyCode;
|
const keyCode = e.keyCode;
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
|
@ -63,9 +70,4 @@ const UploadArea = ({ active, onClose }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
UploadArea.propTypes = {
|
|
||||||
active: PropTypes.bool,
|
|
||||||
onClose: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UploadArea;
|
export default UploadArea;
|
|
@ -61,7 +61,7 @@ export const AccountRecord = ImmutableRecord({
|
||||||
note_emojified: '',
|
note_emojified: '',
|
||||||
note_plain: '',
|
note_plain: '',
|
||||||
patron: null as PatronAccount | null,
|
patron: null as PatronAccount | null,
|
||||||
relationship: ImmutableList<ImmutableMap<string, any>>(),
|
relationship: ImmutableMap<string, any>(),
|
||||||
should_refetch: false,
|
should_refetch: false,
|
||||||
staff: false,
|
staff: false,
|
||||||
});
|
});
|
||||||
|
|
Ładowanie…
Reference in New Issue