Fix handles

This commit is contained in:
Jorik Schellekens 2020-07-16 16:21:38 +01:00
commit 173ccbcec9
70 changed files with 713 additions and 180 deletions

View file

@ -233,6 +233,9 @@ export class ContextMenu extends React.PureComponent<IProps, IState> {
switch (ev.key) {
case Key.TAB:
case Key.ESCAPE:
// close on left and right arrows too for when it is a context menu on a <Toolbar />
case Key.ARROW_LEFT:
case Key.ARROW_RIGHT:
this.props.onFinished();
break;
case Key.ARROW_UP:

View file

@ -38,7 +38,7 @@ const HomePage = () => {
}
const brandingConfig = config.branding;
let logoUrl = "themes/riot/img/logos/riot-logo.svg";
let logoUrl = "themes/element/img/logos/element-logo.svg";
if (brandingConfig && brandingConfig.authHeaderLogoUrl) {
logoUrl = brandingConfig.authHeaderLogoUrl;
}
@ -46,7 +46,7 @@ const HomePage = () => {
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
return <AutoHideScrollbar className="mx_HomePage mx_HomePage_default">
<div className="mx_HomePage_default_wrapper">
<img src={logoUrl} alt="Riot" />
<img src={logoUrl} alt={config.brand || "Riot"} />
<h1>{ _t("Welcome to %(appName)s", { appName: config.brand || "Riot" }) }</h1>
<h4>{ _t("Liberate your communication") }</h4>
<div className="mx_HomePage_default_buttons">

View file

@ -269,7 +269,7 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
const firstRoom = this.listContainerRef.current.querySelector<HTMLDivElement>(".mx_RoomTile2");
if (firstRoom) {
firstRoom.click();
this.onSearch(""); // clear the search field
return true; // to get the field to clear
}
};

View file

@ -675,12 +675,16 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
case 'hide_left_panel':
this.setState({
collapseLhs: true,
}, () => {
this.state.resizeNotifier.notifyLeftHandleResized();
});
break;
case 'focus_room_filter': // for CtrlOrCmd+K to work by expanding the left panel first
case 'show_left_panel':
this.setState({
collapseLhs: false,
}, () => {
this.state.resizeNotifier.notifyLeftHandleResized();
});
break;
case 'panel_disable': {

View file

@ -28,8 +28,8 @@ import { Action } from "../../dispatcher/actions";
interface IProps {
onQueryUpdate: (newQuery: string) => void;
isMinimized: boolean;
onVerticalArrow(ev: React.KeyboardEvent);
onEnter(ev: React.KeyboardEvent);
onVerticalArrow(ev: React.KeyboardEvent): void;
onEnter(ev: React.KeyboardEvent): boolean;
}
interface IState {
@ -107,7 +107,13 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
} else if (ev.key === Key.ARROW_UP || ev.key === Key.ARROW_DOWN) {
this.props.onVerticalArrow(ev);
} else if (ev.key === Key.ENTER) {
this.props.onEnter(ev);
const shouldClear = this.props.onEnter(ev);
if (shouldClear) {
// wrap in set immediate to delay it so that we don't clear the filter & then change room
setImmediate(() => {
this.clearInput();
});
}
}
};

View file

@ -66,7 +66,7 @@ export default class DecoratedRoomAvatar extends React.PureComponent<IProps, ISt
oobData={this.props.oobData}
viewAvatarOnClick={this.props.viewAvatarOnClick}
/>
<RoomTileIcon room={this.props.room} tag={this.props.tag} />
<RoomTileIcon room={this.props.room} />
{badge}
</div>;
}

View file

@ -20,7 +20,6 @@ import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
import dis from '../../../dispatcher/dispatcher';
import TagOrderActions from '../../../actions/TagOrderActions';
import * as sdk from '../../../index';
import {MenuItem} from "../../structures/ContextMenu";
import MatrixClientContext from "../../../contexts/MatrixClientContext";

View file

@ -23,26 +23,26 @@ import DialogButtons from '../elements/DialogButtons';
export enum RebrandDialogKind {
NAG,
ONE_TIME,
};
}
interface IProps {
onFinished: (bool) => void;
kind: RebrandDialogKind,
targetUrl?: string,
kind: RebrandDialogKind;
targetUrl?: string;
}
export default class RebrandDialog extends React.PureComponent<IProps> {
private onDoneClick = () => {
this.props.onFinished(true);
}
};
private onGoToElementClick = () => {
this.props.onFinished(true);
}
};
private onRemindMeLaterClick = () => {
this.props.onFinished(false);
}
};
private getPrettyTargetUrl() {
const u = new URL(this.props.targetUrl);
@ -79,14 +79,14 @@ export default class RebrandDialog extends React.PureComponent<IProps> {
cancelButton={"Remind me later"}
onCancel={this.onRemindMeLaterClick}
focus={true}
/>
/>;
} else {
return <DialogButtons primaryButton={_t("Done")}
primaryButtonClass='primary'
hasCancel={false}
onPrimaryButtonClick={this.onDoneClick}
focus={true}
/>
/>;
}
}

