mirror of
https://github.com/mastodon/mastodon.git
synced 2026-09-13 02:36:36 -05:00
Composer redesign: Poll duration (#40148)
This commit is contained in:
@@ -12,6 +12,8 @@ import { Icon } from '../icon';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
|
||||
export const buttonClasses = classes;
|
||||
|
||||
interface ButtonPropsBase<As extends 'a' | 'button'> {
|
||||
size?: 'lg' | 'md' | 'sm' | 'xs';
|
||||
variant?: 'solid' | 'ghost';
|
||||
|
||||
@@ -64,7 +64,7 @@ input.input {
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 2px solid var(--color-border-strong);
|
||||
outline: 2px solid var(--color-border-brand);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
|
||||
@@ -3,6 +3,8 @@ import { useCallback, useId } from 'react';
|
||||
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { PlusIcon } from '@phosphor-icons/react';
|
||||
|
||||
import { changePollSettings, removePoll } from '@/mastodon/actions/compose';
|
||||
@@ -11,12 +13,13 @@ import {
|
||||
deletePollOption,
|
||||
updatePollOption,
|
||||
} from '@/mastodon/actions/compose_typed';
|
||||
import { Button } from '@/mastodon/components/button/redesign';
|
||||
import { Button, buttonClasses } from '@/mastodon/components/button/redesign';
|
||||
import {
|
||||
ToggleField,
|
||||
TextInput,
|
||||
} from '@/mastodon/components/form_fields/redesign';
|
||||
import { useAppSelector, useAppDispatch } from '@/mastodon/store';
|
||||
import { DAY, HOUR, MINUTE } from '@/mastodon/utils/time';
|
||||
|
||||
import { selectComposePoll } from './selectors';
|
||||
import classes from './styles.module.scss';
|
||||
@@ -40,26 +43,31 @@ const messages = defineMessages({
|
||||
},
|
||||
});
|
||||
|
||||
const pollDurationOptions = [
|
||||
5 * MINUTE,
|
||||
30 * MINUTE,
|
||||
HOUR,
|
||||
12 * HOUR,
|
||||
DAY,
|
||||
3 * DAY,
|
||||
7 * DAY,
|
||||
];
|
||||
function durationToMessage(durationMs: number) {
|
||||
if (durationMs < HOUR) {
|
||||
return { message: messages.minutes, multiplier: MINUTE };
|
||||
} else if (durationMs < DAY) {
|
||||
return { message: messages.hours, multiplier: HOUR };
|
||||
}
|
||||
return { message: messages.days, multiplier: DAY };
|
||||
}
|
||||
|
||||
export const ComposePoll: React.FC = () => {
|
||||
const { options, maxOptions, expiresIn, multiple } =
|
||||
useAppSelector(selectComposePoll);
|
||||
const listId = useId();
|
||||
const intl = useIntl();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const handleAdd = useCallback(() => {
|
||||
dispatch(addPollOption());
|
||||
}, [dispatch]);
|
||||
const handlePollChangeMultiple: React.ChangeEventHandler<HTMLInputElement> =
|
||||
useCallback(
|
||||
(event) => {
|
||||
dispatch(changePollSettings(expiresIn, event.target.checked));
|
||||
},
|
||||
[dispatch, expiresIn],
|
||||
);
|
||||
const handleDelete = useCallback(() => {
|
||||
dispatch(removePoll());
|
||||
}, [dispatch]);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(index: number, event: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
const value = event.currentTarget.value;
|
||||
@@ -91,6 +99,28 @@ export const ComposePoll: React.FC = () => {
|
||||
},
|
||||
[dispatch, listId, maxOptions],
|
||||
);
|
||||
const handleAdd = useCallback(() => {
|
||||
dispatch(addPollOption());
|
||||
}, [dispatch]);
|
||||
const handlePollChangeMultiple: React.ChangeEventHandler<HTMLInputElement> =
|
||||
useCallback(
|
||||
(event) => {
|
||||
dispatch(changePollSettings(expiresIn, event.target.checked));
|
||||
},
|
||||
[dispatch, expiresIn],
|
||||
);
|
||||
const handleDurationChange: React.ChangeEventHandler<HTMLSelectElement> =
|
||||
useCallback(
|
||||
(event) => {
|
||||
dispatch(
|
||||
changePollSettings(Number.parseInt(event.target.value), multiple),
|
||||
);
|
||||
},
|
||||
[dispatch, multiple],
|
||||
);
|
||||
const handleDelete = useCallback(() => {
|
||||
dispatch(removePoll());
|
||||
}, [dispatch]);
|
||||
|
||||
const firstItemEmpty = !options.at(0);
|
||||
|
||||
@@ -138,22 +168,36 @@ export const ComposePoll: React.FC = () => {
|
||||
/>
|
||||
|
||||
<div className={classes.pollControls}>
|
||||
<FormattedMessage
|
||||
id='compose.poll.duration'
|
||||
defaultMessage='Duration: {button}'
|
||||
values={{
|
||||
button: (
|
||||
<Button color='tonal' size='xs'>
|
||||
<FormattedMessage
|
||||
id='intervals.full.days'
|
||||
defaultMessage='{number, plural, one {# day} other {# days}}'
|
||||
values={{ number: 1 }}
|
||||
/>
|
||||
</Button>
|
||||
),
|
||||
}}
|
||||
tagName='span'
|
||||
/>
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id='compose.poll.duration'
|
||||
defaultMessage='Duration:'
|
||||
description='Followed by current poll duration'
|
||||
/>
|
||||
|
||||
<select
|
||||
value={expiresIn}
|
||||
onChange={handleDurationChange}
|
||||
className={classNames(
|
||||
classes.pollDurationSelect,
|
||||
buttonClasses.base,
|
||||
buttonClasses.solid,
|
||||
buttonClasses.tonal,
|
||||
buttonClasses.xs,
|
||||
)}
|
||||
>
|
||||
{pollDurationOptions.map((duration) => {
|
||||
const { message, multiplier } = durationToMessage(duration);
|
||||
return (
|
||||
<option key={duration} value={duration}>
|
||||
{intl.formatMessage(message, {
|
||||
number: duration / multiplier,
|
||||
})}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
</span>
|
||||
|
||||
<Button
|
||||
variant='ghost'
|
||||
|
||||
@@ -272,8 +272,11 @@
|
||||
@include mixins.type-micro;
|
||||
|
||||
content: counter(poll, upper-alpha);
|
||||
width: 8px;
|
||||
padding: var(--space-2xs);
|
||||
width: var(--space-lg);
|
||||
height: var(--space-lg);
|
||||
flex-shrink: 0;
|
||||
line-height: var(--space-lg);
|
||||
text-align: center;
|
||||
border-radius: var(--radius-xs);
|
||||
background: var(--color-bg-highlight);
|
||||
}
|
||||
@@ -292,6 +295,10 @@
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.pollDurationSelect {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// Emoji picker
|
||||
|
||||
div.emojiRoot {
|
||||
|
||||
Reference in New Issue
Block a user