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 866b61429..000000000 --- a/app/soapbox/features/compose/components/schedule_form.js +++ /dev/null @@ -1,129 +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 IconButton from 'soapbox/components/icon_button'; -import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; -import { DatePicker } from 'soapbox/features/ui/util/async-components'; - -import { setSchedule, removeSchedule } from '../../../actions/compose'; - -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; diff --git a/app/styles/components/datepicker.scss b/app/styles/components/datepicker.scss index 60cb58409..ed5a5d839 100644 --- a/app/styles/components/datepicker.scss +++ b/app/styles/components/datepicker.scss @@ -1,14 +1,22 @@ .react-datepicker { - @apply p-4 font-sans text-xs text-gray-900 border border-solid border-gray-200 rounded-lg; + @apply dark:bg-slate-900 dark:border-slate-700 p-4 font-sans text-xs text-gray-900 dark:text-gray-300 border border-solid border-gray-200 rounded-lg; +} + +.react-datepicker__input-container > input { + @apply dark:bg-slate-800 dark:text-white block w-full sm:text-sm border-gray-300 dark:border-gray-600 rounded-md focus:ring-indigo-500 focus:border-indigo-500; + + &.has-error { + @apply text-red-600 border-red-600; + } } .react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle::before, .react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle::after { - @apply border-b-white; + @apply border-b-white dark:border-b-slate-900; } .react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle::before { - @apply border-b-gray-200; + @apply border-b-gray-200 dark:border-b-slate-700; } .react-datepicker__header:not(.react-datepicker__header--has-time-select) { @@ -16,14 +24,14 @@ } .react-datepicker__header { - @apply bg-white border-b-0 py-1 px-0; + @apply bg-white dark:bg-slate-900 border-b-0 py-1 px-0; // border-top-left-radius: var(--border-radius-lg); } .react-datepicker__current-month, .react-datepicker-time__header, .react-datepicker-year-header { - @apply text-gray-900 font-bold text-sm; + @apply text-gray-900 dark:text-gray-300 font-bold text-sm; } .react-datepicker__current-month { @@ -31,7 +39,7 @@ } .react-datepicker__navigation { - @apply top-4 h-8 w-8 rounded hover:bg-gray-50; + @apply top-4 h-8 w-8 rounded hover:bg-gray-50 dark:hover:bg-slate-900/50; } .react-datepicker__navigation-icon { @@ -70,24 +78,37 @@ .react-datepicker__day-names, .react-datepicker__week { - display: flex; - justify-content: space-between; + @apply flex justify-between; +} + +.react-datepicker__time { + @apply dark:bg-slate-900; +} + +.react-datepicker__time-container { + @apply dark:border-slate-700; } .react-datepicker__day-name, .react-datepicker__day, .react-datepicker__time-name { - @apply text-gray-900; + @apply text-gray-900 dark:text-gray-300; width: 30px; height: 30px; line-height: 30px; } +.react-datepicker__time-list-item--disabled, +.react-datepicker__day--disabled { + @apply text-gray-400 dark:text-gray-500; +} + .react-datepicker__day:hover, .react-datepicker__month-text:hover, .react-datepicker__quarter-text:hover, -.react-datepicker__year-text:hover { - @apply bg-gray-100 rounded; +.react-datepicker__year-text:hover, +.react-datepicker__time-list-item:hover { + @apply bg-gray-100 dark:bg-slate-700 rounded; } .react-datepicker__day--selected, @@ -102,16 +123,12 @@ .react-datepicker__year-text--selected, .react-datepicker__year-text--in-selecting-range, .react-datepicker__year-text--in-range { - @apply bg-primary-600 hover:bg-primary-700 text-white rounded; -} - -.react-datepicker__day--disabled { - @apply text-gray-400; + @apply bg-primary-600 hover:bg-primary-700 dark:bg-slate-300 dark:hover:bg-slate-200 text-white dark:text-black rounded; } .react-datepicker__day--keyboard-selected, .react-datepicker__month-text--keyboard-selected, .react-datepicker__quarter-text--keyboard-selected, .react-datepicker__year-text--keyboard-selected { - @apply bg-primary-50 hover:bg-primary-100 text-primary-600 dark:text-primary-400; + @apply bg-primary-50 hover:bg-primary-100 dark:bg-slate-700 dark:hover:bg-slate-600 text-primary-600 dark:text-primary-400; }