From 722c96bec2d9c909b45f299421e63a69bac2a62f Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 16 Apr 2022 13:43:55 -0500 Subject: [PATCH] Notification: convert to TSX --- app/soapbox/components/status.tsx | 2 +- .../{notification.js => notification.tsx} | 136 ++++++++++-------- app/soapbox/normalizers/notification.ts | 2 +- 3 files changed, 75 insertions(+), 65 deletions(-) rename app/soapbox/features/notifications/components/{notification.js => notification.tsx} (57%) diff --git a/app/soapbox/components/status.tsx b/app/soapbox/components/status.tsx index c3417c35e..a7f40a861 100644 --- a/app/soapbox/components/status.tsx +++ b/app/soapbox/components/status.tsx @@ -29,7 +29,7 @@ import type { } from 'soapbox/types/entities'; // Defined in components/scrollable_list -type ScrollPosition = { height: number, top: number }; +export type ScrollPosition = { height: number, top: number }; export const textForScreenReader = (intl: IntlShape, status: StatusEntity, rebloggedByText?: string): string => { const { account } = status; diff --git a/app/soapbox/features/notifications/components/notification.js b/app/soapbox/features/notifications/components/notification.tsx similarity index 57% rename from app/soapbox/features/notifications/components/notification.js rename to app/soapbox/features/notifications/components/notification.tsx index 00911e68e..df4984592 100644 --- a/app/soapbox/features/notifications/components/notification.js +++ b/app/soapbox/features/notifications/components/notification.tsx @@ -1,7 +1,5 @@ -import PropTypes from 'prop-types'; import React from 'react'; import { HotKeys } from 'react-hotkeys'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import { FormattedMessage, useIntl } from 'react-intl'; import { useHistory } from 'react-router-dom'; @@ -11,7 +9,12 @@ import { HStack, Text } from '../../../components/ui'; import AccountContainer from '../../../containers/account_container'; import StatusContainer from '../../../containers/status_container'; -const notificationForScreenReader = (intl, message, timestamp) => { +import type { History } from 'history'; +import type { ScrollPosition } from 'soapbox/components/status'; +import type { NotificationType } from 'soapbox/normalizers/notification'; +import type { Account, Status, Notification as NotificationEntity } from 'soapbox/types/entities'; + +const notificationForScreenReader = (intl: ReturnType, message: string, timestamp: Date) => { const output = [message]; output.push(intl.formatDate(timestamp, { hour: '2-digit', minute: '2-digit', month: 'short', day: 'numeric' })); @@ -20,18 +23,18 @@ const notificationForScreenReader = (intl, message, timestamp) => { }; // Workaround for dynamic messages (https://github.com/formatjs/babel-plugin-react-intl/issues/119#issuecomment-326202499) -function FormattedMessageFixed(props) { +function FormattedMessageFixed(props: any) { return ; } -const buildLink = (account) => ( +const buildLink = (account: Account): JSX.Element => ( ); @@ -46,7 +49,8 @@ const icons = { status: require('@tabler/icons/icons/home.svg'), }; -const messages = { +// @ts-ignore +const messages: Record = { follow: { id: 'notification.follow', defaultMessage: '{name} followed you', @@ -57,11 +61,11 @@ const messages = { }, favourite: { id: 'notification.favourite', - defaultMessage: '{name} liked your TRUTH', + defaultMessage: '{name} liked your post', }, reblog: { id: 'notification.reblog', - defaultMessage: '{name} re-TRUTH your TRUTH', + defaultMessage: '{name} reposted your post', }, status: { id: 'notification.status', @@ -69,7 +73,7 @@ const messages = { }, }; -const buildMessage = (type, account) => { +const buildMessage = (type: NotificationType, account: Account): JSX.Element => { const link = buildLink(account); return ( @@ -81,15 +85,30 @@ const buildMessage = (type, account) => { ); }; -const Notification = (props) => { - const { hidden, notification, onMoveUp, onMoveDown } = props; +interface INotificaton { + hidden?: boolean, + notification: NotificationEntity, + onMoveUp: (notificationId: string) => void, + onMoveDown: (notificationId: string) => void, + onMention: (account: Account, history: History) => void, + onFavourite: (status: Status) => void, + onReblog: (status: Status, e?: KeyboardEvent) => void, + onToggleHidden: (status: Status) => void, + getScrollPosition?: () => ScrollPosition | undefined, + updateScrollBottom?: (bottom: number) => void, + cacheMediaWidth: () => void, + cachedMediaWidth: number, + siteTitle?: string, +} + +const Notification: React.FC = (props) => { + const { hidden = false, notification, onMoveUp, onMoveDown } = props; const history = useHistory(); const intl = useIntl(); - const type = notification.get('type'); - const timestamp = notification.get('created_at'); - const account = notification.get('account'); + const type = notification.type; + const { account, status } = notification; const getHandlers = () => ({ reply: handleMention, @@ -104,64 +123,71 @@ const Notification = (props) => { }); const handleOpen = () => { - if (notification.get('status')) { - history.push(`/@${notification.getIn(['account', 'acct'])}/posts/${notification.getIn(['status', 'id'])}`); + if (status && typeof status === 'object' && account && typeof account === 'object') { + history.push(`/@${account.acct}/posts/${status.id}`); } else { handleOpenProfile(); } }; const handleOpenProfile = () => { - history.push(`/@${notification.getIn(['account', 'acct'])}`); + if (account && typeof account === 'object') { + history.push(`/@${account.acct}`); + } }; - const handleMention = (event) => { - event.preventDefault(); + const handleMention = (e?: KeyboardEvent) => { + e?.preventDefault(); - props.onMention(notification.get('account'), history); + if (account && typeof account === 'object') { + props.onMention(account, history); + } }; - const handleHotkeyFavourite = () => { - const status = notification.get('status'); - if (status) props.onFavourite(status); + const handleHotkeyFavourite = (e?: KeyboardEvent) => { + if (status && typeof status === 'object') { + props.onFavourite(status); + } }; - const handleHotkeyBoost = (e) => { - const status = notification.get('status'); - if (status) props.onReblog(status, e); + const handleHotkeyBoost = (e?: KeyboardEvent) => { + if (status && typeof status === 'object') { + props.onReblog(status, e); + } }; - const handleHotkeyToggleHidden = () => { - const status = notification.get('status'); - if (status) props.onToggleHidden(status); + const handleHotkeyToggleHidden = (e?: KeyboardEvent) => { + if (status && typeof status === 'object') { + props.onToggleHidden(status); + } }; const handleMoveUp = () => { - onMoveUp(notification.get('id')); + onMoveUp(notification.id); }; const handleMoveDown = () => { - onMoveDown(notification.get('id')); + onMoveDown(notification.id); }; const renderContent = () => { switch (type) { case 'follow': - return ( + return account && typeof account === 'object' ? (