diff --git a/app/soapbox/features/compose/components/schedule_form.js b/app/soapbox/features/compose/components/schedule_form.js
deleted file mode 100644
index 73a94d0ef..000000000
--- a/app/soapbox/features/compose/components/schedule_form.js
+++ /dev/null
@@ -1,136 +0,0 @@
-'use strict';
-
-import classNames from 'classnames';
-import PropTypes from 'prop-types';
-import React from 'react';
-import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
-import { connect } from 'react-redux';
-
-import { setSchedule, removeSchedule } from 'soapbox/actions/compose';
-import IconButton from 'soapbox/components/icon_button';
-import { HStack, Stack, Text } from 'soapbox/components/ui';
-import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
-import { DatePicker } from 'soapbox/features/ui/util/async-components';
-
-const messages = defineMessages({
- schedule: { id: 'schedule.post_time', defaultMessage: 'Post Date/Time' },
- remove: { id: 'schedule.remove', defaultMessage: 'Remove schedule' },
-});
-
-const mapStateToProps = state => ({
- active: state.getIn(['compose', 'schedule']) ? true : false,
- scheduledAt: state.getIn(['compose', 'schedule']),
-});
-
-const mapDispatchToProps = dispatch => ({
- onSchedule(date) {
- dispatch(setSchedule(date));
- },
-
- onRemoveSchedule(date) {
- dispatch(removeSchedule());
- },
-});
-
-export default @connect(mapStateToProps, mapDispatchToProps)
-@injectIntl
-class ScheduleForm extends React.Component {
-
- static propTypes = {
- scheduledAt: PropTypes.instanceOf(Date),
- intl: PropTypes.object.isRequired,
- onSchedule: PropTypes.func.isRequired,
- onRemoveSchedule: PropTypes.func.isRequired,
- dispatch: PropTypes.func,
- active: PropTypes.bool,
- };
-
- state = {
- initialized: false,
- }
-
- setSchedule = date => {
- this.props.onSchedule(date);
- }
-
- setRef = c => {
- this.datePicker = c;
- }
-
- openDatePicker = () => {
- if (!this.datePicker) return;
- this.datePicker.setOpen(true);
- }
-
- isCurrentOrFutureDate(date) {
- return date && new Date().setHours(0, 0, 0, 0) <= new Date(date).setHours(0, 0, 0, 0);
- }
-
- isFiveMinutesFromNow(time) {
- const fiveMinutesFromNow = new Date(new Date().getTime() + 300000); // now, plus five minutes (Pleroma won't schedule posts )
- const selectedDate = new Date(time);
-
- return fiveMinutesFromNow.getTime() < selectedDate.getTime();
- }
-
- handleRemove = e => {
- this.props.onRemoveSchedule();
- e.preventDefault();
- }
-
- initialize = () => {
- const { initialized } = this.state;
-
- if (!initialized && this.datePicker) {
- this.openDatePicker();
- this.setState({ initialized: true });
- }
- }
-
- componentDidUpdate() {
- this.initialize();
- }
-
- render() {
- if (!this.props.active) {
- return null;
- }
-
- const { intl, scheduledAt } = this.props;
-
- return (
-
-
-
-
-
-
- {Component => ()}
-
-
-
-
- );
- }
-
-}
diff --git a/app/soapbox/features/compose/components/schedule_form.tsx b/app/soapbox/features/compose/components/schedule_form.tsx
new file mode 100644
index 000000000..6467ba51e
--- /dev/null
+++ b/app/soapbox/features/compose/components/schedule_form.tsx
@@ -0,0 +1,84 @@
+'use strict';
+
+import classNames from 'classnames';
+import React from 'react';
+import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
+
+import { setSchedule, removeSchedule } from 'soapbox/actions/compose';
+import IconButton from 'soapbox/components/icon_button';
+import { HStack, Stack, Text } from 'soapbox/components/ui';
+import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
+import { DatePicker } from 'soapbox/features/ui/util/async-components';
+import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
+
+const isCurrentOrFutureDate = (date: Date) => {
+ return date && new Date().setHours(0, 0, 0, 0) <= new Date(date).setHours(0, 0, 0, 0);
+};
+
+const isFiveMinutesFromNow = (time: Date) => {
+ const fiveMinutesFromNow = new Date(new Date().getTime() + 300000); // now, plus five minutes (Pleroma won't schedule posts )
+ const selectedDate = new Date(time);
+
+ return fiveMinutesFromNow.getTime() < selectedDate.getTime();
+};
+
+const messages = defineMessages({
+ schedule: { id: 'schedule.post_time', defaultMessage: 'Post Date/Time' },
+ remove: { id: 'schedule.remove', defaultMessage: 'Remove schedule' },
+});
+
+const ScheduleForm: React.FC = () => {
+ const dispatch = useAppDispatch();
+ const intl = useIntl();
+
+ const scheduledAt = useAppSelector((state) => state.compose.get('schedule'));
+ const active = !!scheduledAt;
+
+ const onSchedule = (date: Date) => {
+ dispatch(setSchedule(date));
+ };
+
+ const handleRemove = (e: React.MouseEvent) => {
+ dispatch(removeSchedule());
+ e.preventDefault();
+ };
+
+ if (!active) {
+ return null;
+ }
+
+ return (
+
+
+
+
+
+
+ {Component => ()}
+
+
+
+
+ );
+};
+
+export default ScheduleForm;