View file

@ -16,7 +16,7 @@ limitations under the License.
*/
import React from 'react';
import classnames from 'classnames';
import classNames from 'classnames';
import AccessibleButton from "./AccessibleButton";
import {IProps} from "./AccessibleButton";
@ -24,6 +24,7 @@ import Tooltip from './Tooltip';
interface ITooltipProps extends IProps {
title: string;
tooltip?: React.ReactNode;
tooltipClassName?: string;
}
@ -52,16 +53,12 @@ export default class AccessibleTooltipButton extends React.PureComponent<IToolti
};
render() {
const {title, children, ...props} = this.props;
const tooltipClassName = classnames(
"mx_AccessibleTooltipButton_tooltip",
this.props.tooltipClassName,
);
const {title, tooltip, children, tooltipClassName, ...props} = this.props;
const tip = this.state.hover ? <Tooltip
className="mx_AccessibleTooltipButton_container"
tooltipClassName={tooltipClassName}
label={title}
tooltipClassName={classNames("mx_AccessibleTooltipButton_tooltip", tooltipClassName)}
label={tooltip || title}
/> : <div />;
return (
<AccessibleButton {...props} onMouseOver={this.onMouseOver} onMouseOut={this.onMouseOut} aria-label={title}>

View file

@ -25,9 +25,12 @@ import dis from '../../../dispatcher/dispatcher';
import {aboveLeftOf, ContextMenu, ContextMenuButton, useContextMenu} from '../../structures/ContextMenu';
import { isContentActionable, canEditContent } from '../../../utils/EventUtils';
import RoomContext from "../../../contexts/RoomContext";
import Toolbar from "../../../accessibility/Toolbar";
import {RovingAccessibleButton, useRovingTabIndex} from "../../../accessibility/RovingTabIndex";
const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange}) => {
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
const [onFocus, isActive, ref] = useRovingTabIndex(button);
useEffect(() => {
onFocusChange(menuDisplayed);
}, [onFocusChange, menuDisplayed]);
@ -57,7 +60,9 @@ const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFo
label={_t("Options")}
onClick={openMenu}
isExpanded={menuDisplayed}
inputRef={button}
inputRef={ref}
onFocus={onFocus}
tabIndex={isActive ? 0 : -1}
/>
{ contextMenu }
@ -66,6 +71,7 @@ const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFo
const ReactButton = ({mxEvent, reactions, onFocusChange}) => {
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
const [onFocus, isActive, ref] = useRovingTabIndex(button);
useEffect(() => {
onFocusChange(menuDisplayed);
}, [onFocusChange, menuDisplayed]);
@ -85,7 +91,9 @@ const ReactButton = ({mxEvent, reactions, onFocusChange}) => {
label={_t("React")}
onClick={openMenu}
isExpanded={menuDisplayed}
inputRef={button}
inputRef={ref}
onFocus={onFocus}
tabIndex={isActive ? 0 : -1}
/>
{ contextMenu }
@ -148,8 +156,6 @@ export default class MessageActionBar extends React.PureComponent {
};
render() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
let reactButton;
let replyButton;
let editButton;
@ -161,7 +167,7 @@ export default class MessageActionBar extends React.PureComponent {
);
}
if (this.context.canReply) {
replyButton = <AccessibleButton
replyButton = <RovingAccessibleButton
className="mx_MessageActionBar_maskButton mx_MessageActionBar_replyButton"
title={_t("Reply")}
onClick={this.onReplyClick}
@ -169,7 +175,7 @@ export default class MessageActionBar extends React.PureComponent {
}
}
if (canEditContent(this.props.mxEvent)) {
editButton = <AccessibleButton
editButton = <RovingAccessibleButton
className="mx_MessageActionBar_maskButton mx_MessageActionBar_editButton"
title={_t("Edit")}
onClick={this.onEditClick}
@ -177,7 +183,7 @@ export default class MessageActionBar extends React.PureComponent {
}
// aria-live=off to not have this read out automatically as navigating around timeline, gets repetitive.
return <div className="mx_MessageActionBar" role="toolbar" aria-label={_t("Message Actions")} aria-live="off">
return <Toolbar className="mx_MessageActionBar" aria-label={_t("Message Actions")} aria-live="off">
{reactButton}
{replyButton}
{editButton}
@ -188,6 +194,6 @@ export default class MessageActionBar extends React.PureComponent {
permalinkCreator={this.props.permalinkCreator}
onFocusChange={this.onFocusChange}
/>
</div>;
</Toolbar>;
}
}

View file

@ -55,7 +55,7 @@ export default class ReactionsRowButtonTooltip extends React.PureComponent {
},
{
reactors: () => {
return <div className="mx_ReactionsRowButtonTooltip_senders">
return <div className="mx_Tooltip_title">
{formatCommaSeparatedList(senders, 6)}
</div>;
},
@ -63,7 +63,7 @@ export default class ReactionsRowButtonTooltip extends React.PureComponent {
if (!shortName) {
return null;
}
return <div className="mx_ReactionsRowButtonTooltip_reactedWith">
return <div className="mx_Tooltip_sub">
{sub}
</div>;
},

View file

@ -376,11 +376,21 @@ export default createReactClass({
const date = this.props.mxEvent.replacingEventDate();
const dateString = date && formatDate(date);
const tooltip = <div>
<div className="mx_Tooltip_title">
{_t("Edited at %(date)s", {date: dateString})}
</div>
<div className="mx_Tooltip_sub">
{_t("Click to view edits")}
</div>
</div>;
return (
<AccessibleTooltipButton
className="mx_EventTile_edited"
onClick={this._openHistoryDialog}
title={_t("Edited at %(date)s. Click to view edits.", {date: dateString})}
tooltip={tooltip}
tooltipClassName="mx_Tooltip_timeline"
>
<span>{`(${_t("edited")})`}</span>

View file

@ -333,7 +333,7 @@ export default createReactClass({
return;
}
const eventSenderTrust = this.context.checkDeviceTrust(
const eventSenderTrust = encryptionInfo.sender && this.context.checkDeviceTrust(
senderId, encryptionInfo.sender.deviceId,
);
if (!eventSenderTrust) {

View file

@ -25,7 +25,8 @@ 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";
import { RovingAccessibleTooltipButton } from "../../../accessibility/RovingTabIndex";
import Toolbar from "../../../accessibility/Toolbar";
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
@ -86,7 +87,7 @@ 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 (
<AccessibleTooltipButton
<RovingAccessibleTooltipButton
className="mx_RoomBreadcrumbs2_crumb"
key={r.roomId}
onClick={() => this.viewRoom(r, i)}
@ -101,7 +102,7 @@ export default class RoomBreadcrumbs2 extends React.PureComponent<IProps, IState
displayBadge={true}
forceCount={true}
/>
</AccessibleTooltipButton>
</RovingAccessibleTooltipButton>
);
});
@ -112,9 +113,9 @@ export default class RoomBreadcrumbs2 extends React.PureComponent<IProps, IState
appear={true} in={this.state.doAnimation} timeout={640}
classNames='mx_RoomBreadcrumbs2'
>
<div className='mx_RoomBreadcrumbs2'>
<Toolbar className='mx_RoomBreadcrumbs2'>
{tiles.slice(this.state.skipFirst ? 1 : 0)}
</div>
</Toolbar>
</CSSTransition>
);
} else {

View file

@ -31,7 +31,6 @@ import ManageIntegsButton from '../elements/ManageIntegsButton';
import {CancelButton} from './SimpleRoomHeader';
import SettingsStore from "../../../settings/SettingsStore";
import RoomHeaderButtons from '../right_panel/RoomHeaderButtons';
import DMRoomMap from '../../../utils/DMRoomMap';
import E2EIcon from './E2EIcon';
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
import {DefaultTagID} from "../../../stores/room-list/models";
@ -158,10 +157,6 @@ export default createReactClass({
let settingsButton = null;
let pinnedEventsButton = null;
const dmUserId = DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId);
const joinRules = this.props.room && this.props.room.currentState.getStateEvents("m.room.join_rules", "");
const joinRule = joinRules && joinRules.getContent().join_rule;
if (this.props.onCancelClick) {
cancelButton = <CancelButton onClick={this.props.onCancelClick} />;
}

View file

@ -444,24 +444,20 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
<React.Fragment>
<hr />
<div>
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Unread rooms")}</div>
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Appearance")}</div>
<StyledMenuItemCheckbox
onClose={this.onCloseMenu}
onChange={this.onUnreadFirstChanged}
checked={isUnreadFirst}
>
{_t("Always show first")}
{_t("Show rooms with unread messages first")}
</StyledMenuItemCheckbox>
</div>
<hr />
<div>
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Show")}</div>
<StyledMenuItemCheckbox
onClose={this.onCloseMenu}
onChange={this.onMessagePreviewChanged}
checked={this.layout.showPreviews}
>
{_t("Message preview")}
{_t("Show previews of messages")}
</StyledMenuItemCheckbox>
</div>
</React.Fragment>

View file

@ -22,6 +22,8 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import DMRoomMap from "../../../utils/DMRoomMap";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { isPresenceEnabled } from "../../../utils/presence";
import { _t } from "../../../languageHandler";
import TextWithTooltip from "../elements/TextWithTooltip";
enum Icon {
// Note: the names here are used in CSS class names
@ -32,9 +34,21 @@ enum Icon {
PresenceOffline = "OFFLINE",
}
function tooltipText(variant: Icon) {
switch (variant) {
case Icon.Globe:
return _t("This room is public");
case Icon.PresenceOnline:
return _t("Online");
case Icon.PresenceAway:
return _t("Away");
case Icon.PresenceOffline:
return _t("Offline");
}
}
interface IProps {
room: Room;
tag: TagID;
}
interface IState {
@ -122,10 +136,11 @@ export default class RoomTileIcon extends React.Component<IProps, IState> {
private calculateIcon(): Icon {
let icon = Icon.None;
if (this.props.tag === DefaultTagID.DM && this.props.room.getJoinedMemberCount() === 2) {
// We look at the DMRoomMap and not the tag here so that we don't exclude DMs in Favourites
const otherUserId = DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId);
if (otherUserId && this.props.room.getJoinedMemberCount() === 2) {
// Track presence, if available
if (isPresenceEnabled()) {
const otherUserId = DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId);
if (otherUserId) {
this.dmUser = MatrixClientPeg.get().getUser(otherUserId);
icon = this.getPresenceIcon();
@ -145,6 +160,10 @@ export default class RoomTileIcon extends React.Component<IProps, IState> {
public render(): React.ReactElement {
if (this.state.icon === Icon.None) return null;
return <span className={`mx_RoomTileIcon mx_RoomTileIcon_${this.state.icon.toLowerCase()}`} />;
return <TextWithTooltip
tooltip={tooltipText(this.state.icon)}
tooltipClass="mx_Tooltip_timeline"
class={`mx_RoomTileIcon mx_RoomTileIcon_${this.state.icon.toLowerCase()}`}
/>;
}
}

View file

@ -120,7 +120,7 @@ export default class HelpUserSettingsTab extends React.Component {
<span className='mx_SettingsTab_subheading'>{_t("Credits")}</span>
<ul>
<li>
The <a href="themes/riot/img/backgrounds/lake.jpg" rel="noreferrer noopener" target="_blank">
The <a href="themes/element/img/backgrounds/lake.jpg" rel="noreferrer noopener" target="_blank">
default cover photo</a> is ©&nbsp;
<a href="https://www.flickr.com/golan" rel="noreferrer noopener" target="_blank">Jesús Roncero</a>{' '}
used under the terms of&nbsp;
@ -158,7 +158,7 @@ export default class HelpUserSettingsTab extends React.Component {
},
{
'a': (sub) => <a
href="https://about.riot.im/need-help/"
href="https://element.io/help"
rel="noreferrer noopener"
target="_blank"
>
@ -177,7 +177,7 @@ export default class HelpUserSettingsTab extends React.Component {
},
{
'a': (sub) => <a
href="https://about.riot.im/need-help/"
href="https://element.io/help"
rel='noreferrer noopener'
target='_blank'
>