From e20a083fb494b43ebb7226cca59da67223f88576 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sun, 1 May 2022 12:45:37 -0500 Subject: [PATCH 1/5] Convert placeholder components to TSX --- ...laceholder_avatar.js => placeholder_avatar.tsx} | 13 ++++++------- ...isplay_name.js => placeholder_display_name.tsx} | 14 +++++++------- ...s_content.js => placeholder_status_content.tsx} | 14 +++++++------- 3 files changed, 20 insertions(+), 21 deletions(-) rename app/soapbox/features/placeholder/components/{placeholder_avatar.js => placeholder_avatar.tsx} (66%) rename app/soapbox/features/placeholder/components/{placeholder_display_name.js => placeholder_display_name.tsx} (65%) rename app/soapbox/features/placeholder/components/{placeholder_status_content.js => placeholder_status_content.tsx} (60%) diff --git a/app/soapbox/features/placeholder/components/placeholder_avatar.js b/app/soapbox/features/placeholder/components/placeholder_avatar.tsx similarity index 66% rename from app/soapbox/features/placeholder/components/placeholder_avatar.js rename to app/soapbox/features/placeholder/components/placeholder_avatar.tsx index 47cb346aa..a9740e86a 100644 --- a/app/soapbox/features/placeholder/components/placeholder_avatar.js +++ b/app/soapbox/features/placeholder/components/placeholder_avatar.tsx @@ -1,7 +1,11 @@ -import PropTypes from 'prop-types'; import * as React from 'react'; -const PlaceholderAvatar = ({ size }) => { +interface IPlaceholderAvatar { + size: number, +} + +/** Fake avatar to display while data is loading. */ +const PlaceholderAvatar: React.FC = ({ size }) => { const style = React.useMemo(() => { if (!size) { return {}; @@ -17,13 +21,8 @@ const PlaceholderAvatar = ({ size }) => {
); }; -PlaceholderAvatar.propTypes = { - size: PropTypes.number.isRequired, -}; - export default PlaceholderAvatar; diff --git a/app/soapbox/features/placeholder/components/placeholder_display_name.js b/app/soapbox/features/placeholder/components/placeholder_display_name.tsx similarity index 65% rename from app/soapbox/features/placeholder/components/placeholder_display_name.js rename to app/soapbox/features/placeholder/components/placeholder_display_name.tsx index ed71f6420..62d24a125 100644 --- a/app/soapbox/features/placeholder/components/placeholder_display_name.js +++ b/app/soapbox/features/placeholder/components/placeholder_display_name.tsx @@ -1,9 +1,14 @@ -import PropTypes from 'prop-types'; import React from 'react'; 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 = ({ minLength, maxLength }) => { const length = 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; diff --git a/app/soapbox/features/placeholder/components/placeholder_status_content.js b/app/soapbox/features/placeholder/components/placeholder_status_content.tsx similarity index 60% rename from app/soapbox/features/placeholder/components/placeholder_status_content.js rename to app/soapbox/features/placeholder/components/placeholder_status_content.tsx index 84772ccf2..85f747d52 100644 --- a/app/soapbox/features/placeholder/components/placeholder_status_content.js +++ b/app/soapbox/features/placeholder/components/placeholder_status_content.tsx @@ -1,9 +1,14 @@ -import PropTypes from 'prop-types'; import React from 'react'; 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 = ({ minLength, maxLength }) => { const length = randomIntFromInterval(maxLength, minLength); return ( @@ -13,9 +18,4 @@ const PlaceholderStatusContent = ({ minLength, maxLength }) => { ); }; -PlaceholderStatusContent.propTypes = { - maxLength: PropTypes.number.isRequired, - minLength: PropTypes.number.isRequired, -}; - export default PlaceholderStatusContent; From 5def7a087dfbe2f34973ed2db2286a90effdcfdc Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sun, 1 May 2022 12:46:06 -0500 Subject: [PATCH 2/5] Convert UploadArea to tsx --- app/soapbox/features/delete_account/index.tsx | 6 ------ .../{upload_area.js => upload_area.tsx} | 20 ++++++++++--------- 2 files changed, 11 insertions(+), 15 deletions(-) rename app/soapbox/features/ui/components/{upload_area.js => upload_area.tsx} (83%) diff --git a/app/soapbox/features/delete_account/index.tsx b/app/soapbox/features/delete_account/index.tsx index 733b9554c..d5927f763 100644 --- a/app/soapbox/features/delete_account/index.tsx +++ b/app/soapbox/features/delete_account/index.tsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import * as React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -75,9 +74,4 @@ const DeleteAccount = () => { ); }; -DeleteAccount.propTypes = { - intl: PropTypes.object, - dispatch: PropTypes.func, -}; - export default DeleteAccount; diff --git a/app/soapbox/features/ui/components/upload_area.js b/app/soapbox/features/ui/components/upload_area.tsx similarity index 83% rename from app/soapbox/features/ui/components/upload_area.js rename to app/soapbox/features/ui/components/upload_area.tsx index 6a940c649..ebdad855c 100644 --- a/app/soapbox/features/ui/components/upload_area.js +++ b/app/soapbox/features/ui/components/upload_area.tsx @@ -1,15 +1,22 @@ import classNames from 'classnames'; -import PropTypes from 'prop-types'; import * as React from 'react'; 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 Motion from '../../ui/util/optional_motion'; -const UploadArea = ({ active, onClose }) => { - const handleKeyUp = (e) => { +interface IUploadArea { + /** 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 = ({ active, onClose }) => { + const handleKeyUp = (e: KeyboardEvent) => { const keyCode = e.keyCode; if (active) { @@ -63,9 +70,4 @@ const UploadArea = ({ active, onClose }) => { ); }; -UploadArea.propTypes = { - active: PropTypes.bool, - onClose: PropTypes.func, -}; - export default UploadArea; From 311ec14200b06db7bc8d31792cf088074f077b8d Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sun, 1 May 2022 12:53:53 -0500 Subject: [PATCH 3/5] Convert most Placeholder components into TSX --- .../components/placeholder_account.js | 23 ------------- .../components/placeholder_account.tsx | 22 +++++++++++++ ...aceholder_card.js => placeholder_card.tsx} | 3 +- .../components/placeholder_chat.js | 32 ------------------- .../components/placeholder_chat.tsx | 31 ++++++++++++++++++ .../components/placeholder_hashtag.js | 21 ------------ .../components/placeholder_hashtag.tsx | 20 ++++++++++++ .../components/placeholder_material_status.js | 17 ---------- .../placeholder_material_status.tsx | 16 ++++++++++ ...cation.js => placeholder_notification.tsx} | 1 + .../components/placeholder_status.tsx | 3 +- 11 files changed, 94 insertions(+), 95 deletions(-) delete mode 100644 app/soapbox/features/placeholder/components/placeholder_account.js create mode 100644 app/soapbox/features/placeholder/components/placeholder_account.tsx rename app/soapbox/features/placeholder/components/{placeholder_card.js => placeholder_card.tsx} (85%) delete mode 100644 app/soapbox/features/placeholder/components/placeholder_chat.js create mode 100644 app/soapbox/features/placeholder/components/placeholder_chat.tsx delete mode 100644 app/soapbox/features/placeholder/components/placeholder_hashtag.js create mode 100644 app/soapbox/features/placeholder/components/placeholder_hashtag.tsx delete mode 100644 app/soapbox/features/placeholder/components/placeholder_material_status.js create mode 100644 app/soapbox/features/placeholder/components/placeholder_material_status.tsx rename app/soapbox/features/placeholder/components/{placeholder_notification.js => placeholder_notification.tsx} (94%) diff --git a/app/soapbox/features/placeholder/components/placeholder_account.js b/app/soapbox/features/placeholder/components/placeholder_account.js deleted file mode 100644 index 4d638046b..000000000 --- a/app/soapbox/features/placeholder/components/placeholder_account.js +++ /dev/null @@ -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 ( -
-
- -
- -
- -
-
-
- ); - } - -} diff --git a/app/soapbox/features/placeholder/components/placeholder_account.tsx b/app/soapbox/features/placeholder/components/placeholder_account.tsx new file mode 100644 index 000000000..ad31db3a4 --- /dev/null +++ b/app/soapbox/features/placeholder/components/placeholder_account.tsx @@ -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 ( +
+
+ +
+ +
+ +
+
+
+ ); +}; + +export default PlaceholderAccount; diff --git a/app/soapbox/features/placeholder/components/placeholder_card.js b/app/soapbox/features/placeholder/components/placeholder_card.tsx similarity index 85% rename from app/soapbox/features/placeholder/components/placeholder_card.js rename to app/soapbox/features/placeholder/components/placeholder_card.tsx index 87b7e5caf..92911b9d6 100644 --- a/app/soapbox/features/placeholder/components/placeholder_card.js +++ b/app/soapbox/features/placeholder/components/placeholder_card.tsx @@ -3,7 +3,8 @@ import * as React from 'react'; import { randomIntFromInterval, generateText } from '../utils'; -const PlaceholderCard = () => ( +/** Fake link preview to display while data is loading. */ +const PlaceholderCard: React.FC = () => (
-
-
-
-
- -
- - - {generateText(messageLength)} - -
-
-
-
- ); - } - -} diff --git a/app/soapbox/features/placeholder/components/placeholder_chat.tsx b/app/soapbox/features/placeholder/components/placeholder_chat.tsx new file mode 100644 index 000000000..6b587f03d --- /dev/null +++ b/app/soapbox/features/placeholder/components/placeholder_chat.tsx @@ -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 ( +
+
+
+
+
+ +
+ + + {generateText(messageLength)} + +
+
+
+
+ ); +}; + +export default PlaceholderChat; diff --git a/app/soapbox/features/placeholder/components/placeholder_hashtag.js b/app/soapbox/features/placeholder/components/placeholder_hashtag.js deleted file mode 100644 index 81c788238..000000000 --- a/app/soapbox/features/placeholder/components/placeholder_hashtag.js +++ /dev/null @@ -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 ( -
-
-
- {generateText(length)} -
-
-
- ); - } - -} \ No newline at end of file diff --git a/app/soapbox/features/placeholder/components/placeholder_hashtag.tsx b/app/soapbox/features/placeholder/components/placeholder_hashtag.tsx new file mode 100644 index 000000000..28dceec72 --- /dev/null +++ b/app/soapbox/features/placeholder/components/placeholder_hashtag.tsx @@ -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 ( +
+
+
+ {generateText(length)} +
+
+
+ ); +}; + +export default PlaceholderHashtag; diff --git a/app/soapbox/features/placeholder/components/placeholder_material_status.js b/app/soapbox/features/placeholder/components/placeholder_material_status.js deleted file mode 100644 index 3199d42aa..000000000 --- a/app/soapbox/features/placeholder/components/placeholder_material_status.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; - -import PlaceholderStatus from './placeholder_status'; - -export default class PlaceholderMaterialStatus extends React.Component { - - render() { - return ( -
-
- -
-
- ); - } - -} diff --git a/app/soapbox/features/placeholder/components/placeholder_material_status.tsx b/app/soapbox/features/placeholder/components/placeholder_material_status.tsx new file mode 100644 index 000000000..28581cb09 --- /dev/null +++ b/app/soapbox/features/placeholder/components/placeholder_material_status.tsx @@ -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 ( +
+
+ +
+
+ ); +}; + +export default PlaceholderMaterialStatus; diff --git a/app/soapbox/features/placeholder/components/placeholder_notification.js b/app/soapbox/features/placeholder/components/placeholder_notification.tsx similarity index 94% rename from app/soapbox/features/placeholder/components/placeholder_notification.js rename to app/soapbox/features/placeholder/components/placeholder_notification.tsx index e56f90c58..bb99eeb5b 100644 --- a/app/soapbox/features/placeholder/components/placeholder_notification.js +++ b/app/soapbox/features/placeholder/components/placeholder_notification.tsx @@ -4,6 +4,7 @@ import PlaceholderAvatar from './placeholder_avatar'; import PlaceholderDisplayName from './placeholder_display_name'; import PlaceholderStatusContent from './placeholder_status_content'; +/** Fake notification to display while data is loading. */ const PlaceholderNotification = () => (
diff --git a/app/soapbox/features/placeholder/components/placeholder_status.tsx b/app/soapbox/features/placeholder/components/placeholder_status.tsx index a11823f8a..d67c41204 100644 --- a/app/soapbox/features/placeholder/components/placeholder_status.tsx +++ b/app/soapbox/features/placeholder/components/placeholder_status.tsx @@ -9,7 +9,8 @@ interface IPlaceholderStatus { thread?: boolean } -const PlaceholderStatus = ({ thread = false }: IPlaceholderStatus) => ( +/** Fake status to display while data is loading. */ +const PlaceholderStatus: React.FC = ({ thread = false }) => (
Date: Sun, 1 May 2022 12:54:54 -0500 Subject: [PATCH 4/5] Delete unused ColumnSubheading --- .../features/ui/components/column_subheading.js | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 app/soapbox/features/ui/components/column_subheading.js diff --git a/app/soapbox/features/ui/components/column_subheading.js b/app/soapbox/features/ui/components/column_subheading.js deleted file mode 100644 index c586e27b7..000000000 --- a/app/soapbox/features/ui/components/column_subheading.js +++ /dev/null @@ -1,16 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; - -const ColumnSubheading = ({ text }) => { - return ( -
- {text} -
- ); -}; - -ColumnSubheading.propTypes = { - text: PropTypes.string.isRequired, -}; - -export default ColumnSubheading; From 2e5cc2619dd0ed81f7db15195c612837481d0d1f Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sun, 1 May 2022 13:11:20 -0500 Subject: [PATCH 5/5] ProfileHoverCard: convert to tsx --- app/soapbox/components/hover_ref_wrapper.tsx | 3 +- ...e_hover_card.js => profile_hover_card.tsx} | 52 +++++++++---------- app/soapbox/normalizers/account.ts | 2 +- 3 files changed, 26 insertions(+), 31 deletions(-) rename app/soapbox/components/{profile_hover_card.js => profile_hover_card.tsx} (70%) diff --git a/app/soapbox/components/hover_ref_wrapper.tsx b/app/soapbox/components/hover_ref_wrapper.tsx index 239c27580..f1da2e65d 100644 --- a/app/soapbox/components/hover_ref_wrapper.tsx +++ b/app/soapbox/components/hover_ref_wrapper.tsx @@ -20,7 +20,7 @@ interface IHoverRefWrapper { /** Makes a profile hover card appear when the wrapped element is hovered. */ export const HoverRefWrapper: React.FC = ({ accountId, children, inline = false }) => { const dispatch = useDispatch(); - const ref = useRef(); + const ref = useRef(null); const Elem: keyof JSX.IntrinsicElements = inline ? 'span' : 'div'; const handleMouseEnter = () => { @@ -41,7 +41,6 @@ export const HoverRefWrapper: React.FC = ({ accountId, childre return ( { +const getBadges = (account: Account): JSX.Element[] => { const badges = []; if (account.admin) { @@ -43,29 +44,34 @@ const getBadges = (account) => { return badges; }; -const handleMouseEnter = (dispatch) => { - return e => { +const handleMouseEnter = (dispatch: AppDispatch): React.MouseEventHandler => { + return () => { dispatch(updateProfileHoverCard()); }; }; -const handleMouseLeave = (dispatch) => { - return e => { +const handleMouseLeave = (dispatch: AppDispatch): React.MouseEventHandler => { + return () => { dispatch(closeProfileHoverCard(true)); }; }; -export const ProfileHoverCard = ({ visible }) => { - const dispatch = useDispatch(); +interface IProfileHoverCard { + visible: boolean, +} + +/** Popup profile preview that appears when hovering avatars and display names. */ +export const ProfileHoverCard: React.FC = ({ visible = true }) => { + const dispatch = useAppDispatch(); const history = useHistory(); const intl = useIntl(); - const [popperElement, setPopperElement] = useState(null); + const [popperElement, setPopperElement] = useState(null); - const me = useSelector(state => state.get('me')); - const accountId = useSelector(state => state.getIn(['profile_hover_card', 'accountId'])); - const account = useSelector(state => accountId && getAccount(state, accountId)); - const targetRef = useSelector(state => state.getIn(['profile_hover_card', 'ref', 'current'])); + const me = useAppSelector(state => state.me); + const accountId: string | undefined = useAppSelector(state => state.profile_hover_card.get('accountId', undefined)); + const account = useAppSelector(state => accountId && getAccount(state, accountId)); + const targetRef = useAppSelector(state => state.profile_hover_card.getIn(['ref', 'current']) as Element | null); const badges = account ? getBadges(account) : []; useEffect(() => { @@ -86,8 +92,8 @@ export const ProfileHoverCard = ({ visible }) => { const { styles, attributes } = usePopper(targetRef, popperElement); if (!account) return null; - const accountBio = { __html: account.get('note_emojified') }; - const followedBy = me !== account.get('id') && account.getIn(['relationship', 'followed_by']); + const accountBio = { __html: account.note_emojified }; + const followedBy = me !== account.id && account.relationship.get('followed_by') === true; return (
{ )} - {account.getIn(['source', 'note'], '').length > 0 && ( + {account.source.get('note', '').length > 0 && ( )} @@ -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; diff --git a/app/soapbox/normalizers/account.ts b/app/soapbox/normalizers/account.ts index c4a5faffc..f72b18a09 100644 --- a/app/soapbox/normalizers/account.ts +++ b/app/soapbox/normalizers/account.ts @@ -61,7 +61,7 @@ export const AccountRecord = ImmutableRecord({ note_emojified: '', note_plain: '', patron: null as PatronAccount | null, - relationship: ImmutableList>(), + relationship: ImmutableMap(), should_refetch: false, staff: false, });