Improve design of the rich text editor (#9533)

New design for rich text composer
This commit is contained in:
Florian Duros 2022-11-04 16:36:50 +01:00 committed by GitHub
parent 9101b42de8
commit 5ca9accce2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 668 additions and 270 deletions

View file

@ -25,9 +25,8 @@ import { THREAD_RELATION_TYPE } from 'matrix-js-sdk/src/models/thread';
import { _t } from '../../../languageHandler';
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
import { CollapsibleButton } from './CollapsibleButton';
import ContextMenu, { aboveLeftOf, AboveLeftOf, useContextMenu } from '../../structures/ContextMenu';
import { AboveLeftOf } from '../../structures/ContextMenu';
import dis from '../../../dispatcher/dispatcher';
import EmojiPicker from '../emojipicker/EmojiPicker';
import ErrorDialog from "../dialogs/ErrorDialog";
import LocationButton from '../location/LocationButton';
import Modal from "../../../Modal";
@ -39,6 +38,8 @@ import RoomContext from '../../../contexts/RoomContext';
import { useDispatcher } from "../../../hooks/useDispatcher";
import { chromeFileInputFix } from "../../../utils/BrowserWorkarounds";
import IconizedContextMenu, { IconizedContextMenuOptionList } from '../context_menus/IconizedContextMenu';
import { EmojiButton } from './EmojiButton';
import { useSettingValue } from '../../../hooks/useSettings';
interface IProps {
addEmoji: (emoji: string) => boolean;
@ -56,7 +57,6 @@ interface IProps {
showVoiceBroadcastButton: boolean;
onStartVoiceBroadcastClick: () => void;
isRichTextEnabled: boolean;
showComposerModeButton: boolean;
onComposerModeClick: () => void;
}
@ -67,6 +67,8 @@ const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
const matrixClient: MatrixClient = useContext(MatrixClientContext);
const { room, roomId, narrow } = useContext(RoomContext);
const isWysiwygLabEnabled = useSettingValue<boolean>('feature_wysiwyg_composer');
if (props.haveRecording) {
return null;
}
@ -75,7 +77,9 @@ const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
let moreButtons: ReactElement[];
if (narrow) {
mainButtons = [
emojiButton(props),
isWysiwygLabEnabled ?
<ComposerModeButton key="composerModeButton" isRichTextEnabled={props.isRichTextEnabled} onClick={props.onComposerModeClick} /> :
emojiButton(props),
];
moreButtons = [
uploadButton(), // props passed via UploadButtonContext
@ -87,9 +91,9 @@ const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
];
} else {
mainButtons = [
emojiButton(props),
props.showComposerModeButton &&
<ComposerModeButton key="composerModeButton" isRichTextEnabled={props.isRichTextEnabled} onClick={props.onComposerModeClick} />,
isWysiwygLabEnabled ?
<ComposerModeButton key="composerModeButton" isRichTextEnabled={props.isRichTextEnabled} onClick={props.onComposerModeClick} /> :
emojiButton(props),
uploadButton(), // props passed via UploadButtonContext
];
moreButtons = [
@ -139,58 +143,10 @@ function emojiButton(props: IProps): ReactElement {
key="emoji_button"
addEmoji={props.addEmoji}
menuPosition={props.menuPosition}
className="mx_MessageComposer_button"
/>;
}
interface IEmojiButtonProps {
addEmoji: (unicode: string) => boolean;
menuPosition: AboveLeftOf;
}
const EmojiButton: React.FC<IEmojiButtonProps> = ({ addEmoji, menuPosition }) => {
const overflowMenuCloser = useContext(OverflowMenuContext);
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
let contextMenu: React.ReactElement | null = null;
if (menuDisplayed) {
const position = (
menuPosition ?? aboveLeftOf(button.current.getBoundingClientRect())
);
contextMenu = <ContextMenu
{...position}
onFinished={() => {
closeMenu();
overflowMenuCloser?.();
}}
managed={false}
>
<EmojiPicker onChoose={addEmoji} showQuickReactions={true} />
</ContextMenu>;
}
const className = classNames(
"mx_MessageComposer_button",
{
"mx_MessageComposer_button_highlight": menuDisplayed,
},
);
// TODO: replace ContextMenuTooltipButton with a unified representation of
// the header buttons and the right panel buttons
return <React.Fragment>
<CollapsibleButton
className={className}
iconClassName="mx_MessageComposer_emoji"
onClick={openMenu}
title={_t("Emoji")}
inputRef={button}
/>
{ contextMenu }
</React.Fragment>;
};
function uploadButton(): ReactElement {
return <UploadButton key="controls_upload" />;
}
@ -408,7 +364,7 @@ interface WysiwygToggleButtonProps {
}
function ComposerModeButton({ isRichTextEnabled, onClick }: WysiwygToggleButtonProps) {
const title = isRichTextEnabled ? _t("Show plain text") : _t("Show formatting");
const title = isRichTextEnabled ? _t("Hide formatting") : _t("Show formatting");
return <CollapsibleButton
className="mx_MessageComposer_button"