Merge branches 'develop' and 't3chguy/room-list/6' of github.com:matrix-org/matrix-react-sdk into t3chguy/room-list/6
Conflicts: src/components/views/rooms/RoomSublist2.tsx src/components/views/rooms/RoomTile2.tsx
This commit is contained in:
commit
9cf162e267
20 changed files with 118 additions and 92 deletions
|
@ -140,6 +140,13 @@ export class ContextMenu extends React.Component {
|
|||
e.stopPropagation();
|
||||
};
|
||||
|
||||
// Prevent clicks on the background from going through to the component which opened the menu.
|
||||
_onFinished = (ev: InputEvent) => {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
if (this.props.onFinished) this.props.onFinished();
|
||||
};
|
||||
|
||||
_onMoveFocus = (element, up) => {
|
||||
let descending = false; // are we currently descending or ascending through the DOM tree?
|
||||
|
||||
|
@ -326,7 +333,7 @@ export class ContextMenu extends React.Component {
|
|||
let background;
|
||||
if (hasBackground) {
|
||||
background = (
|
||||
<div className="mx_ContextualMenu_background" style={wrapperStyle} onClick={props.onFinished} onContextMenu={this.onContextMenu} />
|
||||
<div className="mx_ContextualMenu_background" style={wrapperStyle} onClick={this._onFinished} onContextMenu={this.onContextMenu} />
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import { OwnProfileStore } from "../../stores/OwnProfileStore";
|
|||
import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
||||
import BaseAvatar from '../views/avatars/BaseAvatar';
|
||||
import classNames from "classnames";
|
||||
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
|
||||
|
||||
interface IProps {
|
||||
isMinimized: boolean;
|
||||
|
@ -230,7 +231,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
{MatrixClientPeg.get().getUserId()}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
<AccessibleTooltipButton
|
||||
className="mx_UserMenu_contextMenu_themeButton"
|
||||
onClick={this.onSwitchThemeClick}
|
||||
title={this.state.isDarkTheme ? _t("Switch to light mode") : _t("Switch to dark mode")}
|
||||
|
@ -240,7 +241,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
alt={_t("Switch theme")}
|
||||
width={16}
|
||||
/>
|
||||
</div>
|
||||
</AccessibleTooltipButton>
|
||||
</div>
|
||||
{hostingLink}
|
||||
<div className="mx_IconizedContextMenu_optionList mx_IconizedContextMenu_optionList_notFirst">
|
||||
|
|
|
@ -27,7 +27,7 @@ export type ButtonEvent = React.MouseEvent<Element> | React.KeyboardEvent<Elemen
|
|||
* onClick: (required) Event handler for button activation. Should be
|
||||
* implemented exactly like a normal onClick handler.
|
||||
*/
|
||||
interface IProps extends React.InputHTMLAttributes<Element> {
|
||||
export interface IProps extends React.InputHTMLAttributes<Element> {
|
||||
inputRef?: React.Ref<Element>;
|
||||
element?: string;
|
||||
// The kind of button, similar to how Bootstrap works.
|
||||
|
|
|
@ -16,21 +16,28 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import AccessibleButton from "./AccessibleButton";
|
||||
import * as sdk from "../../../index";
|
||||
import {IProps} from "./AccessibleButton";
|
||||
import Tooltip from './Tooltip';
|
||||
|
||||
export default class AccessibleTooltipButton extends React.PureComponent {
|
||||
static propTypes = {
|
||||
...AccessibleButton.propTypes,
|
||||
// The tooltip to render on hover
|
||||
title: PropTypes.string.isRequired,
|
||||
};
|
||||
interface ITooltipProps extends IProps {
|
||||
title: string;
|
||||
tooltipClassName?: string;
|
||||
}
|
||||
|
||||
state = {
|
||||
hover: false,
|
||||
};
|
||||
interface IState {
|
||||
hover: boolean;
|
||||
}
|
||||
|
||||
export default class AccessibleTooltipButton extends React.PureComponent<ITooltipProps, IState> {
|
||||
constructor(props: ITooltipProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
hover: false,
|
||||
};
|
||||
}
|
||||
|
||||
onMouseOver = () => {
|
||||
this.setState({
|
||||
|
@ -45,14 +52,15 @@ export default class AccessibleTooltipButton extends React.PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const Tooltip = sdk.getComponent("elements.Tooltip");
|
||||
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
|
||||
|
||||
const {title, children, ...props} = this.props;
|
||||
const tooltipClassName = classnames(
|
||||
"mx_AccessibleTooltipButton_tooltip",
|
||||
this.props.tooltipClassName,
|
||||
);
|
||||
|
||||
const tip = this.state.hover ? <Tooltip
|
||||
className="mx_AccessibleTooltipButton_container"
|
||||
tooltipClassName="mx_AccessibleTooltipButton_tooltip"
|
||||
tooltipClassName={tooltipClassName}
|
||||
label={title}
|
||||
/> : <div />;
|
||||
return (
|
|
@ -26,6 +26,7 @@ import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
|||
import { CSSTransition } from "react-transition-group";
|
||||
import RoomListStore from "../../../stores/room-list/RoomListStore2";
|
||||
import { DefaultTagID } from "../../../stores/room-list/models";
|
||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||
|
||||
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
||||
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
|
||||
|
@ -98,11 +99,13 @@ export default class RoomBreadcrumbs2 extends React.PureComponent<IProps, IState
|
|||
const roomTags = RoomListStore.instance.getTagsForRoom(r);
|
||||
const roomTag = roomTags.includes(DefaultTagID.DM) ? DefaultTagID.DM : roomTags[0];
|
||||
return (
|
||||
<AccessibleButton
|
||||
<AccessibleTooltipButton
|
||||
className="mx_RoomBreadcrumbs2_crumb"
|
||||
key={r.roomId}
|
||||
onClick={() => this.viewRoom(r, i)}
|
||||
aria-label={_t("Room %(name)s", {name: r.name})}
|
||||
title={r.name}
|
||||
tooltipClassName={"mx_RoomBreadcrumbs2_Tooltip"}
|
||||
>
|
||||
<DecoratedRoomAvatar
|
||||
room={r}
|
||||
|
@ -111,7 +114,7 @@ export default class RoomBreadcrumbs2 extends React.PureComponent<IProps, IState
|
|||
displayBadge={true}
|
||||
forceCount={true}
|
||||
/>
|
||||
</AccessibleButton>
|
||||
</AccessibleTooltipButton>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -166,19 +166,26 @@ export default class RoomList2 extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
public componentDidMount(): void {
|
||||
RoomListStore.instance.on(LISTS_UPDATE_EVENT, (store: RoomListStore2) => {
|
||||
const newLists = store.orderedLists;
|
||||
console.log("new lists", newLists);
|
||||
|
||||
const layoutMap = new Map<TagID, ListLayout>();
|
||||
for (const tagId of Object.keys(newLists)) {
|
||||
layoutMap.set(tagId, new ListLayout(tagId));
|
||||
}
|
||||
|
||||
this.setState({sublists: newLists, layouts: layoutMap});
|
||||
});
|
||||
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.updateLists);
|
||||
this.updateLists(); // trigger the first update
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.updateLists);
|
||||
}
|
||||
|
||||
private updateLists = () => {
|
||||
const newLists = RoomListStore.instance.orderedLists;
|
||||
console.log("new lists", newLists);
|
||||
|
||||
const layoutMap = new Map<TagID, ListLayout>();
|
||||
for (const tagId of Object.keys(newLists)) {
|
||||
layoutMap.set(tagId, new ListLayout(tagId));
|
||||
}
|
||||
|
||||
this.setState({sublists: newLists, layouts: layoutMap});
|
||||
};
|
||||
|
||||
private renderCommunityInvites(): React.ReactElement[] {
|
||||
// TODO: Put community invites in a more sensible place (not in the room list)
|
||||
return MatrixClientPeg.get().getGroups().filter(g => {
|
||||
|
|
|
@ -35,6 +35,8 @@ import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
|||
import dis from "../../../dispatcher/dispatcher";
|
||||
import NotificationBadge from "./NotificationBadge";
|
||||
import { ListNotificationState } from "../../../stores/notifications/ListNotificationState";
|
||||
import Tooltip from "../elements/Tooltip";
|
||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||
import { Key } from "../../../Keyboard";
|
||||
|
||||
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
||||
|
@ -397,11 +399,13 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
|||
let addRoomButton = null;
|
||||
if (!!this.props.onAddRoom) {
|
||||
addRoomButton = (
|
||||
<AccessibleButton
|
||||
<AccessibleTooltipButton
|
||||
tabIndex={tabIndex}
|
||||
onClick={this.onAddRoom}
|
||||
className="mx_RoomSublist2_auxButton"
|
||||
aria-label={this.props.addRoomLabel || _t("Add room")}
|
||||
title={this.props.addRoomLabel}
|
||||
tooltipClassName={"mx_RoomSublist2_addRoomTooltip"}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { createRef } from "react";
|
||||
import React from "react";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import classNames from "classnames";
|
||||
import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
||||
|
@ -30,7 +30,6 @@ import { ContextMenu, ContextMenuButton, MenuItemRadio } from "../../structures/
|
|||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||
import { MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore";
|
||||
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
|
||||
import RoomTileIcon from "./RoomTileIcon";
|
||||
import { getRoomNotifsState, ALL_MESSAGES, ALL_MESSAGES_LOUD, MENTIONS_ONLY, MUTE } from "../../../RoomNotifs";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import { setRoomNotifsState } from "../../../RoomNotifs";
|
||||
|
@ -120,6 +119,10 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
|||
ActiveRoomObserver.addListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
||||
}
|
||||
|
||||
private get showContextMenu(): boolean {
|
||||
return !this.props.isMinimized && this.props.tag !== DefaultTagID.Invite;
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.props.room) {
|
||||
ActiveRoomObserver.removeListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
||||
|
@ -169,6 +172,9 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
|||
};
|
||||
|
||||
private onContextMenu = (ev: React.MouseEvent) => {
|
||||
// If we don't have a context menu to show, ignore the action.
|
||||
if (!this.showContextMenu) return;
|
||||
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.setState({
|
||||
|
@ -236,7 +242,7 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
|||
private onClickMute = ev => this.saveNotifState(ev, MUTE);
|
||||
|
||||
private renderNotificationsMenu(isActive: boolean): React.ReactElement {
|
||||
if (this.props.isMinimized || MatrixClientPeg.get().isGuest() || this.props.tag === DefaultTagID.Invite) {
|
||||
if (MatrixClientPeg.get().isGuest() || !this.showContextMenu) {
|
||||
// the menu makes no sense in these cases so do not show one
|
||||
return null;
|
||||
}
|
||||
|
@ -281,12 +287,14 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
|||
|
||||
const classes = classNames("mx_RoomTile2_notificationsButton", {
|
||||
// Show bell icon for the default case too.
|
||||
mx_RoomTile2_iconBell: state === ALL_MESSAGES_LOUD || state === ALL_MESSAGES,
|
||||
mx_RoomTile2_iconBellDot: state === MENTIONS_ONLY,
|
||||
mx_RoomTile2_iconBell: state === state === ALL_MESSAGES,
|
||||
mx_RoomTile2_iconBellDot: state === ALL_MESSAGES_LOUD,
|
||||
mx_RoomTile2_iconBellMentions: state === MENTIONS_ONLY,
|
||||
mx_RoomTile2_iconBellCrossed: state === MUTE,
|
||||
// XXX: RoomNotifs assumes ALL_MESSAGES is default, this is wrong,
|
||||
// but cannot be fixed until FTUE Notifications lands.
|
||||
mx_RoomTile2_notificationsButton_show: state !== ALL_MESSAGES,
|
||||
|
||||
// Only show the icon by default if the room is overridden to muted.
|
||||
// TODO: [FTUE Notifications] Probably need to detect global mute state
|
||||
mx_RoomTile2_notificationsButton_show: state === MUTE,
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -304,12 +312,9 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
private renderGeneralMenu(): React.ReactElement {
|
||||
if (this.props.isMinimized) return null; // no menu when minimized
|
||||
if (!this.showContextMenu) return null; // no menu to show
|
||||
|
||||
// TODO: Get a proper invite context menu, or take invites out of the room list.
|
||||
if (this.props.tag === DefaultTagID.Invite) {
|
||||
return null;
|
||||
}
|
||||
// TODO: We could do with a proper invite context menu, unlike what showContextMenu suggests
|
||||
|
||||
let contextMenu = null;
|
||||
if (this.state.generalMenuPosition) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue