Move status context menu to its own component

This fixes a lot of the state bugs such as buttons not updating, etc. 

This commit also adds the border around the avatar to indicate a status is set.
This commit is contained in:
Travis Ralston 2018-12-12 22:26:39 -07:00
parent 99f5b9e39b
commit b0b7932f5f
5 changed files with 143 additions and 91 deletions

View file

@ -27,6 +27,7 @@
@import "./views/avatars/_MemberStatusMessageAvatar.scss";
@import "./views/context_menus/_MessageContextMenu.scss";
@import "./views/context_menus/_RoomTileContextMenu.scss";
@import "./views/context_menus/_StatusMessageContextMenu.scss";
@import "./views/context_menus/_TagTileContextMenu.scss";
@import "./views/dialogs/_BugReportDialog.scss";
@import "./views/dialogs/_ChangelogDialog.scss";

View file

@ -14,38 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_MemberStatusMessageAvatar_contextMenu_message {
display: inline-block;
border-radius: 3px 0 0 3px;
border: 1px solid $input-border-color;
font-size: 13px;
padding: 7px 7px 7px 9px;
width: 135px;
background-color: $primary-bg-color !important;
}
.mx_MemberStatusMessageAvatar_contextMenu_submit {
display: inline-block;
}
.mx_MemberStatusMessageAvatar_contextMenu_submit img {
vertical-align: middle;
margin-left: 8px;
}
.mx_MemberStatusMessageAvatar_contextMenu hr {
border: 0.5px solid $menu-border-color;
}
.mx_MemberStatusMessageAvatar_contextMenu_clearIcon {
margin: 5px 15px 5px 5px;
vertical-align: middle;
}
.mx_MemberStatusMessageAvatar_contextMenu_clear {
padding: 2px;
}
.mx_MemberStatusMessageAvatar_contextMenu_hasStatus .mx_MemberStatusMessageAvatar_contextMenu_clear {
color: $warning-color;
.mx_MemberStatusMessageAvatar_hasStatus {
border: 2px solid $accent-color;
border-radius: 40px;
}

View file

@ -0,0 +1,51 @@
/*
Copyright 2018 New Vector Ltd
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.
*/
.mx_StatusMessageContextMenu_message {
display: inline-block;
border-radius: 3px 0 0 3px;
border: 1px solid $input-border-color;
font-size: 13px;
padding: 7px 7px 7px 9px;
width: 135px;
background-color: $primary-bg-color !important;
}
.mx_StatusMessageContextMenu_submit {
display: inline-block;
}
.mx_StatusMessageContextMenu_submit img {
vertical-align: middle;
margin-left: 8px;
}
.mx_StatusMessageContextMenu hr {
border: 0.5px solid $menu-border-color;
}
.mx_StatusMessageContextMenu_clearIcon {
margin: 5px 15px 5px 5px;
vertical-align: middle;
}
.mx_StatusMessageContextMenu_clear {
padding: 2px;
}
.mx_StatusMessageContextMenu_hasStatus .mx_StatusMessageContextMenu_clear {
color: $warning-color;
}

View file

@ -16,22 +16,18 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
import MatrixClientPeg from '../../../MatrixClientPeg';
import AccessibleButton from '../elements/AccessibleButton';
import MemberAvatar from '../avatars/MemberAvatar';
import classNames from 'classnames';
import * as ContextualMenu from "../../structures/ContextualMenu";
import GenericElementContextMenu from "../context_menus/GenericElementContextMenu";
import StatusMessageContextMenu from "../context_menus/StatusMessageContextMenu";
export default class MemberStatusMessageAvatar extends React.Component {
constructor(props, context) {
super(props, context);
this._onRoomStateEvents = this._onRoomStateEvents.bind(this);
this._onClick = this._onClick.bind(this);
this._onClearClick = this._onClearClick.bind(this);
this._onSubmit = this._onSubmit.bind(this);
this._onStatusChange = this._onStatusChange.bind(this);
}
componentWillMount() {
@ -75,64 +71,16 @@ export default class MemberStatusMessageAvatar extends React.Component {
let y = elementRect.top + (elementRect.height / 2) + window.pageYOffset;
y = y - (chevronOffset + 4); // where 4 is 1/4 the height of the chevron
const contextMenu = this._renderContextMenu();
ContextualMenu.createMenu(GenericElementContextMenu, {
ContextualMenu.createMenu(StatusMessageContextMenu, {
chevronOffset: chevronOffset,
chevronFace: 'bottom',
left: x,
top: y,
menuWidth: 190,
element: contextMenu,
user: this.props.member.user,
});
}
async _onClearClick(e) {
await MatrixClientPeg.get().setStatusMessage("");
this.setState({message: ""});
}
_onSubmit(e) {
e.preventDefault();
MatrixClientPeg.get().setStatusMessage(this.state.message);
}
_onStatusChange(e) {
this.setState({message: e.target.value});
}
_renderContextMenu() {
const form = <form className="mx_MemberStatusMessageAvatar_contextMenu_form" onSubmit={this._onSubmit}>
<input type="text" key="message" placeholder={_t("Set a new status...")}
className="mx_MemberStatusMessageAvatar_contextMenu_message"
defaultValue={this.state.message} onChange={this._onStatusChange} maxLength="60"
/>
<AccessibleButton onClick={this._onSubmit} element="div" className="mx_MemberStatusMessageAvatar_contextMenu_submit">
<img src="img/icons-checkmark.svg" width="22" height="22" />
</AccessibleButton>
</form>;
const clearIcon = this.state.message ? "img/cancel-red.svg" : "img/cancel.svg";
const clearButton = <AccessibleButton onClick={this._onClearClick} disabled={!this.state.message}
className="mx_MemberStatusMessageAvatar_contextMenu_clear">
<img src={clearIcon} alt={_t('Clear status')} width="12" height="12"
className="mx_filterFlipColor mx_MemberStatusMessageAvatar_contextMenu_clearIcon"
/>
<span>{_t("Clear status")}</span>
</AccessibleButton>;
const menuClasses = classNames({
"mx_MemberStatusMessageAvatar_contextMenu": true,
"mx_MemberStatusMessageAvatar_contextMenu_hasStatus": this.state.message,
});
return <div className={menuClasses}>
{ form }
<hr />
{ clearButton }
</div>;
}
render() {
const hasStatus = this.props.member.user ? !!this.props.member.user.statusMessage : false;
@ -145,8 +93,7 @@ export default class MemberStatusMessageAvatar extends React.Component {
<MemberAvatar member={this.props.member}
width={this.props.width}
height={this.props.height}
resizeMethod={this.props.resizeMethod}
/>
resizeMethod={this.props.resizeMethod} />
</AccessibleButton>;
}
}

View file

@ -0,0 +1,84 @@
/*
Copyright 2018 New Vector Ltd
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';
import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
import MatrixClientPeg from '../../../MatrixClientPeg';
import AccessibleButton from '../elements/AccessibleButton';
import classNames from 'classnames';
export default class StatusMessageContextMenu extends React.Component {
constructor(props, context) {
super(props, context);
this._onClearClick = this._onClearClick.bind(this);
this._onSubmit = this._onSubmit.bind(this);
this._onStatusChange = this._onStatusChange.bind(this);
this.state = {
message: props.user ? props.user.statusMessage : "",
};
}
async _onClearClick(e) {
await MatrixClientPeg.get().setStatusMessage("");
this.setState({message: ""});
}
_onSubmit(e) {
e.preventDefault();
MatrixClientPeg.get().setStatusMessage(this.state.message);
}
_onStatusChange(e) {
this.setState({message: e.target.value});
}
render() {
const form = <form className="mx_StatusMessageContextMenu_form" onSubmit={this._onSubmit}>
<input type="text" key="message" placeholder={_t("Set a new status...")} autoFocus={true}
className="mx_StatusMessageContextMenu_message"
value={this.state.message} onChange={this._onStatusChange} maxLength="60" />
<AccessibleButton onClick={this._onSubmit} element="div" className="mx_StatusMessageContextMenu_submit">
<img src="img/icons-checkmark.svg" width="22" height="22" />
</AccessibleButton>
</form>;
const clearIcon = this.state.message ? "img/cancel-red.svg" : "img/cancel.svg";
const clearButton = <AccessibleButton onClick={this._onClearClick} disabled={!this.state.message}
className="mx_StatusMessageContextMenu_clear">
<img src={clearIcon} alt={_t('Clear status')} width="12" height="12"
className="mx_filterFlipColor mx_StatusMessageContextMenu_clearIcon" />
<span>{_t("Clear status")}</span>
</AccessibleButton>;
const menuClasses = classNames({
"mx_StatusMessageContextMenu": true,
"mx_StatusMessageContextMenu_hasStatus": this.state.message,
});
return <div className={menuClasses}>
{ form }
<hr />
{ clearButton }
</div>;
}
}
StatusMessageContextMenu.propTypes = {
// js-sdk User object. Not required because it might not exist.
user: PropTypes.object,
};