Merge remote-tracking branch 'parent/main' into upstream-20240123
This commit is contained in:
commit
50ae2d9439
320 changed files with 2587 additions and 2817 deletions
|
@ -1,18 +0,0 @@
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import { length } from 'stringz';
|
||||
|
||||
export const CharacterCounter = ({ text, max }) => {
|
||||
const diff = max - length(text);
|
||||
|
||||
if (diff < 0) {
|
||||
return <span className='character-counter character-counter--over'>{diff}</span>;
|
||||
}
|
||||
|
||||
return <span className='character-counter'>{diff}</span>;
|
||||
};
|
||||
|
||||
CharacterCounter.propTypes = {
|
||||
text: PropTypes.string.isRequired,
|
||||
max: PropTypes.number.isRequired,
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
import { length } from 'stringz';
|
||||
|
||||
export const CharacterCounter: React.FC<{
|
||||
text: string;
|
||||
max: number;
|
||||
}> = ({ text, max }) => {
|
||||
const diff = max - length(text);
|
||||
|
||||
if (diff < 0) {
|
||||
return (
|
||||
<span className='character-counter character-counter--over'>{diff}</span>
|
||||
);
|
||||
}
|
||||
|
||||
return <span className='character-counter'>{diff}</span>;
|
||||
};
|
|
@ -332,6 +332,7 @@ class ComposeForm extends ImmutablePureComponent {
|
|||
<div className='compose-form__submit'>
|
||||
<Button
|
||||
type='submit'
|
||||
compact
|
||||
text={intl.formatMessage(this.props.isEditing ? messages.saveChanges : (this.props.isInReply ? messages.reply : messages.publish))}
|
||||
disabled={!this.canSubmit()}
|
||||
/>
|
||||
|
|
|
@ -27,6 +27,7 @@ class LanguageDropdownMenu extends PureComponent {
|
|||
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
guess: PropTypes.string,
|
||||
frequentlyUsedLanguages: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
|
@ -81,14 +82,17 @@ class LanguageDropdownMenu extends PureComponent {
|
|||
};
|
||||
|
||||
search () {
|
||||
const { languages, value, frequentlyUsedLanguages } = this.props;
|
||||
const { languages, value, frequentlyUsedLanguages, guess } = this.props;
|
||||
const { searchValue } = this.state;
|
||||
|
||||
if (searchValue === '') {
|
||||
return [...languages].sort((a, b) => {
|
||||
// Push current selection to the top of the list
|
||||
|
||||
if (a[0] === value) {
|
||||
if (guess && a[0] === guess) { // Push guessed language higher than current selection
|
||||
return -1;
|
||||
} else if (guess && b[0] === guess) {
|
||||
return 1;
|
||||
} else if (a[0] === value) { // Push current selection to the top of the list
|
||||
return -1;
|
||||
} else if (b[0] === value) {
|
||||
return 1;
|
||||
|
@ -238,6 +242,7 @@ class LanguageDropdown extends PureComponent {
|
|||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
frequentlyUsedLanguages: PropTypes.arrayOf(PropTypes.string),
|
||||
guess: PropTypes.string,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onChange: PropTypes.func,
|
||||
};
|
||||
|
@ -281,7 +286,7 @@ class LanguageDropdown extends PureComponent {
|
|||
};
|
||||
|
||||
render () {
|
||||
const { value, intl, frequentlyUsedLanguages } = this.props;
|
||||
const { value, guess, intl, frequentlyUsedLanguages } = this.props;
|
||||
const { open, placement } = this.state;
|
||||
const current = preloadedLanguages.find(lang => lang[0] === value) ?? [];
|
||||
|
||||
|
@ -294,7 +299,7 @@ class LanguageDropdown extends PureComponent {
|
|||
onClick={this.handleToggle}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onKeyDown={this.handleButtonKeyDown}
|
||||
className={classNames('dropdown-button', { active: open })}
|
||||
className={classNames('dropdown-button', { active: open, warning: guess !== '' && guess !== value })}
|
||||
>
|
||||
<Icon icon={TranslateIcon} />
|
||||
<span className='dropdown-button__label'>{current[2] ?? value}</span>
|
||||
|
@ -306,6 +311,7 @@ class LanguageDropdown extends PureComponent {
|
|||
<div className={`dropdown-animation language-dropdown__dropdown ${placement}`} >
|
||||
<LanguageDropdownMenu
|
||||
value={value}
|
||||
guess={guess}
|
||||
frequentlyUsedLanguages={frequentlyUsedLanguages}
|
||||
onClose={this.handleClose}
|
||||
onChange={this.handleChange}
|
||||
|
|
|
@ -4,16 +4,16 @@ import { FormattedMessage } from 'react-intl';
|
|||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import type { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
|
||||
import { useSortable } from '@dnd-kit/sortable';
|
||||
import { CSS } from '@dnd-kit/utilities';
|
||||
|
||||
import CloseIcon from '@/material-icons/400-20px/close.svg?react';
|
||||
import EditIcon from '@/material-icons/400-24px/edit.svg?react';
|
||||
import WarningIcon from '@/material-icons/400-24px/warning.svg?react';
|
||||
import {
|
||||
undoUploadCompose,
|
||||
initMediaEditModal,
|
||||
} from 'mastodon/actions/compose';
|
||||
import { undoUploadCompose } from 'mastodon/actions/compose';
|
||||
import { openModal } from 'mastodon/actions/modal';
|
||||
import { Blurhash } from 'mastodon/components/blurhash';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import type { MediaAttachment } from 'mastodon/models/media_attachment';
|
||||
|
@ -27,16 +27,15 @@ export const Upload: React.FC<{
|
|||
wide?: boolean;
|
||||
}> = ({ id, dragging, overlay, tall, wide }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const media = useAppSelector(
|
||||
(state) =>
|
||||
state.compose // eslint-disable-line @typescript-eslint/no-unsafe-call
|
||||
.get('media_attachments') // eslint-disable-line @typescript-eslint/no-unsafe-member-access
|
||||
.find((item: MediaAttachment) => item.get('id') === id) as // eslint-disable-line @typescript-eslint/no-unsafe-member-access
|
||||
| MediaAttachment
|
||||
| undefined,
|
||||
const media = useAppSelector((state) =>
|
||||
(
|
||||
(state.compose as ImmutableMap<string, unknown>).get(
|
||||
'media_attachments',
|
||||
) as ImmutableList<MediaAttachment>
|
||||
).find((item) => item.get('id') === id),
|
||||
);
|
||||
const sensitive = useAppSelector(
|
||||
(state) => state.compose.get('spoiler') as boolean, // eslint-disable-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
||||
(state) => state.compose.get('spoiler') as boolean,
|
||||
);
|
||||
|
||||
const handleUndoClick = useCallback(() => {
|
||||
|
@ -44,7 +43,9 @@ export const Upload: React.FC<{
|
|||
}, [dispatch, id]);
|
||||
|
||||
const handleFocalPointClick = useCallback(() => {
|
||||
dispatch(initMediaEditModal(id));
|
||||
dispatch(
|
||||
openModal({ modalType: 'FOCAL_POINT', modalProps: { mediaId: id } }),
|
||||
);
|
||||
}, [dispatch, id]);
|
||||
|
||||
const { attributes, listeners, setNodeRef, transform, transition } =
|
||||
|
|
|
@ -2,7 +2,11 @@ import { useState, useCallback, useMemo } from 'react';
|
|||
|
||||
import { useIntl, defineMessages } from 'react-intl';
|
||||
|
||||
import type { List } from 'immutable';
|
||||
import type {
|
||||
List,
|
||||
Map as ImmutableMap,
|
||||
List as ImmutableList,
|
||||
} from 'immutable';
|
||||
|
||||
import type {
|
||||
DragStartEvent,
|
||||
|
@ -63,18 +67,20 @@ export const UploadForm: React.FC = () => {
|
|||
const intl = useIntl();
|
||||
const mediaIds = useAppSelector(
|
||||
(state) =>
|
||||
state.compose // eslint-disable-line @typescript-eslint/no-unsafe-call
|
||||
.get('media_attachments') // eslint-disable-line @typescript-eslint/no-unsafe-member-access
|
||||
.map((item: MediaAttachment) => item.get('id')) as List<string>, // eslint-disable-line @typescript-eslint/no-unsafe-member-access
|
||||
(
|
||||
(state.compose as ImmutableMap<string, unknown>).get(
|
||||
'media_attachments',
|
||||
) as ImmutableList<MediaAttachment>
|
||||
).map((item: MediaAttachment) => item.get('id')) as List<string>,
|
||||
);
|
||||
const active = useAppSelector(
|
||||
(state) => state.compose.get('is_uploading') as boolean, // eslint-disable-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
||||
(state) => state.compose.get('is_uploading') as boolean,
|
||||
);
|
||||
const progress = useAppSelector(
|
||||
(state) => state.compose.get('progress') as number, // eslint-disable-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
||||
(state) => state.compose.get('progress') as number,
|
||||
);
|
||||
const isProcessing = useAppSelector(
|
||||
(state) => state.compose.get('is_processing') as boolean, // eslint-disable-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
||||
(state) => state.compose.get('is_processing') as boolean,
|
||||
);
|
||||
const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null);
|
||||
const sensors = useSensors(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue