Merge pull request #4875 from matrix-org/t3chguy/room-list/4

Add click-to-jump on badge in the room sublist header
This commit is contained in:
Michael Telatynski 2020-07-02 20:04:43 +01:00 committed by GitHub
commit 4a03b464d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 9 deletions

View file

@ -29,6 +29,8 @@ import { IDestroyable } from "../../../utils/IDestroyable";
import SettingsStore from "../../../settings/SettingsStore";
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
import { readReceiptChangeIsFor } from "../../../utils/read-receipts";
import AccessibleButton from "../elements/AccessibleButton";
import { XOR } from "../../../@types/common";
export const NOTIFICATION_STATE_UPDATE = "update";
@ -62,11 +64,18 @@ interface IProps {
roomId?: string;
}
interface IClickableProps extends IProps, React.InputHTMLAttributes<Element> {
/**
* If specified will return an AccessibleButton instead of a div.
*/
onClick?(ev: React.MouseEvent);
}
interface IState {
showCounts: boolean; // whether or not to show counts. Independent of props.forceCount
}
export default class NotificationBadge extends React.PureComponent<IProps, IState> {
export default class NotificationBadge extends React.PureComponent<XOR<IProps, IClickableProps>, IState> {
private countWatcherRef: string;
constructor(props: IProps) {
@ -109,20 +118,22 @@ export default class NotificationBadge extends React.PureComponent<IProps, IStat
};
public render(): React.ReactElement {
// Don't show a badge if we don't need to
if (this.props.notification.color <= NotificationColor.None) return null;
const {notification, forceCount, roomId, onClick, ...props} = this.props;
const hasNotif = this.props.notification.color >= NotificationColor.Red;
const hasCount = this.props.notification.color >= NotificationColor.Grey;
const hasUnread = this.props.notification.color >= NotificationColor.Bold;
// Don't show a badge if we don't need to
if (notification.color <= NotificationColor.None) return null;
const hasNotif = notification.color >= NotificationColor.Red;
const hasCount = notification.color >= NotificationColor.Grey;
const hasUnread = notification.color >= NotificationColor.Bold;
const couldBeEmpty = (!this.state.showCounts || hasUnread) && !hasNotif;
let isEmptyBadge = couldBeEmpty && (!this.state.showCounts || !hasCount);
if (this.props.forceCount) {
if (forceCount) {
isEmptyBadge = false;
if (!hasCount) return null; // Can't render a badge
}
let symbol = this.props.notification.symbol || formatMinimalBadgeCount(this.props.notification.count);
let symbol = notification.symbol || formatMinimalBadgeCount(notification.count);
if (isEmptyBadge) symbol = "";
const classes = classNames({
@ -134,6 +145,14 @@ export default class NotificationBadge extends React.PureComponent<IProps, IStat
'mx_NotificationBadge_3char': symbol.length > 2,
});
if (onClick) {
return (
<AccessibleButton {...props} className={classes} onClick={onClick}>
<span className="mx_NotificationBadge_count">{symbol}</span>
</AccessibleButton>
);
}
return (
<div className={classes}>
<span className="mx_NotificationBadge_count">{symbol}</span>

View file

@ -33,6 +33,7 @@ import StyledRadioButton from "../elements/StyledRadioButton";
import RoomListStore from "../../../stores/room-list/RoomListStore2";
import { ListAlgorithm, SortAlgorithm } from "../../../stores/room-list/algorithms/models";
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
import dis from "../../../dispatcher/dispatcher";
// 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
@ -175,6 +176,30 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
this.forceUpdate(); // because the layout doesn't trigger a re-render
};
private onBadgeClick = (ev: React.MouseEvent) => {
ev.preventDefault();
ev.stopPropagation();
let room;
if (this.props.tagId === DefaultTagID.Invite) {
// switch to first room as that'll be the top of the list for the user
room = this.props.rooms && this.props.rooms[0];
} else {
// find the first room with a count of the same colour as the badge count
room = this.props.rooms.find((r: Room) => {
const notifState = this.state.notificationState.getForRoom(r);
return notifState.count > 0 && notifState.color === this.state.notificationState.color;
});
}
if (room) {
dis.dispatch({
action: 'view_room',
room_id: room.roomId,
});
}
};
private onHeaderClick = (ev: React.MouseEvent<HTMLDivElement>) => {
let target = ev.target as HTMLDivElement;
if (!target.classList.contains('mx_RoomSublist2_headerText')) {
@ -312,7 +337,14 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
// TODO: Use onFocus: https://github.com/vector-im/riot-web/issues/14180
const tabIndex = isActive ? 0 : -1;
const badge = <NotificationBadge forceCount={true} notification={this.state.notificationState}/>;
const badge = (
<NotificationBadge
forceCount={true}
notification={this.state.notificationState}
onClick={this.onBadgeClick}
tabIndex={tabIndex}
/>
);
let addRoomButton = null;
if (!!this.props.onAddRoom) {