From a3d1d2dc9191f6581127598264ec21e815a19cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Sat, 28 May 2022 21:53:22 +0200 Subject: [PATCH] TS, FC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- .../auth_login/components/otp_auth_form.js | 101 ------------------ .../auth_login/components/otp_auth_form.tsx | 88 +++++++++++++++ .../auth_login/components/password_reset.js | 72 ------------- .../auth_login/components/password_reset.tsx | 66 ++++++++++++ app/soapbox/features/new_status/index.js | 34 ------ app/soapbox/features/new_status/index.tsx | 20 ++++ .../components/pinned_hosts_picker.tsx | 2 - .../features/reply_mentions/account.js | 94 ---------------- .../features/reply_mentions/account.tsx | 67 ++++++++++++ app/soapbox/features/server_info/index.js | 48 --------- app/soapbox/features/server_info/index.tsx | 36 +++++++ .../{media_display.js => media_display.tsx} | 19 ++-- app/soapbox/features/share/index.js | 47 -------- app/soapbox/features/share/index.tsx | 30 ++++++ .../components/site-preview.tsx | 1 - .../ui/components/reply_mentions_modal.tsx | 2 +- .../{email_passthru.js => email_passthru.tsx} | 13 +-- .../{waitlist_page.js => waitlist_page.tsx} | 11 +- 18 files changed, 323 insertions(+), 428 deletions(-) delete mode 100644 app/soapbox/features/auth_login/components/otp_auth_form.js create mode 100644 app/soapbox/features/auth_login/components/otp_auth_form.tsx delete mode 100644 app/soapbox/features/auth_login/components/password_reset.js create mode 100644 app/soapbox/features/auth_login/components/password_reset.tsx delete mode 100644 app/soapbox/features/new_status/index.js create mode 100644 app/soapbox/features/new_status/index.tsx delete mode 100644 app/soapbox/features/reply_mentions/account.js create mode 100644 app/soapbox/features/reply_mentions/account.tsx delete mode 100644 app/soapbox/features/server_info/index.js create mode 100644 app/soapbox/features/server_info/index.tsx rename app/soapbox/features/settings/{media_display.js => media_display.tsx} (78%) delete mode 100644 app/soapbox/features/share/index.js create mode 100644 app/soapbox/features/share/index.tsx rename app/soapbox/features/verification/{email_passthru.js => email_passthru.tsx} (96%) rename app/soapbox/features/verification/{waitlist_page.js => waitlist_page.tsx} (91%) diff --git a/app/soapbox/features/auth_login/components/otp_auth_form.js b/app/soapbox/features/auth_login/components/otp_auth_form.js deleted file mode 100644 index 0446a7afe..000000000 --- a/app/soapbox/features/auth_login/components/otp_auth_form.js +++ /dev/null @@ -1,101 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; -import { connect } from 'react-redux'; -import { Redirect } from 'react-router-dom'; - -import { otpVerify, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; -import { Button, Form, FormActions, FormGroup, Input } from 'soapbox/components/ui'; - -const messages = defineMessages({ - otpCodeHint: { id: 'login.fields.otp_code_hint', defaultMessage: 'Enter the two-factor code generated by your phone app or use one of your recovery codes' }, - otpCodeLabel: { id: 'login.fields.otp_code_label', defaultMessage: 'Two-factor code:' }, - otpLoginFail: { id: 'login.otp_log_in.fail', defaultMessage: 'Invalid code, please try again.' }, -}); - -export default @connect() -@injectIntl -class OtpAuthForm extends ImmutablePureComponent { - - state = { - isLoading: false, - code_error: '', - shouldRedirect: false, - } - - static propTypes = { - intl: PropTypes.object.isRequired, - dispatch: PropTypes.func.isRequired, - mfa_token: PropTypes.string, - }; - - getFormData = (form) => { - return Object.fromEntries( - Array.from(form).map(i => [i.name, i.value]), - ); - } - - handleSubmit = (event) => { - const { dispatch, mfa_token } = this.props; - const { code } = this.getFormData(event.target); - dispatch(otpVerify(code, mfa_token)).then(({ access_token }) => { - this.setState({ code_error: false }); - return dispatch(verifyCredentials(access_token)); - }).then(account => { - this.setState({ shouldRedirect: true }); - return dispatch(switchAccount(account.id)); - }).catch(error => { - this.setState({ isLoading: false, code_error: true }); - }); - this.setState({ isLoading: true }); - event.preventDefault(); - } - - render() { - const { intl } = this.props; - const { code_error, shouldRedirect } = this.state; - - if (shouldRedirect) return ; - - return ( -
-
-

- -

-
- -
-
- - - - - - - -
-
-
- ); - } - -} diff --git a/app/soapbox/features/auth_login/components/otp_auth_form.tsx b/app/soapbox/features/auth_login/components/otp_auth_form.tsx new file mode 100644 index 000000000..eaeade08b --- /dev/null +++ b/app/soapbox/features/auth_login/components/otp_auth_form.tsx @@ -0,0 +1,88 @@ +import React, { useState } from 'react'; +import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; +import { Redirect } from 'react-router-dom'; + +import { otpVerify, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; +import { Button, Form, FormActions, FormGroup, Input } from 'soapbox/components/ui'; +import { useAppDispatch } from 'soapbox/hooks'; + +const messages = defineMessages({ + otpCodeHint: { id: 'login.fields.otp_code_hint', defaultMessage: 'Enter the two-factor code generated by your phone app or use one of your recovery codes' }, + otpCodeLabel: { id: 'login.fields.otp_code_label', defaultMessage: 'Two-factor code:' }, + otpLoginFail: { id: 'login.otp_log_in.fail', defaultMessage: 'Invalid code, please try again.' }, +}); + +interface IOtpAuthForm { + mfa_token: string, +} + +const OtpAuthForm: React.FC = ({ mfa_token }) => { + const dispatch = useAppDispatch(); + const intl = useIntl(); + + const [isLoading, setIsLoading] = useState(false); + const [shouldRedirect, setShouldRedirect] = useState(false); + const [codeError, setCodeError] = useState(''); + + const getFormData = (form: any) => Object.fromEntries( + Array.from(form).map((i: any) => [i.name, i.value]), + ); + + const handleSubmit = (event: React.FormEvent) => { + const { code } = getFormData(event.target); + dispatch(otpVerify(code, mfa_token)).then(({ access_token }) => { + setCodeError(false); + return dispatch(verifyCredentials(access_token)); + }).then(account => { + setShouldRedirect(true); + return dispatch(switchAccount(account.id)); + }).catch(() => { + setIsLoading(false); + setCodeError(true); + }); + setIsLoading(true); + event.preventDefault(); + }; + + if (shouldRedirect) return ; + + return ( +
+
+

+ +

+
+ +
+
+ + + + + + + +
+
+
+ ); +}; + +export default OtpAuthForm; diff --git a/app/soapbox/features/auth_login/components/password_reset.js b/app/soapbox/features/auth_login/components/password_reset.js deleted file mode 100644 index f047207be..000000000 --- a/app/soapbox/features/auth_login/components/password_reset.js +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { defineMessages, FormattedMessage, injectIntl } from 'react-intl'; -import { connect } from 'react-redux'; -import { Redirect } from 'react-router-dom'; - -import { resetPassword } from 'soapbox/actions/security'; -import snackbar from 'soapbox/actions/snackbar'; - -import { Button, Form, FormActions, FormGroup, Input } from '../../../components/ui'; - -const messages = defineMessages({ - nicknameOrEmail: { id: 'password_reset.fields.username_placeholder', defaultMessage: 'Email or username' }, - confirmation: { id: 'password_reset.confirmation', defaultMessage: 'Check your email for confirmation.' }, -}); - -export default @connect() -@injectIntl -class PasswordReset extends ImmutablePureComponent { - - state = { - isLoading: false, - success: false, - } - - handleSubmit = e => { - const { dispatch, intl } = this.props; - const nicknameOrEmail = e.target.nickname_or_email.value; - this.setState({ isLoading: true }); - dispatch(resetPassword(nicknameOrEmail)).then(() => { - this.setState({ isLoading: false, success: true }); - dispatch(snackbar.info(intl.formatMessage(messages.confirmation))); - }).catch(error => { - this.setState({ isLoading: false }); - }); - } - - render() { - const { intl } = this.props; - - if (this.state.success) return ; - - return ( -
-
-

- -

-
- -
-
- - - - - - - -
-
-
- ); - } - -} diff --git a/app/soapbox/features/auth_login/components/password_reset.tsx b/app/soapbox/features/auth_login/components/password_reset.tsx new file mode 100644 index 000000000..bcd7976c6 --- /dev/null +++ b/app/soapbox/features/auth_login/components/password_reset.tsx @@ -0,0 +1,66 @@ +import React, { useState } from 'react'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import { Redirect } from 'react-router-dom'; + +import { resetPassword } from 'soapbox/actions/security'; +import snackbar from 'soapbox/actions/snackbar'; +import { Button, Form, FormActions, FormGroup, Input } from 'soapbox/components/ui'; +import { useAppDispatch } from 'soapbox/hooks'; + +const messages = defineMessages({ + nicknameOrEmail: { id: 'password_reset.fields.username_placeholder', defaultMessage: 'Email or username' }, + confirmation: { id: 'password_reset.confirmation', defaultMessage: 'Check your email for confirmation.' }, +}); + +const PasswordReset = () => { + const dispatch = useAppDispatch(); + const intl = useIntl(); + + const [isLoading, setIsLoading] = useState(false); + const [success, setSuccess] = useState(false); + + const handleSubmit = (e: React.FormEvent) => { + const nicknameOrEmail = (e.target as any).nickname_or_email.value; + setIsLoading(true); + dispatch(resetPassword(nicknameOrEmail)).then(() => { + setIsLoading(false); + setSuccess(true); + dispatch(snackbar.info(intl.formatMessage(messages.confirmation))); + }).catch(() => { + setIsLoading(false); + }); + }; + + if (success) return ; + + return ( +
+
+

+ +

+
+ +
+
+ + + + + + + +
+
+
+ ); +}; + +export default PasswordReset; diff --git a/app/soapbox/features/new_status/index.js b/app/soapbox/features/new_status/index.js deleted file mode 100644 index ef6092b11..000000000 --- a/app/soapbox/features/new_status/index.js +++ /dev/null @@ -1,34 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { connect } from 'react-redux'; -import { Redirect } from 'react-router-dom'; - -import { openModal } from '../../actions/modals'; - -const mapDispatchToProps = dispatch => ({ - - onLoad: (text) => { - dispatch(openModal('COMPOSE')); - }, - -}); - -export default @connect(null, mapDispatchToProps) -class NewStatus extends React.Component { - - static propTypes = { - onLoad: PropTypes.func.isRequired, - }; - - constructor(props) { - super(props); - this.props.onLoad(); - } - - render() { - return ( - - ); - } - -} diff --git a/app/soapbox/features/new_status/index.tsx b/app/soapbox/features/new_status/index.tsx new file mode 100644 index 000000000..322976afc --- /dev/null +++ b/app/soapbox/features/new_status/index.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { useEffect } from 'react'; +import { Redirect } from 'react-router-dom'; + +import { openModal } from 'soapbox/actions/modals'; +import { useAppDispatch } from 'soapbox/hooks'; + +const NewStatus = () => { + const dispatch = useAppDispatch(); + + useEffect(() => { + dispatch(openModal('COMPOSE')); + }, []); + + return ( + + ); +}; + +export default NewStatus; diff --git a/app/soapbox/features/remote_timeline/components/pinned_hosts_picker.tsx b/app/soapbox/features/remote_timeline/components/pinned_hosts_picker.tsx index aa7940761..3f08e94d6 100644 --- a/app/soapbox/features/remote_timeline/components/pinned_hosts_picker.tsx +++ b/app/soapbox/features/remote_timeline/components/pinned_hosts_picker.tsx @@ -1,8 +1,6 @@ 'use strict'; -import classNames from 'classnames'; import React from 'react'; -import { Link } from 'react-router-dom'; import { Button, HStack } from 'soapbox/components/ui'; import { useSettings } from 'soapbox/hooks'; diff --git a/app/soapbox/features/reply_mentions/account.js b/app/soapbox/features/reply_mentions/account.js deleted file mode 100644 index b9bf62d51..000000000 --- a/app/soapbox/features/reply_mentions/account.js +++ /dev/null @@ -1,94 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { defineMessages, injectIntl } from 'react-intl'; -import { connect } from 'react-redux'; - -import { fetchAccount } from 'soapbox/actions/accounts'; -import { addToMentions, removeFromMentions } from 'soapbox/actions/compose'; -import Avatar from 'soapbox/components/avatar'; -import DisplayName from 'soapbox/components/display-name'; -import IconButton from 'soapbox/components/icon_button'; -import { makeGetAccount } from 'soapbox/selectors'; - -const messages = defineMessages({ - remove: { id: 'reply_mentions.account.remove', defaultMessage: 'Remove from mentions' }, - add: { id: 'reply_mentions.account.add', defaultMessage: 'Add to mentions' }, -}); - -const makeMapStateToProps = () => { - const getAccount = makeGetAccount(); - - const mapStateToProps = (state, { accountId }) => { - const account = getAccount(state, accountId); - - return { - added: !!account && state.getIn(['compose', 'to']).includes(account.get('acct')), - account, - }; - }; - - return mapStateToProps; -}; - -const mapDispatchToProps = (dispatch, { accountId }) => ({ - onRemove: () => dispatch(removeFromMentions(accountId)), - onAdd: () => dispatch(addToMentions(accountId)), - fetchAccount: () => dispatch(fetchAccount(accountId)), -}); - -export default @connect(makeMapStateToProps, mapDispatchToProps) -@injectIntl -class Account extends ImmutablePureComponent { - - static propTypes = { - accountId: PropTypes.string.isRequired, - intl: PropTypes.object.isRequired, - onRemove: PropTypes.func.isRequired, - onAdd: PropTypes.func.isRequired, - added: PropTypes.bool, - author: PropTypes.bool, - }; - - static defaultProps = { - added: false, - }; - - componentDidMount() { - const { account, accountId } = this.props; - - if (accountId && !account) { - this.props.fetchAccount(accountId); - } - } - - render() { - const { account, intl, onRemove, onAdd, added, author } = this.props; - - if (!account) return null; - - let button; - - if (added) { - button = ; - } else { - button = ; - } - - return ( -
-
-
-
- -
- -
- {!author && button} -
-
-
- ); - } - -} diff --git a/app/soapbox/features/reply_mentions/account.tsx b/app/soapbox/features/reply_mentions/account.tsx new file mode 100644 index 000000000..c4817e8cf --- /dev/null +++ b/app/soapbox/features/reply_mentions/account.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import { useEffect } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; + +import { fetchAccount } from 'soapbox/actions/accounts'; +import { addToMentions, removeFromMentions } from 'soapbox/actions/compose'; +import Avatar from 'soapbox/components/avatar'; +import DisplayName from 'soapbox/components/display-name'; +import IconButton from 'soapbox/components/icon_button'; +import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; +import { makeGetAccount } from 'soapbox/selectors'; + +const messages = defineMessages({ + remove: { id: 'reply_mentions.account.remove', defaultMessage: 'Remove from mentions' }, + add: { id: 'reply_mentions.account.add', defaultMessage: 'Add to mentions' }, +}); + +const getAccount = makeGetAccount(); + +interface IAccount { + accountId: string, + author: boolean, +} + +const Account: React.FC = ({ accountId, author }) => { + const intl = useIntl(); + const dispatch = useAppDispatch(); + + const account = useAppSelector((state) => getAccount(state, accountId)); + const added = useAppSelector((state) => !!account && state.compose.get('to').includes(account.acct)); + + const onRemove = () => dispatch(removeFromMentions(accountId)); + const onAdd = () => dispatch(addToMentions(accountId)); + + useEffect(() => { + if (accountId && !account) { + dispatch(fetchAccount(accountId)); + } + }, []); + + if (!account) return null; + + let button; + + if (added) { + button = ; + } else { + button = ; + } + + return ( +
+
+
+
+ +
+ +
+ {!author && button} +
+
+
+ ); +}; + +export default Account; diff --git a/app/soapbox/features/server_info/index.js b/app/soapbox/features/server_info/index.js deleted file mode 100644 index a7d19c72a..000000000 --- a/app/soapbox/features/server_info/index.js +++ /dev/null @@ -1,48 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { defineMessages, injectIntl } from 'react-intl'; -import { connect } from 'react-redux'; - -import Column from '../ui/components/column'; -import LinkFooter from '../ui/components/link_footer'; -import PromoPanel from '../ui/components/promo_panel'; - -const messages = defineMessages({ - heading: { id: 'column.info', defaultMessage: 'Server information' }, -}); - -const mapStateToProps = (state, props) => ({ - instance: state.get('instance'), -}); - -export default @connect(mapStateToProps) -@injectIntl -class ServerInfo extends ImmutablePureComponent { - - static propTypes = { - intl: PropTypes.object.isRequired, - }; - - render() { - const { intl, instance } = this.props; - - return ( - -
-
-
-

{instance.get('title')}

-
-
- {instance.get('description')} -
-
- - -
-
- ); - } - -} diff --git a/app/soapbox/features/server_info/index.tsx b/app/soapbox/features/server_info/index.tsx new file mode 100644 index 000000000..0e12538d4 --- /dev/null +++ b/app/soapbox/features/server_info/index.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { defineMessages, useIntl } from 'react-intl'; + +import { useAppSelector } from 'soapbox/hooks'; + +import Column from '../ui/components/column'; +import LinkFooter from '../ui/components/link_footer'; +import PromoPanel from '../ui/components/promo_panel'; + +const messages = defineMessages({ + heading: { id: 'column.info', defaultMessage: 'Server information' }, +}); + +const ServerInfo = () => { + const intl = useIntl(); + const instance = useAppSelector((state) => state.instance); + + return ( + +
+
+
+

{instance.title}

+
+
+ {instance.description} +
+
+ + +
+
+ ); +}; + +export default ServerInfo; diff --git a/app/soapbox/features/settings/media_display.js b/app/soapbox/features/settings/media_display.tsx similarity index 78% rename from app/soapbox/features/settings/media_display.js rename to app/soapbox/features/settings/media_display.tsx index 0ce0eb51a..ee522347f 100644 --- a/app/soapbox/features/settings/media_display.js +++ b/app/soapbox/features/settings/media_display.tsx @@ -1,16 +1,11 @@ import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; -import { useDispatch } from 'react-redux'; import { getSettings, changeSettingImmediate } from 'soapbox/actions/settings'; -import { - SimpleForm, - SelectDropdown, -} from 'soapbox/features/forms'; -import { useAppSelector } from 'soapbox/hooks'; - -import List, { ListItem } from '../../components/list'; -import { Card, CardBody, CardHeader, CardTitle } from '../../components/ui'; +import List, { ListItem } from 'soapbox/components/list'; +import { Card, CardBody, CardHeader, CardTitle } from 'soapbox/components/ui'; +import { SimpleForm, SelectDropdown } from 'soapbox/features/forms'; +import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; const messages = defineMessages({ mediaDisplay: { id: 'preferences.fields.media_display_label', defaultMessage: 'Media display' }, @@ -20,7 +15,7 @@ const messages = defineMessages({ }); const MediaDisplay = () => { - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); const intl = useIntl(); const settings = useAppSelector((state) => getSettings(state)); @@ -31,7 +26,7 @@ const MediaDisplay = () => { show_all: intl.formatMessage(messages.display_media_show_all), }; - const onSelectChange = path => { + const onSelectChange: (path: string[]) => React.ChangeEventHandler = path => { return e => { dispatch(changeSettingImmediate(path, e.target.value)); }; @@ -49,7 +44,7 @@ const MediaDisplay = () => { diff --git a/app/soapbox/features/share/index.js b/app/soapbox/features/share/index.js deleted file mode 100644 index ff6dd18f3..000000000 --- a/app/soapbox/features/share/index.js +++ /dev/null @@ -1,47 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { connect } from 'react-redux'; -import { Redirect } from 'react-router-dom'; - -import { openComposeWithText } from '../../actions/compose'; - -const mapDispatchToProps = dispatch => ({ - - onShare: (text) => { - dispatch(openComposeWithText(text)); - }, - -}); - -export default @connect(null, mapDispatchToProps) -class Share extends React.Component { - - static propTypes = { - onShare: PropTypes.func.isRequired, - }; - - constructor(props) { - super(props); - - const params = new URLSearchParams(window.location.search); - - const text = [ - params.get('title'), - params.get('text'), - params.get('url'), - ] - .filter(v => v) - .join('\n\n'); - - if (text) { - this.props.onShare(text); - } - } - - render() { - return ( - - ); - } - -} diff --git a/app/soapbox/features/share/index.tsx b/app/soapbox/features/share/index.tsx new file mode 100644 index 000000000..562f23689 --- /dev/null +++ b/app/soapbox/features/share/index.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { Redirect, useLocation } from 'react-router-dom'; + +import { openComposeWithText } from 'soapbox/actions/compose'; +import { useAppDispatch } from 'soapbox/hooks'; + +const Share = () => { + const dispatch = useAppDispatch(); + + const { search } = useLocation(); + const params = new URLSearchParams(search); + + const text = [ + params.get('title'), + params.get('text'), + params.get('url'), + ] + .filter(v => v) + .join('\n\n'); + + if (text) { + dispatch(openComposeWithText(text)); + } + + return ( + + ); +}; + +export default Share; \ No newline at end of file diff --git a/app/soapbox/features/soapbox_config/components/site-preview.tsx b/app/soapbox/features/soapbox_config/components/site-preview.tsx index 8721be6ff..1c4efc92f 100644 --- a/app/soapbox/features/soapbox_config/components/site-preview.tsx +++ b/app/soapbox/features/soapbox_config/components/site-preview.tsx @@ -49,7 +49,6 @@ const SitePreview: React.FC = ({ soapbox }) => { })} > - {/* Logo */} ); diff --git a/app/soapbox/features/ui/components/reply_mentions_modal.tsx b/app/soapbox/features/ui/components/reply_mentions_modal.tsx index c1d3422fb..b1a959afb 100644 --- a/app/soapbox/features/ui/components/reply_mentions_modal.tsx +++ b/app/soapbox/features/ui/components/reply_mentions_modal.tsx @@ -33,7 +33,7 @@ const ReplyMentionsModal: React.FC = ({ onClose }) => { closePosition='left' >
- {mentions.map(accountId => )} + {mentions.map(accountId => )}
); diff --git a/app/soapbox/features/verification/email_passthru.js b/app/soapbox/features/verification/email_passthru.tsx similarity index 96% rename from app/soapbox/features/verification/email_passthru.js rename to app/soapbox/features/verification/email_passthru.tsx index 52b791c52..d014143aa 100644 --- a/app/soapbox/features/verification/email_passthru.js +++ b/app/soapbox/features/verification/email_passthru.tsx @@ -1,7 +1,8 @@ -import PropTypes from 'prop-types'; +import { AxiosError } from 'axios'; import * as React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; +import { useParams } from 'react-router-dom'; import snackbar from 'soapbox/actions/snackbar'; import { confirmEmailVerification } from 'soapbox/actions/verification'; @@ -91,8 +92,8 @@ const TokenExpired = () => { ); }; -const EmailPassThru = ({ match }) => { - const { token } = match.params; +const EmailPassThru = () => { + const { token } = useParams<{ token: string }>(); const dispatch = useDispatch(); const intl = useIntl(); @@ -106,7 +107,7 @@ const EmailPassThru = ({ match }) => { setStatus(Statuses.SUCCESS); dispatch(snackbar.success(intl.formatMessage({ id: 'email_passthru.success', defaultMessage: 'Your email has been verified!' }))); }) - .catch((error) => { + .catch((error: AxiosError) => { const errorKey = error?.response?.data?.error; let message = intl.formatMessage({ id: 'email_passthru.fail.generic', @@ -155,8 +156,4 @@ const EmailPassThru = ({ match }) => { } }; -EmailPassThru.propTypes = { - match: PropTypes.object, -}; - export default EmailPassThru; diff --git a/app/soapbox/features/verification/waitlist_page.js b/app/soapbox/features/verification/waitlist_page.tsx similarity index 91% rename from app/soapbox/features/verification/waitlist_page.js rename to app/soapbox/features/verification/waitlist_page.tsx index 14047b7b1..0a28f4993 100644 --- a/app/soapbox/features/verification/waitlist_page.js +++ b/app/soapbox/features/verification/waitlist_page.tsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React, { useEffect } from 'react'; import { useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; @@ -12,15 +11,15 @@ import { useAppSelector, useOwnAccount } from 'soapbox/hooks'; import { logOut } from '../../actions/auth'; import { Button, Stack, Text } from '../../components/ui'; -const WaitlistPage = ({ account }) => { +const WaitlistPage = (/* { account } */) => { const dispatch = useDispatch(); const intl = useIntl(); const title = useAppSelector((state) => state.instance.title); const me = useOwnAccount(); - const isSmsVerified = me.getIn(['source', 'sms_verified']); + const isSmsVerified = me?.source.get('sms_verified'); - const onClickLogOut = (event) => { + const onClickLogOut: React.MouseEventHandler = (event) => { event.preventDefault(); dispatch(logOut(intl)); }; @@ -76,8 +75,4 @@ const WaitlistPage = ({ account }) => { ); }; -WaitlistPage.propTypes = { - account: PropTypes.object, -}; - export default WaitlistPage;