Fix accessibility and consistency of MessageComposerButtons (#7679)
This commit is contained in:
parent
a17d585a12
commit
991257cbc3
8 changed files with 94 additions and 75 deletions
|
@ -192,11 +192,14 @@ limitations under the License.
|
||||||
line-height: var(--size);
|
line-height: var(--size);
|
||||||
width: auto;
|
width: auto;
|
||||||
padding-left: var(--size);
|
padding-left: var(--size);
|
||||||
border-radius: 100%;
|
|
||||||
margin-right: 6px;
|
|
||||||
|
|
||||||
&:last-child {
|
&:not(.mx_CallContextMenu_item) {
|
||||||
margin-right: auto;
|
border-radius: 50%;
|
||||||
|
margin-right: 6px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
|
@ -407,6 +410,7 @@ limitations under the License.
|
||||||
align-items: center;
|
align-items: center;
|
||||||
max-width: unset;
|
max-width: unset;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
margin: 7px 7px 7px 16px; // space out the buttons
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MessageComposer_Menu .mx_ContextualMenu {
|
.mx_MessageComposer_Menu .mx_ContextualMenu {
|
||||||
|
|
|
@ -453,7 +453,13 @@ export const alwaysAboveRightOf = (elementRect: DOMRect, chevronFace = ChevronFa
|
||||||
return menuOptions;
|
return menuOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ContextMenuTuple<T> = [boolean, RefObject<T>, () => void, () => void, (val: boolean) => void];
|
type ContextMenuTuple<T> = [
|
||||||
|
boolean,
|
||||||
|
RefObject<T>,
|
||||||
|
(ev?: SyntheticEvent) => void,
|
||||||
|
(ev?: SyntheticEvent) => void,
|
||||||
|
(val: boolean) => void,
|
||||||
|
];
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
|
||||||
export const useContextMenu = <T extends any = HTMLElement>(): ContextMenuTuple<T> => {
|
export const useContextMenu = <T extends any = HTMLElement>(): ContextMenuTuple<T> => {
|
||||||
const button = useRef<T>(null);
|
const button = useRef<T>(null);
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { ReactElement, useContext } from 'react';
|
import React, { ReactElement, SyntheticEvent, useContext } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
|
import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
@ -23,25 +23,29 @@ import { makeLocationContent } from "matrix-js-sdk/src/content-helpers";
|
||||||
|
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import LocationPicker from './LocationPicker';
|
import LocationPicker from './LocationPicker';
|
||||||
import { CollapsibleButton, ICollapsibleButtonProps } from '../rooms/CollapsibleButton';
|
import { CollapsibleButton } from '../rooms/CollapsibleButton';
|
||||||
import ContextMenu, { aboveLeftOf, useContextMenu, AboveLeftOf } from "../../structures/ContextMenu";
|
import ContextMenu, { aboveLeftOf, useContextMenu, AboveLeftOf } from "../../structures/ContextMenu";
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import QuestionDialog from '../dialogs/QuestionDialog';
|
import QuestionDialog from '../dialogs/QuestionDialog';
|
||||||
import MatrixClientContext from '../../../contexts/MatrixClientContext';
|
import MatrixClientContext from '../../../contexts/MatrixClientContext';
|
||||||
|
import { OverflowMenuContext } from "../rooms/MessageComposerButtons";
|
||||||
|
|
||||||
interface IProps extends Pick<ICollapsibleButtonProps, "narrowMode"> {
|
interface IProps {
|
||||||
roomId: string;
|
roomId: string;
|
||||||
sender: RoomMember;
|
sender: RoomMember;
|
||||||
menuPosition: AboveLeftOf;
|
menuPosition: AboveLeftOf;
|
||||||
narrowMode: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LocationButton: React.FC<IProps> = (
|
export const LocationButton: React.FC<IProps> = ({ roomId, sender, menuPosition }) => {
|
||||||
{ roomId, sender, menuPosition, narrowMode },
|
const overflowMenuCloser = useContext(OverflowMenuContext);
|
||||||
) => {
|
|
||||||
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
|
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
|
||||||
const matrixClient = useContext(MatrixClientContext);
|
const matrixClient = useContext(MatrixClientContext);
|
||||||
|
|
||||||
|
const _onFinished = (ev?: SyntheticEvent) => {
|
||||||
|
closeMenu(ev);
|
||||||
|
overflowMenuCloser?.();
|
||||||
|
};
|
||||||
|
|
||||||
let contextMenu: ReactElement;
|
let contextMenu: ReactElement;
|
||||||
if (menuDisplayed) {
|
if (menuDisplayed) {
|
||||||
const position = menuPosition ?? aboveLeftOf(
|
const position = menuPosition ?? aboveLeftOf(
|
||||||
|
@ -49,13 +53,13 @@ export const LocationButton: React.FC<IProps> = (
|
||||||
|
|
||||||
contextMenu = <ContextMenu
|
contextMenu = <ContextMenu
|
||||||
{...position}
|
{...position}
|
||||||
onFinished={closeMenu}
|
onFinished={_onFinished}
|
||||||
managed={false}
|
managed={false}
|
||||||
>
|
>
|
||||||
<LocationPicker
|
<LocationPicker
|
||||||
sender={sender}
|
sender={sender}
|
||||||
onChoose={shareLocation(matrixClient, roomId, openMenu)}
|
onChoose={shareLocation(matrixClient, roomId, openMenu)}
|
||||||
onFinished={closeMenu}
|
onFinished={_onFinished}
|
||||||
/>
|
/>
|
||||||
</ContextMenu>;
|
</ContextMenu>;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +78,6 @@ export const LocationButton: React.FC<IProps> = (
|
||||||
<CollapsibleButton
|
<CollapsibleButton
|
||||||
className={className}
|
className={className}
|
||||||
onClick={openMenu}
|
onClick={openMenu}
|
||||||
narrowMode={narrowMode}
|
|
||||||
title={_t("Share location")}
|
title={_t("Share location")}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -14,23 +14,29 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { ComponentProps } from 'react';
|
import React, { ComponentProps, useContext } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
|
import { MenuItem } from "../../structures/ContextMenu";
|
||||||
|
import { OverflowMenuContext } from './MessageComposerButtons';
|
||||||
|
|
||||||
export interface ICollapsibleButtonProps
|
interface ICollapsibleButtonProps extends ComponentProps<typeof MenuItem> {
|
||||||
extends ComponentProps<typeof AccessibleTooltipButton>
|
|
||||||
{
|
|
||||||
narrowMode: boolean;
|
|
||||||
title: string;
|
title: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CollapsibleButton = ({ narrowMode, title, ...props }: ICollapsibleButtonProps) => {
|
export const CollapsibleButton = ({ title, className, ...props }: ICollapsibleButtonProps) => {
|
||||||
return <AccessibleTooltipButton
|
const inOverflowMenu = !!useContext(OverflowMenuContext);
|
||||||
{...props}
|
if (inOverflowMenu) {
|
||||||
title={narrowMode ? undefined : title}
|
return <MenuItem
|
||||||
label={narrowMode ? title : undefined}
|
{...props}
|
||||||
/>;
|
className={classNames("mx_CallContextMenu_item", className)}
|
||||||
|
>
|
||||||
|
{ title }
|
||||||
|
</MenuItem>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <AccessibleTooltipButton {...props} title={title} className={className} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CollapsibleButton;
|
export default CollapsibleButton;
|
||||||
|
|
|
@ -330,7 +330,10 @@ export default class MessageComposer extends React.Component<IProps, IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
private setStickerPickerOpen = (isStickerPickerOpen: boolean) => {
|
private setStickerPickerOpen = (isStickerPickerOpen: boolean) => {
|
||||||
this.setState({ isStickerPickerOpen });
|
this.setState({
|
||||||
|
isStickerPickerOpen,
|
||||||
|
isMenuOpen: false,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
private toggleButtonMenu = (): void => {
|
private toggleButtonMenu = (): void => {
|
||||||
|
@ -453,7 +456,12 @@ export default class MessageComposer extends React.Component<IProps, IState> {
|
||||||
menuPosition={menuPosition}
|
menuPosition={menuPosition}
|
||||||
narrowMode={this.state.narrowMode}
|
narrowMode={this.state.narrowMode}
|
||||||
relation={this.props.relation}
|
relation={this.props.relation}
|
||||||
onRecordStartEndClick={() => this.voiceRecordingButton.current?.onRecordStartEndClick()}
|
onRecordStartEndClick={() => {
|
||||||
|
this.voiceRecordingButton.current?.onRecordStartEndClick();
|
||||||
|
if (this.state.narrowMode) {
|
||||||
|
this.toggleButtonMenu();
|
||||||
|
}
|
||||||
|
}}
|
||||||
setStickerPickerOpen={this.setStickerPickerOpen}
|
setStickerPickerOpen={this.setStickerPickerOpen}
|
||||||
showLocationButton={this.state.showLocationButton}
|
showLocationButton={this.state.showLocationButton}
|
||||||
showStickersButton={this.state.showStickersButton}
|
showStickersButton={this.state.showStickersButton}
|
||||||
|
|
|
@ -17,14 +17,14 @@ limitations under the License.
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { IEventRelation } from "matrix-js-sdk/src/models/event";
|
import { IEventRelation } from "matrix-js-sdk/src/models/event";
|
||||||
import { M_POLL_START } from "matrix-events-sdk";
|
import { M_POLL_START } from "matrix-events-sdk";
|
||||||
import React, { ReactElement, useContext } from 'react';
|
import React, { createContext, ReactElement, useContext } from 'react';
|
||||||
import { Room } from 'matrix-js-sdk/src/models/room';
|
import { Room } from 'matrix-js-sdk/src/models/room';
|
||||||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||||
|
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
import { CollapsibleButton, ICollapsibleButtonProps } from './CollapsibleButton';
|
import { CollapsibleButton } from './CollapsibleButton';
|
||||||
import ContextMenu, { aboveLeftOf, AboveLeftOf, MenuItem, useContextMenu } from '../../structures/ContextMenu';
|
import ContextMenu, { aboveLeftOf, AboveLeftOf, useContextMenu } from '../../structures/ContextMenu';
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import EmojiPicker from '../emojipicker/EmojiPicker';
|
import EmojiPicker from '../emojipicker/EmojiPicker';
|
||||||
import ErrorDialog from "../dialogs/ErrorDialog";
|
import ErrorDialog from "../dialogs/ErrorDialog";
|
||||||
|
@ -52,6 +52,9 @@ interface IProps {
|
||||||
toggleButtonMenu: () => void;
|
toggleButtonMenu: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OverflowMenuCloser = () => void;
|
||||||
|
export const OverflowMenuContext = createContext<OverflowMenuCloser | null>(null);
|
||||||
|
|
||||||
const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
|
const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
|
||||||
const matrixClient: MatrixClient = useContext(MatrixClientContext);
|
const matrixClient: MatrixClient = useContext(MatrixClientContext);
|
||||||
const { room, roomId } = useContext(RoomContext);
|
const { room, roomId } = useContext(RoomContext);
|
||||||
|
@ -107,7 +110,6 @@ function narrowMode(
|
||||||
className={moreOptionsClasses}
|
className={moreOptionsClasses}
|
||||||
onClick={props.toggleButtonMenu}
|
onClick={props.toggleButtonMenu}
|
||||||
title={_t("More options")}
|
title={_t("More options")}
|
||||||
tooltip={false}
|
|
||||||
/>
|
/>
|
||||||
{ props.isMenuOpen && (
|
{ props.isMenuOpen && (
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
|
@ -115,15 +117,9 @@ function narrowMode(
|
||||||
{...props.menuPosition}
|
{...props.menuPosition}
|
||||||
wrapperClassName="mx_MessageComposer_Menu"
|
wrapperClassName="mx_MessageComposer_Menu"
|
||||||
>
|
>
|
||||||
{ moreButtons.map((button, index) => (
|
<OverflowMenuContext.Provider value={props.toggleButtonMenu}>
|
||||||
<MenuItem
|
{ moreButtons }
|
||||||
className="mx_CallContextMenu_item"
|
</OverflowMenuContext.Provider>
|
||||||
key={index}
|
|
||||||
onClick={props.toggleButtonMenu}
|
|
||||||
>
|
|
||||||
{ button }
|
|
||||||
</MenuItem>
|
|
||||||
)) }
|
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
) }
|
) }
|
||||||
</>;
|
</>;
|
||||||
|
@ -134,18 +130,16 @@ function emojiButton(props: IProps): ReactElement {
|
||||||
key="emoji_button"
|
key="emoji_button"
|
||||||
addEmoji={props.addEmoji}
|
addEmoji={props.addEmoji}
|
||||||
menuPosition={props.menuPosition}
|
menuPosition={props.menuPosition}
|
||||||
narrowMode={props.narrowMode}
|
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IEmojiButtonProps extends Pick<ICollapsibleButtonProps, "narrowMode"> {
|
interface IEmojiButtonProps {
|
||||||
addEmoji: (unicode: string) => boolean;
|
addEmoji: (unicode: string) => boolean;
|
||||||
menuPosition: AboveLeftOf;
|
menuPosition: AboveLeftOf;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EmojiButton: React.FC<IEmojiButtonProps> = (
|
const EmojiButton: React.FC<IEmojiButtonProps> = ({ addEmoji, menuPosition }) => {
|
||||||
{ addEmoji, menuPosition, narrowMode },
|
const overflowMenuCloser = useContext(OverflowMenuContext);
|
||||||
) => {
|
|
||||||
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
|
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
|
||||||
|
|
||||||
let contextMenu: React.ReactElement | null = null;
|
let contextMenu: React.ReactElement | null = null;
|
||||||
|
@ -156,7 +150,10 @@ const EmojiButton: React.FC<IEmojiButtonProps> = (
|
||||||
|
|
||||||
contextMenu = <ContextMenu
|
contextMenu = <ContextMenu
|
||||||
{...position}
|
{...position}
|
||||||
onFinished={closeMenu}
|
onFinished={() => {
|
||||||
|
closeMenu();
|
||||||
|
overflowMenuCloser?.();
|
||||||
|
}}
|
||||||
managed={false}
|
managed={false}
|
||||||
>
|
>
|
||||||
<EmojiPicker onChoose={addEmoji} showQuickReactions={true} />
|
<EmojiPicker onChoose={addEmoji} showQuickReactions={true} />
|
||||||
|
@ -177,7 +174,6 @@ const EmojiButton: React.FC<IEmojiButtonProps> = (
|
||||||
<CollapsibleButton
|
<CollapsibleButton
|
||||||
className={className}
|
className={className}
|
||||||
onClick={openMenu}
|
onClick={openMenu}
|
||||||
narrowMode={narrowMode}
|
|
||||||
title={_t("Add emoji")}
|
title={_t("Add emoji")}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -274,19 +270,18 @@ class UploadButton extends React.Component<IUploadButtonProps> {
|
||||||
function showStickersButton(props: IProps): ReactElement {
|
function showStickersButton(props: IProps): ReactElement {
|
||||||
return (
|
return (
|
||||||
props.showStickersButton
|
props.showStickersButton
|
||||||
? <AccessibleTooltipButton
|
? <CollapsibleButton
|
||||||
id='stickersButton'
|
id='stickersButton'
|
||||||
key="controls_stickers"
|
key="controls_stickers"
|
||||||
className="mx_MessageComposer_button mx_MessageComposer_stickers"
|
className="mx_MessageComposer_button mx_MessageComposer_stickers"
|
||||||
onClick={() => props.setStickerPickerOpen(!props.isStickerPickerOpen)}
|
onClick={() => props.setStickerPickerOpen(!props.isStickerPickerOpen)}
|
||||||
title={
|
title={
|
||||||
props.narrowMode
|
props.narrowMode
|
||||||
? null
|
? _t("Send a sticker")
|
||||||
: props.isStickerPickerOpen
|
: props.isStickerPickerOpen
|
||||||
? _t("Hide Stickers")
|
? _t("Hide Stickers")
|
||||||
: _t("Show Stickers")
|
: _t("Show Stickers")
|
||||||
}
|
}
|
||||||
label={props.narrowMode ? _t("Send a sticker") : null}
|
|
||||||
/>
|
/>
|
||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
@ -302,25 +297,23 @@ function voiceRecordingButton(props: IProps): ReactElement {
|
||||||
className="mx_MessageComposer_button mx_MessageComposer_voiceMessage"
|
className="mx_MessageComposer_button mx_MessageComposer_voiceMessage"
|
||||||
onClick={props.onRecordStartEndClick}
|
onClick={props.onRecordStartEndClick}
|
||||||
title={_t("Send voice message")}
|
title={_t("Send voice message")}
|
||||||
narrowMode={props.narrowMode}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function pollButton(props: IProps, room: Room): ReactElement {
|
function pollButton(props: IProps, room: Room): ReactElement {
|
||||||
return <PollButton
|
return <PollButton key="polls" room={room} />;
|
||||||
key="polls"
|
|
||||||
room={room}
|
|
||||||
narrowMode={props.narrowMode}
|
|
||||||
/>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IPollButtonProps extends Pick<ICollapsibleButtonProps, "narrowMode"> {
|
interface IPollButtonProps {
|
||||||
room: Room;
|
room: Room;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PollButton extends React.PureComponent<IPollButtonProps> {
|
class PollButton extends React.PureComponent<IPollButtonProps> {
|
||||||
|
static contextType = OverflowMenuContext;
|
||||||
|
|
||||||
private onCreateClick = () => {
|
private onCreateClick = () => {
|
||||||
|
this.context?.(); // close overflow menu
|
||||||
const canSend = this.props.room.currentState.maySendEvent(
|
const canSend = this.props.room.currentState.maySendEvent(
|
||||||
M_POLL_START.name,
|
M_POLL_START.name,
|
||||||
MatrixClientPeg.get().getUserId(),
|
MatrixClientPeg.get().getUserId(),
|
||||||
|
@ -357,7 +350,6 @@ class PollButton extends React.PureComponent<IPollButtonProps> {
|
||||||
<CollapsibleButton
|
<CollapsibleButton
|
||||||
className="mx_MessageComposer_button mx_MessageComposer_poll"
|
className="mx_MessageComposer_button mx_MessageComposer_poll"
|
||||||
onClick={this.onCreateClick}
|
onClick={this.onCreateClick}
|
||||||
narrowMode={this.props.narrowMode}
|
|
||||||
title={_t("Create poll")}
|
title={_t("Create poll")}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -377,7 +369,6 @@ function showLocationButton(
|
||||||
roomId={roomId}
|
roomId={roomId}
|
||||||
sender={room.getMember(matrixClient.getUserId())}
|
sender={room.getMember(matrixClient.getUserId())}
|
||||||
menuPosition={props.menuPosition}
|
menuPosition={props.menuPosition}
|
||||||
narrowMode={props.narrowMode}
|
|
||||||
/>
|
/>
|
||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
|
@ -1696,9 +1696,9 @@
|
||||||
"Send voice message": "Send voice message",
|
"Send voice message": "Send voice message",
|
||||||
"Add emoji": "Add emoji",
|
"Add emoji": "Add emoji",
|
||||||
"Upload file": "Upload file",
|
"Upload file": "Upload file",
|
||||||
|
"Send a sticker": "Send a sticker",
|
||||||
"Hide Stickers": "Hide Stickers",
|
"Hide Stickers": "Hide Stickers",
|
||||||
"Show Stickers": "Show Stickers",
|
"Show Stickers": "Show Stickers",
|
||||||
"Send a sticker": "Send a sticker",
|
|
||||||
"You do not have permission to start polls in this room.": "You do not have permission to start polls in this room.",
|
"You do not have permission to start polls in this room.": "You do not have permission to start polls in this room.",
|
||||||
"Create poll": "Create poll",
|
"Create poll": "Create poll",
|
||||||
"Bold": "Bold",
|
"Bold": "Bold",
|
||||||
|
|
|
@ -77,6 +77,7 @@ describe("MessageComposerButtons", () => {
|
||||||
narrowMode={true}
|
narrowMode={true}
|
||||||
showLocationButton={true}
|
showLocationButton={true}
|
||||||
showStickersButton={true}
|
showStickersButton={true}
|
||||||
|
toggleButtonMenu={() => {}}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -159,28 +160,28 @@ function createRoomState(room: Room): IRoomState {
|
||||||
|
|
||||||
function buttonLabels(buttons: ReactWrapper): any[] {
|
function buttonLabels(buttons: ReactWrapper): any[] {
|
||||||
// Note: Depends on the fact that the mini buttons use aria-label
|
// Note: Depends on the fact that the mini buttons use aria-label
|
||||||
// and the labels under More options use label
|
// and the labels under More options use textContent
|
||||||
const mainButtons = (
|
const mainButtons = (
|
||||||
buttons
|
buttons
|
||||||
.find('div')
|
.find('div.mx_MessageComposer_button[aria-label]')
|
||||||
.map((button: ReactWrapper) => button.prop("aria-label"))
|
.map((button: ReactWrapper) => button.prop("aria-label") as string)
|
||||||
.filter(x => x)
|
.filter(x => x)
|
||||||
);
|
);
|
||||||
|
|
||||||
let extraButtons = (
|
const extraButtons = (
|
||||||
buttons
|
buttons
|
||||||
.find('div')
|
.find('.mx_MessageComposer_Menu div.mx_AccessibleButton[role="menuitem"]')
|
||||||
.map((button: ReactWrapper) => button.prop("label"))
|
.map((button: ReactWrapper) => button.text())
|
||||||
.filter(x => x)
|
.filter(x => x)
|
||||||
);
|
);
|
||||||
if (extraButtons.length === 0) {
|
|
||||||
extraButtons = [];
|
const list: any[] = [
|
||||||
} else {
|
...mainButtons,
|
||||||
extraButtons = [extraButtons];
|
];
|
||||||
|
|
||||||
|
if (extraButtons.length > 0) {
|
||||||
|
list.push(extraButtons);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return list;
|
||||||
...mainButtons,
|
|
||||||
...extraButtons,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue