Merge branch 'develop' into rav/base_dialog

pull/21833/head
Richard van der Hoff 2017-01-24 21:03:08 +00:00
commit 79e1108564
12 changed files with 119 additions and 45 deletions

View File

@ -26,6 +26,7 @@ var UserSettingsStore = require('../../UserSettingsStore');
var GeminiScrollbar = require('react-gemini-scrollbar');
var Email = require('../../email');
var AddThreepid = require('../../AddThreepid');
var AccessibleButton = require('../views/elements/AccessibleButton');
// if this looks like a release, use the 'version' from package.json; else use
// the git sha.
@ -531,9 +532,9 @@ module.exports = React.createClass({
return <div>
<h3>Deactivate Account</h3>
<div className="mx_UserSettings_section">
<button className="mx_UserSettings_button danger"
<AccessibleButton className="mx_UserSettings_button danger"
onClick={this._onDeactivateAccountClicked}>Deactivate my account
</button>
</AccessibleButton>
</div>
</div>;
},
@ -553,10 +554,10 @@ module.exports = React.createClass({
// bind() the invited rooms so any new invites that may come in as this button is clicked
// don't inadvertently get rejected as well.
reject = (
<button className="mx_UserSettings_button danger"
<AccessibleButton className="mx_UserSettings_button danger"
onClick={this._onRejectAllInvitesClicked.bind(this, invitedRooms)}>
Reject all {invitedRooms.length} invites
</button>
</AccessibleButton>
);
}
@ -724,9 +725,9 @@ module.exports = React.createClass({
<div className="mx_UserSettings_section">
<div className="mx_UserSettings_logout mx_UserSettings_button" onClick={this.onLogoutClicked}>
<AccessibleButton className="mx_UserSettings_logout mx_UserSettings_button" onClick={this.onLogoutClicked}>
Sign out
</div>
</AccessibleButton>
{accountJsx}
</div>

View File

@ -19,6 +19,7 @@ limitations under the License.
var React = require('react');
var AvatarLogic = require("../../../Avatar");
import sdk from '../../../index';
var AccessibleButton = require('../elements/AccessibleButton');
module.exports = React.createClass({
displayName: 'BaseAvatar',
@ -138,7 +139,7 @@ module.exports = React.createClass({
const {
name, idName, title, url, urls, width, height, resizeMethod,
defaultToInitialLetter,
defaultToInitialLetter, onClick,
...otherProps
} = this.props;
@ -156,12 +157,24 @@ module.exports = React.createClass({
</span>
);
}
return (
<img className="mx_BaseAvatar mx_BaseAvatar_image" src={imageUrl}
onError={this.onError}
width={width} height={height}
title={title} alt=""
{...otherProps} />
);
if (onClick != null) {
return (
<AccessibleButton className="mx_BaseAvatar" onClick={onClick}>
<img className="mx_BaseAvatar_image" src={imageUrl}
onError={this.onError}
width={width} height={height}
title={title} alt=""
{...otherProps} />
</AccessibleButton>
);
} else {
return (
<img className="mx_BaseAvatar mx_BaseAvatar_image" src={imageUrl}
onError={this.onError}
width={width} height={height}
title={title} alt=""
{...otherProps} />
);
}
}
});

View File

@ -24,6 +24,7 @@ var DMRoomMap = require('../../../utils/DMRoomMap');
var rate_limited_func = require("../../../ratelimitedfunc");
var dis = require("../../../dispatcher");
var Modal = require('../../../Modal');
var AccessibleButton = require('../elements/AccessibleButton');
const TRUNCATE_QUERY_LIST = 40;
@ -436,9 +437,9 @@ module.exports = React.createClass({
<div className="mx_Dialog_title">
{this.props.title}
</div>
<div className="mx_ChatInviteDialog_cancel" onClick={this.onCancel} >
<AccessibleButton className="mx_ChatInviteDialog_cancel" onClick={this.onCancel} >
<TintableSvg src="img/icons-close-button.svg" width="35" height="35" />
</div>
</AccessibleButton>
<div className="mx_ChatInviteDialog_label">
<label htmlFor="textinput">{ this.props.description }</label>
</div>

View File

@ -0,0 +1,50 @@
/*
Copyright 2016 Jani Mustonen
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
/**
* AccessibleButton is a generic wrapper for any element that should be treated as a button.
* Identifies the element as a button, setting proper tab indexing and keyboard activation behavior.
*/
export default function AccessibleButton(props) {
const {element, onClick, children, ...restProps} = props;
restProps.onClick = onClick;
restProps.onKeyDown = function(e) {
if (e.keyCode == 13 || e.keyCode == 32) return onClick();
};
restProps.tabIndex = restProps.tabIndex || "0";
restProps.role = "button";
return React.createElement(element, restProps, children);
}
/**
* children: React's magic prop. Represents all children given to the element.
* element: (optional) The base element type. "div" by default.
* onClick: (required) Event handler for button activation. Should be
* implemented exactly like a normal onClick handler.
*/
AccessibleButton.propTypes = {
children: React.PropTypes.node,
element: React.PropTypes.string,
onClick: React.PropTypes.func.isRequired,
};
AccessibleButton.defaultProps = {
element: 'div'
};
AccessibleButton.displayName = "AccessibleButton";

View File

@ -69,6 +69,7 @@ var TintableSvg = React.createClass({
width={ this.props.width }
height={ this.props.height }
onLoad={ this.onLoad }
tabIndex="-1"
/>
);
}

View File

@ -20,6 +20,7 @@ var React = require('react');
var MatrixClientPeg = require('../../../MatrixClientPeg');
var sdk = require('../../../index');
var AccessibleButton = require('../elements/AccessibleButton');
var PRESENCE_CLASS = {
@ -152,7 +153,7 @@ module.exports = React.createClass({
var av = this.props.avatarJsx || <BaseAvatar name={this.props.name} width={36} height={36} />;
return (
<div className={mainClassName} title={ this.props.title }
<AccessibleButton className={mainClassName} title={ this.props.title }
onClick={ this.props.onClick } onMouseEnter={ this.mouseEnter }
onMouseLeave={ this.mouseLeave }>
<div className="mx_EntityTile_avatar">
@ -161,7 +162,7 @@ module.exports = React.createClass({
</div>
{ nameEl }
{ inviteButton }
</div>
</AccessibleButton>
);
}
});

View File

@ -35,6 +35,7 @@ var DMRoomMap = require('../../../utils/DMRoomMap');
var Unread = require('../../../Unread');
var Receipt = require('../../../utils/Receipt');
var WithMatrixClient = require('../../../wrappers/WithMatrixClient');
var AccessibleButton = require('../elements/AccessibleButton');
module.exports = WithMatrixClient(React.createClass({
displayName: 'MemberInfo',
@ -612,7 +613,7 @@ module.exports = WithMatrixClient(React.createClass({
mx_MemberInfo_createRoom_label: true,
mx_RoomTile_name: true,
});
const startNewChat = <div
const startNewChat = <AccessibleButton
className="mx_MemberInfo_createRoom"
onClick={this.onNewDMClick}
>
@ -620,7 +621,7 @@ module.exports = WithMatrixClient(React.createClass({
<img src="img/create-big.svg" width="26" height="26" />
</div>
<div className={labelClasses}><i>Start new chat</i></div>
</div>;
</AccessibleButton>;
startChat = <div>
<h3>Direct chats</h3>
@ -635,26 +636,26 @@ module.exports = WithMatrixClient(React.createClass({
}
if (this.state.can.kick) {
kickButton = <div className="mx_MemberInfo_field" onClick={this.onKick}>
kickButton = <AccessibleButton className="mx_MemberInfo_field" onClick={this.onKick}>
{ this.props.member.membership === "invite" ? "Disinvite" : "Kick" }
</div>;
</AccessibleButton>;
}
if (this.state.can.ban) {
banButton = <div className="mx_MemberInfo_field" onClick={this.onBan}>
banButton = <AccessibleButton className="mx_MemberInfo_field" onClick={this.onBan}>
Ban
</div>;
</AccessibleButton>;
}
if (this.state.can.mute) {
var muteLabel = this.state.muted ? "Unmute" : "Mute";
muteButton = <div className="mx_MemberInfo_field" onClick={this.onMuteToggle}>
muteButton = <AccessibleButton className="mx_MemberInfo_field" onClick={this.onMuteToggle}>
{muteLabel}
</div>;
</AccessibleButton>;
}
if (this.state.can.toggleMod) {
var giveOpLabel = this.state.isTargetMod ? "Revoke Moderator" : "Make Moderator";
giveModButton = <div className="mx_MemberInfo_field" onClick={this.onModToggle}>
giveModButton = <AccessibleButton className="mx_MemberInfo_field" onClick={this.onModToggle}>
{giveOpLabel}
</div>;
</AccessibleButton>;
}
// TODO: we should have an invite button if this MemberInfo is showing a user who isn't actually in the current room yet
@ -682,7 +683,7 @@ module.exports = WithMatrixClient(React.createClass({
const EmojiText = sdk.getComponent('elements.EmojiText');
return (
<div className="mx_MemberInfo">
<img className="mx_MemberInfo_cancel" src="img/cancel.svg" width="18" height="18" onClick={this.onCancel}/>
<AccessibleButton className="mx_MemberInfo_cancel" onClick={this.onCancel}> <img src="img/cancel.svg" width="18" height="18"/></AccessibleButton>
<div className="mx_MemberInfo_avatar">
<MemberAvatar onClick={this.onMemberAvatarClick} member={this.props.member} width={48} height={48} />
</div>

View File

@ -192,9 +192,9 @@ module.exports = React.createClass({
width={14} height={14} resizeMethod="crop"
style={style}
title={title}
onClick={this.props.onClick}
/>
</Velociraptor>
);
/* onClick={this.props.onClick} */
},
});

View File

@ -26,6 +26,7 @@ var rate_limited_func = require('../../../ratelimitedfunc');
var linkify = require('linkifyjs');
var linkifyElement = require('linkifyjs/element');
var linkifyMatrix = require('../../../linkify-matrix');
var AccessibleButton = require('../elements/AccessibleButton');
linkifyMatrix(linkify);
@ -182,8 +183,8 @@ module.exports = React.createClass({
'm.room.name', user_id
);
save_button = <div className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>Save</div>;
cancel_button = <div className="mx_RoomHeader_cancelButton mx_filterFlipColor" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </div>;
save_button = <AccessibleButton className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>Save</AccessibleButton>;
cancel_button = <AccessibleButton className="mx_RoomHeader_cancelButton" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </AccessibleButton>;
}
if (this.props.saving) {
@ -275,9 +276,9 @@ module.exports = React.createClass({
var settings_button;
if (this.props.onSettingsClick) {
settings_button =
<div className="mx_RoomHeader_button" onClick={this.props.onSettingsClick} title="Settings">
<AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSettingsClick} title="Settings">
<TintableSvg src="img/icons-settings-room.svg" width="16" height="16"/>
</div>;
</AccessibleButton>;
}
// var leave_button;
@ -291,17 +292,17 @@ module.exports = React.createClass({
var forget_button;
if (this.props.onForgetClick) {
forget_button =
<div className="mx_RoomHeader_button" onClick={this.props.onForgetClick} title="Forget room">
<AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onForgetClick} title="Forget room">
<TintableSvg src="img/leave.svg" width="26" height="20"/>
</div>;
</AccessibleButton>;
}
var rightPanel_buttons;
if (this.props.collapsedRhs) {
rightPanel_buttons =
<div className="mx_RoomHeader_button" onClick={this.onShowRhsClick} title="<">
<AccessibleButton className="mx_RoomHeader_button" onClick={this.onShowRhsClick} title="<">
<TintableSvg src="img/minimise.svg" width="10" height="16"/>
</div>;
</AccessibleButton>;
}
var right_row;
@ -310,9 +311,9 @@ module.exports = React.createClass({
<div className="mx_RoomHeader_rightRow">
{ settings_button }
{ forget_button }
<div className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title="Search">
<AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title="Search">
<TintableSvg src="img/icons-search.svg" width="35" height="35"/>
</div>
</AccessibleButton>
{ rightPanel_buttons }
</div>;
}

View File

@ -26,6 +26,7 @@ var sdk = require('../../../index');
var ContextualMenu = require('../../structures/ContextualMenu');
var RoomNotifs = require('../../../RoomNotifs');
var FormattingUtils = require('../../../utils/FormattingUtils');
var AccessibleButton = require('../elements/AccessibleButton');
var UserSettingsStore = require('../../../UserSettingsStore');
module.exports = React.createClass({
@ -288,8 +289,10 @@ module.exports = React.createClass({
var connectDragSource = this.props.connectDragSource;
var connectDropTarget = this.props.connectDropTarget;
let ret = (
<div className={classes} onClick={this.onClick} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<div> { /* Only native elements can be wrapped in a DnD object. */}
<AccessibleButton className={classes} tabIndex="0" onClick={this.onClick} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<div className={avatarClasses}>
<div className="mx_RoomTile_avatar_menu" onClick={this.onAvatarClicked}>
<div className={avatarContainerClasses}>
@ -304,6 +307,7 @@ module.exports = React.createClass({
</div>
{/* { incomingCallBox } */}
{ tooltip }
</AccessibleButton>
</div>
);

View File

@ -19,6 +19,7 @@ limitations under the License.
var React = require('react');
var sdk = require('../../../index');
var dis = require("../../../dispatcher");
var AccessibleButton = require('../elements/AccessibleButton');
/*
* A stripped-down room header used for things like the user settings
@ -44,7 +45,7 @@ module.exports = React.createClass({
var cancelButton;
if (this.props.onCancelClick) {
cancelButton = <div className="mx_RoomHeader_cancelButton" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </div>;
cancelButton = <AccessibleButton className="mx_RoomHeader_cancelButton" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </AccessibleButton>;
}
var showRhsButton;
@ -70,4 +71,3 @@ module.exports = React.createClass({
);
},
});

View File

@ -19,6 +19,7 @@ limitations under the License.
var React = require('react');
var MatrixClientPeg = require("../../../MatrixClientPeg");
var sdk = require("../../../index");
var AccessibleButton = require('../elements/AccessibleButton');
module.exports = React.createClass({
displayName: 'ChangePassword',
@ -136,9 +137,9 @@ module.exports = React.createClass({
<input id="password2" type="password" ref="confirm_input" />
</div>
</div>
<div className={buttonClassName} onClick={this.onClickChange}>
<AccessibleButton className={buttonClassName} onClick={this.onClickChange}>
Change Password
</div>
</AccessibleButton>
</div>
);
case this.Phases.Uploading: