move room/group panel header buttons into room/group header
This commit is contained in:
parent
4972b1ba7c
commit
e80a1c5051
8 changed files with 379 additions and 242 deletions
|
@ -20,7 +20,6 @@ limitations under the License.
|
||||||
border-bottom: 1px solid $primary-hairline-color;
|
border-bottom: 1px solid $primary-hairline-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* add 20px to the height of the header when editing */
|
/* add 20px to the height of the header when editing */
|
||||||
.mx_RoomHeader_editing {
|
.mx_RoomHeader_editing {
|
||||||
flex: 0 0 93px ! important;
|
flex: 0 0 93px ! important;
|
||||||
|
|
|
@ -24,6 +24,7 @@ import dis from '../../dispatcher';
|
||||||
import { sanitizedHtmlNode } from '../../HtmlUtils';
|
import { sanitizedHtmlNode } from '../../HtmlUtils';
|
||||||
import { _t, _td } from '../../languageHandler';
|
import { _t, _td } from '../../languageHandler';
|
||||||
import AccessibleButton from '../views/elements/AccessibleButton';
|
import AccessibleButton from '../views/elements/AccessibleButton';
|
||||||
|
import GroupHeaderButtons from '../views/right_panel/GroupHeaderButtons';
|
||||||
import Modal from '../../Modal';
|
import Modal from '../../Modal';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
@ -1305,6 +1306,7 @@ export default React.createClass({
|
||||||
<div className="mx_GroupView_header_rightCol">
|
<div className="mx_GroupView_header_rightCol">
|
||||||
{ rightButtons }
|
{ rightButtons }
|
||||||
</div>
|
</div>
|
||||||
|
<GroupHeaderButtons />
|
||||||
</div>
|
</div>
|
||||||
<GeminiScrollbarWrapper className="mx_GroupView_body">
|
<GeminiScrollbarWrapper className="mx_GroupView_body">
|
||||||
{ this._getMembershipSection() }
|
{ this._getMembershipSection() }
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
Copyright 2017 Vector Creations Ltd
|
Copyright 2017 Vector Creations Ltd
|
||||||
Copyright 2017 New Vector Ltd
|
Copyright 2017 New Vector Ltd
|
||||||
|
Copyright 2018 New Vector Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -23,79 +24,27 @@ import { _t } from '../../languageHandler';
|
||||||
import sdk from '../../index';
|
import sdk from '../../index';
|
||||||
import dis from '../../dispatcher';
|
import dis from '../../dispatcher';
|
||||||
import { MatrixClient } from 'matrix-js-sdk';
|
import { MatrixClient } from 'matrix-js-sdk';
|
||||||
import Analytics from '../../Analytics';
|
|
||||||
import RateLimitedFunc from '../../ratelimitedfunc';
|
import RateLimitedFunc from '../../ratelimitedfunc';
|
||||||
import AccessibleButton from '../../components/views/elements/AccessibleButton';
|
import AccessibleButton from '../../components/views/elements/AccessibleButton';
|
||||||
import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddressPicker';
|
import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddressPicker';
|
||||||
import GroupStore from '../../stores/GroupStore';
|
import GroupStore from '../../stores/GroupStore';
|
||||||
|
|
||||||
class HeaderButton extends React.Component {
|
export default class RightPanel extends React.Component {
|
||||||
constructor() {
|
|
||||||
super();
|
static get propTypes() {
|
||||||
this.onClick = this.onClick.bind(this);
|
return {
|
||||||
|
roomId: React.PropTypes.string, // if showing panels for a given room, this is set
|
||||||
|
groupId: React.PropTypes.string, // if showing panels for a given group, this is set
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick(ev) {
|
static get contextTypes() {
|
||||||
Analytics.trackEvent(...this.props.analytics);
|
return {
|
||||||
dis.dispatch({
|
matrixClient: PropTypes.instanceOf(MatrixClient),
|
||||||
action: 'view_right_panel_phase',
|
};
|
||||||
phase: this.props.clickPhase,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
static Phase = Object.freeze({
|
||||||
const TintableSvg = sdk.getComponent("elements.TintableSvg");
|
|
||||||
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
|
|
||||||
|
|
||||||
const classes = classNames({
|
|
||||||
mx_RightPanel_headerButton: true,
|
|
||||||
mx_RightPanel_headerButton_highlight: this.props.isHighlighted,
|
|
||||||
});
|
|
||||||
|
|
||||||
return <AccessibleButton
|
|
||||||
aria-label={this.props.title}
|
|
||||||
aria-expanded={this.props.isHighlighted}
|
|
||||||
title={this.props.title}
|
|
||||||
className={classes}
|
|
||||||
onClick={this.onClick} >
|
|
||||||
<TintableSvg src={this.props.iconSrc} width="20" height="20" />
|
|
||||||
</AccessibleButton>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HeaderButton.propTypes = {
|
|
||||||
// Whether this button is highlighted
|
|
||||||
isHighlighted: PropTypes.bool.isRequired,
|
|
||||||
// The phase to swap to when the button is clicked
|
|
||||||
clickPhase: PropTypes.string.isRequired,
|
|
||||||
// The source file of the icon to display
|
|
||||||
iconSrc: PropTypes.string.isRequired,
|
|
||||||
|
|
||||||
// The badge to display above the icon
|
|
||||||
badge: PropTypes.node,
|
|
||||||
// The parameters to track the click event
|
|
||||||
analytics: PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
||||||
|
|
||||||
// Button title
|
|
||||||
title: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'RightPanel',
|
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
// TODO: We're trying to move away from these being props, but we need to know
|
|
||||||
// whether we should be displaying a room or group member list
|
|
||||||
roomId: React.PropTypes.string, // if showing panels for a given room, this is set
|
|
||||||
groupId: React.PropTypes.string, // if showing panels for a given group, this is set
|
|
||||||
collapsed: React.PropTypes.bool, // currently unused property to request for a minimized view of the panel
|
|
||||||
},
|
|
||||||
|
|
||||||
contextTypes: {
|
|
||||||
matrixClient: PropTypes.instanceOf(MatrixClient),
|
|
||||||
},
|
|
||||||
|
|
||||||
Phase: {
|
|
||||||
RoomMemberList: 'RoomMemberList',
|
RoomMemberList: 'RoomMemberList',
|
||||||
GroupMemberList: 'GroupMemberList',
|
GroupMemberList: 'GroupMemberList',
|
||||||
GroupRoomList: 'GroupRoomList',
|
GroupRoomList: 'GroupRoomList',
|
||||||
|
@ -104,147 +53,100 @@ module.exports = React.createClass({
|
||||||
NotificationPanel: 'NotificationPanel',
|
NotificationPanel: 'NotificationPanel',
|
||||||
RoomMemberInfo: 'RoomMemberInfo',
|
RoomMemberInfo: 'RoomMemberInfo',
|
||||||
GroupMemberInfo: 'GroupMemberInfo',
|
GroupMemberInfo: 'GroupMemberInfo',
|
||||||
},
|
});
|
||||||
|
|
||||||
componentWillMount: function() {
|
constructor(props, context) {
|
||||||
|
super(props, context);
|
||||||
|
this.state = {
|
||||||
|
phase: this.props.groupId ? RightPanel.Phase.GroupMemberList : RightPanel.Phase.RoomMemberList,
|
||||||
|
isUserPrivilegedInGroup: null,
|
||||||
|
};
|
||||||
|
this.onAction = this.onAction.bind(this);
|
||||||
|
this.onRoomStateMember = this.onRoomStateMember.bind(this);
|
||||||
|
this.onGroupStoreUpdated = this.onGroupStoreUpdated.bind(this);
|
||||||
|
this.onInviteToGroupButtonClick = this.onInviteToGroupButtonClick.bind(this);
|
||||||
|
this.onAddRoomToGroupButtonClick = this.onAddRoomToGroupButtonClick.bind(this);
|
||||||
|
|
||||||
|
this._delayedUpdate = new RateLimitedFunc(() => {
|
||||||
|
this.forceUpdate();
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
const cli = this.context.matrixClient;
|
const cli = this.context.matrixClient;
|
||||||
cli.on("RoomState.members", this.onRoomStateMember);
|
cli.on("RoomState.members", this.onRoomStateMember);
|
||||||
this._initGroupStore(this.props.groupId);
|
this._initGroupStore(this.props.groupId);
|
||||||
},
|
}
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount() {
|
||||||
dis.unregister(this.dispatcherRef);
|
dis.unregister(this.dispatcherRef);
|
||||||
if (this.context.matrixClient) {
|
if (this.context.matrixClient) {
|
||||||
this.context.matrixClient.removeListener("RoomState.members", this.onRoomStateMember);
|
this.context.matrixClient.removeListener("RoomState.members", this.onRoomStateMember);
|
||||||
}
|
}
|
||||||
this._unregisterGroupStore(this.props.groupId);
|
this._unregisterGroupStore(this.props.groupId);
|
||||||
},
|
}
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
phase: this.props.groupId ? this.Phase.GroupMemberList : this.Phase.RoomMemberList,
|
|
||||||
isUserPrivilegedInGroup: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillReceiveProps(newProps) {
|
componentWillReceiveProps(newProps) {
|
||||||
if (newProps.groupId !== this.props.groupId) {
|
if (newProps.groupId !== this.props.groupId) {
|
||||||
this._unregisterGroupStore(this.props.groupId);
|
this._unregisterGroupStore(this.props.groupId);
|
||||||
this._initGroupStore(newProps.groupId);
|
this._initGroupStore(newProps.groupId);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
_initGroupStore(groupId) {
|
_initGroupStore(groupId) {
|
||||||
if (!groupId) return;
|
if (!groupId) return;
|
||||||
GroupStore.registerListener(groupId, this.onGroupStoreUpdated);
|
GroupStore.registerListener(groupId, this.onGroupStoreUpdated);
|
||||||
},
|
}
|
||||||
|
|
||||||
_unregisterGroupStore() {
|
_unregisterGroupStore() {
|
||||||
GroupStore.unregisterListener(this.onGroupStoreUpdated);
|
GroupStore.unregisterListener(this.onGroupStoreUpdated);
|
||||||
},
|
}
|
||||||
|
|
||||||
onGroupStoreUpdated: function() {
|
onGroupStoreUpdated() {
|
||||||
this.setState({
|
this.setState({
|
||||||
isUserPrivilegedInGroup: GroupStore.isUserPrivileged(this.props.groupId),
|
isUserPrivilegedInGroup: GroupStore.isUserPrivileged(this.props.groupId),
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
onCollapseClick: function() {
|
onInviteToGroupButtonClick() {
|
||||||
dis.dispatch({
|
|
||||||
action: 'hide_right_panel',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onInviteToGroupButtonClick: function() {
|
|
||||||
showGroupInviteDialog(this.props.groupId).then(() => {
|
showGroupInviteDialog(this.props.groupId).then(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
phase: this.Phase.GroupMemberList,
|
phase: RightPanel.Phase.GroupMemberList,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
onAddRoomToGroupButtonClick: function() {
|
onAddRoomToGroupButtonClick() {
|
||||||
showGroupAddRoomDialog(this.props.groupId).then(() => {
|
showGroupAddRoomDialog(this.props.groupId).then(() => {
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
onRoomStateMember: function(ev, state, member) {
|
onRoomStateMember(ev, state, member) {
|
||||||
if (member.roomId !== this.props.roomId) {
|
if (member.roomId !== this.props.roomId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// redraw the badge on the membership list
|
// redraw the badge on the membership list
|
||||||
if (this.state.phase === this.Phase.RoomMemberList && member.roomId === this.props.roomId) {
|
if (this.state.phase === RightPanel.Phase.RoomMemberList && member.roomId === this.props.roomId) {
|
||||||
this._delayedUpdate();
|
this._delayedUpdate();
|
||||||
} else if (this.state.phase === this.Phase.RoomMemberInfo && member.roomId === this.props.roomId &&
|
} else if (this.state.phase === RightPanel.Phase.RoomMemberInfo && member.roomId === this.props.roomId &&
|
||||||
member.userId === this.state.member.userId) {
|
member.userId === this.state.member.userId) {
|
||||||
// refresh the member info (e.g. new power level)
|
// refresh the member info (e.g. new power level)
|
||||||
this._delayedUpdate();
|
this._delayedUpdate();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
_delayedUpdate: new RateLimitedFunc(function() {
|
onAction(payload) {
|
||||||
this.forceUpdate(); // eslint-disable-line babel/no-invalid-this
|
if (payload.action === "view_right_panel_phase") {
|
||||||
}, 500),
|
|
||||||
|
|
||||||
onAction: function(payload) {
|
|
||||||
if (payload.action === "view_user") {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'show_right_panel',
|
|
||||||
});
|
|
||||||
if (payload.member) {
|
|
||||||
this.setState({
|
|
||||||
phase: this.Phase.RoomMemberInfo,
|
|
||||||
member: payload.member,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (this.props.roomId) {
|
|
||||||
this.setState({
|
|
||||||
phase: this.Phase.RoomMemberList,
|
|
||||||
});
|
|
||||||
} else if (this.props.groupId) {
|
|
||||||
this.setState({
|
|
||||||
phase: this.Phase.GroupMemberList,
|
|
||||||
member: payload.member,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (payload.action === "view_group") {
|
|
||||||
this.setState({
|
|
||||||
phase: this.Phase.GroupMemberList,
|
|
||||||
member: null,
|
|
||||||
});
|
|
||||||
} else if (payload.action === "view_group_room") {
|
|
||||||
this.setState({
|
|
||||||
phase: this.Phase.GroupRoomInfo,
|
|
||||||
groupRoomId: payload.groupRoomId,
|
|
||||||
});
|
|
||||||
} else if (payload.action === "view_group_room_list") {
|
|
||||||
this.setState({
|
|
||||||
phase: this.Phase.GroupRoomList,
|
|
||||||
});
|
|
||||||
} else if (payload.action === "view_group_member_list") {
|
|
||||||
this.setState({
|
|
||||||
phase: this.Phase.GroupMemberList,
|
|
||||||
});
|
|
||||||
} else if (payload.action === "view_group_user") {
|
|
||||||
this.setState({
|
|
||||||
phase: this.Phase.GroupMemberInfo,
|
|
||||||
member: payload.member,
|
|
||||||
});
|
|
||||||
} else if (payload.action === "view_room") {
|
|
||||||
this.setState({
|
|
||||||
phase: this.Phase.RoomMemberList,
|
|
||||||
});
|
|
||||||
} else if (payload.action === "view_right_panel_phase") {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
phase: payload.phase,
|
phase: payload.phase,
|
||||||
|
member: payload.member,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
render: function() {
|
render() {
|
||||||
const MemberList = sdk.getComponent('rooms.MemberList');
|
const MemberList = sdk.getComponent('rooms.MemberList');
|
||||||
const MemberInfo = sdk.getComponent('rooms.MemberInfo');
|
const MemberInfo = sdk.getComponent('rooms.MemberInfo');
|
||||||
const NotificationPanel = sdk.getComponent('structures.NotificationPanel');
|
const NotificationPanel = sdk.getComponent('structures.NotificationPanel');
|
||||||
|
@ -257,96 +159,40 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
const TintableSvg = sdk.getComponent("elements.TintableSvg");
|
const TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
let inviteGroup;
|
let inviteGroup;
|
||||||
|
|
||||||
let membersBadge;
|
|
||||||
const membersTitle = _t('Members');
|
|
||||||
|
|
||||||
const isPhaseGroup = [
|
const isPhaseGroup = [
|
||||||
this.Phase.GroupMemberInfo,
|
RightPanel.Phase.GroupMemberInfo,
|
||||||
this.Phase.GroupMemberList,
|
RightPanel.Phase.GroupMemberList,
|
||||||
].includes(this.state.phase);
|
].includes(this.state.phase);
|
||||||
|
|
||||||
let headerButtons = [];
|
|
||||||
if (this.props.roomId) {
|
|
||||||
headerButtons = [
|
|
||||||
<HeaderButton key="_membersButton" title={membersTitle} iconSrc="img/icons-people.svg"
|
|
||||||
isHighlighted={[this.Phase.RoomMemberList, this.Phase.RoomMemberInfo].includes(this.state.phase)}
|
|
||||||
clickPhase={this.Phase.RoomMemberList}
|
|
||||||
badge={membersBadge}
|
|
||||||
analytics={['Right Panel', 'Member List Button', 'click']}
|
|
||||||
/>,
|
|
||||||
<HeaderButton key="_filesButton" title={_t('Files')} iconSrc="img/icons-files.svg"
|
|
||||||
isHighlighted={this.state.phase === this.Phase.FilePanel}
|
|
||||||
clickPhase={this.Phase.FilePanel}
|
|
||||||
analytics={['Right Panel', 'File List Button', 'click']}
|
|
||||||
/>,
|
|
||||||
<HeaderButton key="_notifsButton" title={_t('Notifications')} iconSrc="img/icons-notifications.svg"
|
|
||||||
isHighlighted={this.state.phase === this.Phase.NotificationPanel}
|
|
||||||
clickPhase={this.Phase.NotificationPanel}
|
|
||||||
analytics={['Right Panel', 'Notification List Button', 'click']}
|
|
||||||
/>,
|
|
||||||
];
|
|
||||||
} else if (this.props.groupId) {
|
|
||||||
headerButtons = [
|
|
||||||
<HeaderButton key="_groupMembersButton" title={_t('Members')} iconSrc="img/icons-people.svg"
|
|
||||||
isHighlighted={isPhaseGroup}
|
|
||||||
clickPhase={this.Phase.GroupMemberList}
|
|
||||||
analytics={['Right Panel', 'Group Member List Button', 'click']}
|
|
||||||
/>,
|
|
||||||
<HeaderButton key="_roomsButton" title={_t('Rooms')} iconSrc="img/icons-room.svg"
|
|
||||||
isHighlighted={[this.Phase.GroupRoomList, this.Phase.GroupRoomInfo].includes(this.state.phase)}
|
|
||||||
clickPhase={this.Phase.GroupRoomList}
|
|
||||||
analytics={['Right Panel', 'Group Room List Button', 'click']}
|
|
||||||
/>,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.props.roomId || this.props.groupId) {
|
|
||||||
// Hiding the right panel hides it completely and relies on an 'expand' button
|
|
||||||
// being put in the RoomHeader or GroupView header, so only show the minimise
|
|
||||||
// button on these 2 screens or you won't be able to re-expand the panel.
|
|
||||||
headerButtons.push(
|
|
||||||
<AccessibleButton className="mx_RightPanel_headerButton mx_RightPanel_collapsebutton" key="_minimizeButton"
|
|
||||||
title={_t("Hide panel")} aria-label={_t("Hide panel")} onClick={this.onCollapseClick}
|
|
||||||
>
|
|
||||||
<TintableSvg src="img/minimise.svg" width="10" height="16" alt="" />
|
|
||||||
</AccessibleButton>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let panel = <div />;
|
let panel = <div />;
|
||||||
if (!this.props.collapsed) {
|
|
||||||
if (this.props.roomId && this.state.phase === this.Phase.RoomMemberList) {
|
if (this.props.roomId && this.state.phase === RightPanel.Phase.RoomMemberList) {
|
||||||
panel = <MemberList roomId={this.props.roomId} key={this.props.roomId} />;
|
panel = <MemberList roomId={this.props.roomId} key={this.props.roomId} />;
|
||||||
} else if (this.props.groupId && this.state.phase === this.Phase.GroupMemberList) {
|
} else if (this.props.groupId && this.state.phase === RightPanel.Phase.GroupMemberList) {
|
||||||
panel = <GroupMemberList groupId={this.props.groupId} key={this.props.groupId} />;
|
panel = <GroupMemberList groupId={this.props.groupId} key={this.props.groupId} />;
|
||||||
} else if (this.state.phase === this.Phase.GroupRoomList) {
|
} else if (this.state.phase === RightPanel.Phase.GroupRoomList) {
|
||||||
panel = <GroupRoomList groupId={this.props.groupId} key={this.props.groupId} />;
|
panel = <GroupRoomList groupId={this.props.groupId} key={this.props.groupId} />;
|
||||||
} else if (this.state.phase === this.Phase.RoomMemberInfo) {
|
} else if (this.state.phase === RightPanel.Phase.RoomMemberInfo) {
|
||||||
panel = <MemberInfo member={this.state.member} key={this.props.roomId || this.state.member.userId} />;
|
panel = <MemberInfo member={this.state.member} key={this.props.roomId || this.state.member.userId} />;
|
||||||
} else if (this.state.phase === this.Phase.GroupMemberInfo) {
|
} else if (this.state.phase === RightPanel.Phase.GroupMemberInfo) {
|
||||||
panel = <GroupMemberInfo
|
panel = <GroupMemberInfo
|
||||||
groupMember={this.state.member}
|
groupMember={this.state.member}
|
||||||
groupId={this.props.groupId}
|
groupId={this.props.groupId}
|
||||||
key={this.state.member.user_id} />;
|
key={this.state.member.user_id} />;
|
||||||
} else if (this.state.phase === this.Phase.GroupRoomInfo) {
|
} else if (this.state.phase === RightPanel.Phase.GroupRoomInfo) {
|
||||||
panel = <GroupRoomInfo
|
panel = <GroupRoomInfo
|
||||||
groupRoomId={this.state.groupRoomId}
|
groupRoomId={this.state.groupRoomId}
|
||||||
groupId={this.props.groupId}
|
groupId={this.props.groupId}
|
||||||
key={this.state.groupRoomId} />;
|
key={this.state.groupRoomId} />;
|
||||||
} else if (this.state.phase === this.Phase.NotificationPanel) {
|
} else if (this.state.phase === RightPanel.Phase.NotificationPanel) {
|
||||||
panel = <NotificationPanel />;
|
panel = <NotificationPanel />;
|
||||||
} else if (this.state.phase === this.Phase.FilePanel) {
|
} else if (this.state.phase === RightPanel.Phase.FilePanel) {
|
||||||
panel = <FilePanel roomId={this.props.roomId} />;
|
panel = <FilePanel roomId={this.props.roomId} />;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!panel) {
|
|
||||||
panel = <div className="mx_RightPanel_blank" />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: either include this in the DOM again, or move it to other component
|
||||||
if (this.props.groupId && this.state.isUserPrivilegedInGroup) {
|
if (this.props.groupId && this.state.isUserPrivilegedInGroup) {
|
||||||
inviteGroup = isPhaseGroup ? (
|
inviteGroup = isPhaseGroup ? (
|
||||||
<AccessibleButton className="mx_RightPanel_invite" onClick={this.onInviteToGroupButtonClick}>
|
<AccessibleButton className="mx_RightPanel_invite" onClick={this.onInviteToGroupButtonClick}>
|
||||||
|
@ -372,13 +218,8 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className={classes}>
|
<aside className={classes}>
|
||||||
<div className="mx_RightPanel_header">
|
|
||||||
<div className="mx_RightPanel_headerButtonGroup">
|
|
||||||
{ headerButtons }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{ panel }
|
{ panel }
|
||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
|
81
src/components/views/right_panel/GroupHeaderButtons.js
Normal file
81
src/components/views/right_panel/GroupHeaderButtons.js
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
Copyright 2017 New Vector Ltd
|
||||||
|
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 { _t } from '../../../languageHandler';
|
||||||
|
import dis from '../../../dispatcher';
|
||||||
|
import HeaderButton from './HeaderButton';
|
||||||
|
import HeaderButtons from './HeaderButtons';
|
||||||
|
import RightPanel from '../../structures/RightPanel';
|
||||||
|
|
||||||
|
export default class GroupHeaderButtons extends HeaderButtons {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props, RightPanel.Phase.GroupMemberList);
|
||||||
|
}
|
||||||
|
|
||||||
|
onAction(payload) {
|
||||||
|
super.onAction(payload);
|
||||||
|
|
||||||
|
if (payload.action === "view_user") {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'show_right_panel',
|
||||||
|
});
|
||||||
|
if (payload.member) {
|
||||||
|
this.setPhase(RightPanel.Phase.RoomMemberInfo, {member: payload.member});
|
||||||
|
} else {
|
||||||
|
this.setPhase(RightPanel.Phase.GroupMemberList);
|
||||||
|
}
|
||||||
|
} else if (payload.action === "view_group") {
|
||||||
|
this.setPhase(RightPanel.Phase.GroupMemberList);
|
||||||
|
} else if (payload.action === "view_group_room") {
|
||||||
|
this.setPhase(RightPanel.Phase.GroupRoomInfo, {groupRoomId: payload.groupRoomId});
|
||||||
|
} else if (payload.action === "view_group_room_list") {
|
||||||
|
this.setPhase(RightPanel.Phase.GroupRoomList);
|
||||||
|
} else if (payload.action === "view_group_member_list") {
|
||||||
|
this.setPhase(RightPanel.Phase.GroupMemberList);
|
||||||
|
} else if (payload.action === "view_group_user") {
|
||||||
|
this.setPhase(RightPanel.Phase.GroupMemberInfo, {member: payload.member});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderButtons() {
|
||||||
|
const isPhaseGroup = [
|
||||||
|
RightPanel.Phase.GroupMemberInfo,
|
||||||
|
RightPanel.Phase.GroupMemberList,
|
||||||
|
].includes(this.state.phase);
|
||||||
|
const isPhaseRoom = [
|
||||||
|
RightPanel.Phase.GroupRoomList,
|
||||||
|
RightPanel.Phase.GroupRoomInfo,
|
||||||
|
].includes(this.state.phase);
|
||||||
|
|
||||||
|
return [
|
||||||
|
<HeaderButton key="_groupMembersButton" title={_t('Members')} iconSrc="img/icons-people.svg"
|
||||||
|
isHighlighted={isPhaseGroup}
|
||||||
|
clickPhase={RightPanel.Phase.GroupMemberList}
|
||||||
|
analytics={['Right Panel', 'Group Member List Button', 'click']}
|
||||||
|
/>,
|
||||||
|
<HeaderButton key="_roomsButton" title={_t('Rooms')} iconSrc="img/icons-room.svg"
|
||||||
|
isHighlighted={isPhaseRoom}
|
||||||
|
clickPhase={RightPanel.Phase.GroupRoomList}
|
||||||
|
analytics={['Right Panel', 'Group Room List Button', 'click']}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
74
src/components/views/right_panel/HeaderButton.js
Normal file
74
src/components/views/right_panel/HeaderButton.js
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
Copyright 2017 New Vector Ltd
|
||||||
|
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 classNames from 'classnames';
|
||||||
|
import dis from '../../../dispatcher';
|
||||||
|
import Analytics from '../../../Analytics';
|
||||||
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
|
import TintableSvg from '../elements/TintableSvg';
|
||||||
|
|
||||||
|
export default class HeaderButton extends React.Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.onClick = this.onClick.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick(ev) {
|
||||||
|
Analytics.trackEvent(...this.props.analytics);
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'view_right_panel_phase',
|
||||||
|
phase: this.props.clickPhase,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const classes = classNames({
|
||||||
|
mx_RightPanel_headerButton: true,
|
||||||
|
mx_RightPanel_headerButton_highlight: this.props.isHighlighted,
|
||||||
|
});
|
||||||
|
|
||||||
|
return <AccessibleButton
|
||||||
|
aria-label={this.props.title}
|
||||||
|
aria-expanded={this.props.isHighlighted}
|
||||||
|
title={this.props.title}
|
||||||
|
className={classes}
|
||||||
|
onClick={this.onClick} >
|
||||||
|
<TintableSvg src={this.props.iconSrc} width="20" height="20" />
|
||||||
|
</AccessibleButton>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeaderButton.propTypes = {
|
||||||
|
// Whether this button is highlighted
|
||||||
|
isHighlighted: PropTypes.bool.isRequired,
|
||||||
|
// The phase to swap to when the button is clicked
|
||||||
|
clickPhase: PropTypes.string.isRequired,
|
||||||
|
// The source file of the icon to display
|
||||||
|
iconSrc: PropTypes.string.isRequired,
|
||||||
|
|
||||||
|
// The badge to display above the icon
|
||||||
|
badge: PropTypes.node,
|
||||||
|
// The parameters to track the click event
|
||||||
|
analytics: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||||
|
|
||||||
|
// Button title
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
};
|
65
src/components/views/right_panel/HeaderButtons.js
Normal file
65
src/components/views/right_panel/HeaderButtons.js
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
Copyright 2017 New Vector Ltd
|
||||||
|
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 dis from '../../../dispatcher';
|
||||||
|
|
||||||
|
export default class HeaderButtons extends React.Component {
|
||||||
|
|
||||||
|
constructor(props, initialPhase) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
phase: initialPhase,
|
||||||
|
isUserPrivilegedInGroup: null,
|
||||||
|
};
|
||||||
|
this.onAction = this.onAction.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
dis.unregister(this.dispatcherRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPhase(phase, extras) {
|
||||||
|
// TODO: delay?
|
||||||
|
dis.dispatch(Object.assign({
|
||||||
|
action: 'view_right_panel_phase',
|
||||||
|
phase: phase,
|
||||||
|
}, extras));
|
||||||
|
}
|
||||||
|
|
||||||
|
onAction(payload) {
|
||||||
|
if (payload.action === "view_right_panel_phase") {
|
||||||
|
this.setState({
|
||||||
|
phase: payload.phase,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
// inline style as this will be swapped around in future commits
|
||||||
|
return <div style={{display: 'flex'}}>
|
||||||
|
{ this.renderButtons() }
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
}
|
73
src/components/views/right_panel/RoomHeaderButtons.js
Normal file
73
src/components/views/right_panel/RoomHeaderButtons.js
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
Copyright 2017 New Vector Ltd
|
||||||
|
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 { _t } from '../../../languageHandler';
|
||||||
|
import dis from '../../../dispatcher';
|
||||||
|
import HeaderButton from './HeaderButton';
|
||||||
|
import HeaderButtons from './HeaderButtons';
|
||||||
|
import RightPanel from '../../structures/RightPanel';
|
||||||
|
|
||||||
|
export default class RoomHeaderButtons extends HeaderButtons {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props, RightPanel.Phase.RoomMemberList);
|
||||||
|
}
|
||||||
|
|
||||||
|
onAction(payload) {
|
||||||
|
super.onAction(payload);
|
||||||
|
if (payload.action === "view_user") {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'show_right_panel',
|
||||||
|
});
|
||||||
|
if (payload.member) {
|
||||||
|
this.setPhase(RightPanel.Phase.RoomMemberInfo, {member: payload.member});
|
||||||
|
} else {
|
||||||
|
this.setPhase(RightPanel.Phase.RoomMemberList);
|
||||||
|
}
|
||||||
|
} else if (payload.action === "view_room") {
|
||||||
|
this.setPhase(RightPanel.Phase.RoomMemberList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderButtons() {
|
||||||
|
const isMembersPhase = [
|
||||||
|
RightPanel.Phase.RoomMemberList,
|
||||||
|
RightPanel.Phase.RoomMemberInfo,
|
||||||
|
].includes(this.state.phase);
|
||||||
|
|
||||||
|
return [
|
||||||
|
<HeaderButton key="_membersButton" title={_t('Members')} iconSrc="img/icons-people.svg"
|
||||||
|
isHighlighted={isMembersPhase}
|
||||||
|
clickPhase={RightPanel.Phase.RoomMemberList}
|
||||||
|
analytics={['Right Panel', 'Member List Button', 'click']}
|
||||||
|
/>,
|
||||||
|
<HeaderButton key="_filesButton" title={_t('Files')} iconSrc="img/icons-files.svg"
|
||||||
|
isHighlighted={this.state.phase === RightPanel.Phase.FilePanel}
|
||||||
|
clickPhase={RightPanel.Phase.FilePanel}
|
||||||
|
analytics={['Right Panel', 'File List Button', 'click']}
|
||||||
|
/>,
|
||||||
|
<HeaderButton key="_notifsButton" title={_t('Notifications')} iconSrc="img/icons-notifications.svg"
|
||||||
|
isHighlighted={this.state.phase === RightPanel.Phase.NotificationPanel}
|
||||||
|
clickPhase={RightPanel.Phase.NotificationPanel}
|
||||||
|
analytics={['Right Panel', 'Notification List Button', 'click']}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,6 +33,7 @@ import AccessibleButton from '../elements/AccessibleButton';
|
||||||
import ManageIntegsButton from '../elements/ManageIntegsButton';
|
import ManageIntegsButton from '../elements/ManageIntegsButton';
|
||||||
import {CancelButton} from './SimpleRoomHeader';
|
import {CancelButton} from './SimpleRoomHeader';
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
import RoomHeaderButtons from '../right_panel/RoomHeaderButtons';
|
||||||
|
|
||||||
linkifyMatrix(linkify);
|
linkifyMatrix(linkify);
|
||||||
|
|
||||||
|
@ -432,6 +433,7 @@ module.exports = React.createClass({
|
||||||
{ saveButton }
|
{ saveButton }
|
||||||
{ cancelButton }
|
{ cancelButton }
|
||||||
{ rightRow }
|
{ rightRow }
|
||||||
|
<RoomHeaderButtons />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue