Merge pull request #2260 from matrix-org/bwindels/rightpanelbelowheader
Redesign: move right panel below room/group headerpull/21833/head
commit
9546df609e
|
@ -15,10 +15,6 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.mx_GroupView {
|
.mx_GroupView {
|
||||||
max-width: 960px;
|
|
||||||
width: 100%;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -29,7 +25,6 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_GroupView_header {
|
.mx_GroupView_header {
|
||||||
max-width: 960px;
|
|
||||||
min-height: 70px;
|
min-height: 70px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -162,6 +157,11 @@ limitations under the License.
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_GroupView > .mx_MainSplit {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_GroupView_body {
|
.mx_GroupView_body {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,8 @@ limitations under the License.
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MatrixChat .mx_MatrixChat_middlePanel {
|
/* not the left panel, and not the resize handle, so the roomview/groupview/... */
|
||||||
|
.mx_MatrixChat > :not(.mx_LeftPanel_container):not(.mx_ResizeHandle) {
|
||||||
background-color: $primary-bg-color;
|
background-color: $primary-bg-color;
|
||||||
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
@ -81,8 +82,6 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
/* To fix https://github.com/vector-im/riot-web/issues/3298 where Safari
|
/* To fix https://github.com/vector-im/riot-web/issues/3298 where Safari
|
||||||
needed height 100% all the way down to the HomePage. Height does not
|
needed height 100% all the way down to the HomePage. Height does not
|
||||||
have to be auto, empirically.
|
have to be auto, empirically.
|
||||||
|
|
|
@ -16,20 +16,10 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_RoomView {
|
.mx_RoomView {
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
position: relative;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomView .mx_RoomHeader {
|
|
||||||
order: 1;
|
|
||||||
|
|
||||||
flex: 0 0 52px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomView_fileDropTarget {
|
.mx_RoomView_fileDropTarget {
|
||||||
min-width: 0px;
|
min-width: 0px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -62,15 +52,11 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomView_auxPanel {
|
.mx_RoomView_auxPanel {
|
||||||
order: 2;
|
|
||||||
|
|
||||||
min-width: 0px;
|
min-width: 0px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0px auto;
|
margin: 0px auto;
|
||||||
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
border-bottom: 1px solid $primary-hairline-color;
|
|
||||||
|
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,13 +65,17 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.mx_RoomView_body {
|
.mx_RoomView .mx_MainSplit {
|
||||||
order: 3;
|
|
||||||
flex: 1 1 0;
|
flex: 1 1 0;
|
||||||
flex-direction: column;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_RoomView_body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_RoomView_body .mx_RoomView_topUnreadMessagesBar {
|
.mx_RoomView_body .mx_RoomView_topUnreadMessagesBar {
|
||||||
order: 1;
|
order: 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MemberList .mx_Spinner {
|
.mx_MemberList .mx_Spinner {
|
||||||
flex: 0 0 auto;
|
flex: 1 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MemberList_chevron {
|
.mx_MemberList_chevron {
|
||||||
|
|
|
@ -14,6 +14,11 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.mx_RoomHeader {
|
||||||
|
flex: 0 0 52px;
|
||||||
|
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;
|
||||||
|
|
|
@ -20,7 +20,6 @@ export default {
|
||||||
HomePage: "home_page",
|
HomePage: "home_page",
|
||||||
RoomView: "room_view",
|
RoomView: "room_view",
|
||||||
UserSettings: "user_settings",
|
UserSettings: "user_settings",
|
||||||
CreateRoom: "create_room",
|
|
||||||
RoomDirectory: "room_directory",
|
RoomDirectory: "room_directory",
|
||||||
UserView: "user_view",
|
UserView: "user_view",
|
||||||
GroupView: "group_view",
|
GroupView: "group_view",
|
||||||
|
|
|
@ -1,284 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015, 2016 OpenMarket 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { _t } from '../../languageHandler';
|
|
||||||
import sdk from '../../index';
|
|
||||||
import MatrixClientPeg from '../../MatrixClientPeg';
|
|
||||||
const PresetValues = {
|
|
||||||
PrivateChat: "private_chat",
|
|
||||||
PublicChat: "public_chat",
|
|
||||||
Custom: "custom",
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'CreateRoom',
|
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
onRoomCreated: PropTypes.func,
|
|
||||||
collapsedRhs: PropTypes.bool,
|
|
||||||
},
|
|
||||||
|
|
||||||
phases: {
|
|
||||||
CONFIG: "CONFIG", // We're waiting for user to configure and hit create.
|
|
||||||
CREATING: "CREATING", // We're sending the request.
|
|
||||||
CREATED: "CREATED", // We successfully created the room.
|
|
||||||
ERROR: "ERROR", // There was an error while trying to create room.
|
|
||||||
},
|
|
||||||
|
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
|
||||||
onRoomCreated: function() {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
phase: this.phases.CONFIG,
|
|
||||||
error_string: "",
|
|
||||||
is_private: true,
|
|
||||||
share_history: false,
|
|
||||||
default_preset: PresetValues.PrivateChat,
|
|
||||||
topic: '',
|
|
||||||
room_name: '',
|
|
||||||
invited_users: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
onCreateRoom: function() {
|
|
||||||
const options = {};
|
|
||||||
|
|
||||||
if (this.state.room_name) {
|
|
||||||
options.name = this.state.room_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.state.topic) {
|
|
||||||
options.topic = this.state.topic;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.state.preset) {
|
|
||||||
if (this.state.preset != PresetValues.Custom) {
|
|
||||||
options.preset = this.state.preset;
|
|
||||||
} else {
|
|
||||||
options.initial_state = [
|
|
||||||
{
|
|
||||||
type: "m.room.join_rules",
|
|
||||||
content: {
|
|
||||||
"join_rule": this.state.is_private ? "invite" : "public",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "m.room.history_visibility",
|
|
||||||
content: {
|
|
||||||
"history_visibility": this.state.share_history ? "shared" : "invited",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
options.invite = this.state.invited_users;
|
|
||||||
|
|
||||||
const alias = this.getAliasLocalpart();
|
|
||||||
if (alias) {
|
|
||||||
options.room_alias_name = alias;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cli = MatrixClientPeg.get();
|
|
||||||
if (!cli) {
|
|
||||||
// TODO: Error.
|
|
||||||
console.error("Cannot create room: No matrix client.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const deferred = cli.createRoom(options);
|
|
||||||
|
|
||||||
if (this.state.encrypt) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
phase: this.phases.CREATING,
|
|
||||||
});
|
|
||||||
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
deferred.then(function(resp) {
|
|
||||||
self.setState({
|
|
||||||
phase: self.phases.CREATED,
|
|
||||||
});
|
|
||||||
self.props.onRoomCreated(resp.room_id);
|
|
||||||
}, function(err) {
|
|
||||||
self.setState({
|
|
||||||
phase: self.phases.ERROR,
|
|
||||||
error_string: err.toString(),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
getPreset: function() {
|
|
||||||
return this.refs.presets.getPreset();
|
|
||||||
},
|
|
||||||
|
|
||||||
getName: function() {
|
|
||||||
return this.refs.name_textbox.getName();
|
|
||||||
},
|
|
||||||
|
|
||||||
getTopic: function() {
|
|
||||||
return this.refs.topic.getTopic();
|
|
||||||
},
|
|
||||||
|
|
||||||
getAliasLocalpart: function() {
|
|
||||||
return this.refs.alias.getAliasLocalpart();
|
|
||||||
},
|
|
||||||
|
|
||||||
getInvitedUsers: function() {
|
|
||||||
return this.refs.user_selector.getUserIds();
|
|
||||||
},
|
|
||||||
|
|
||||||
onPresetChanged: function(preset) {
|
|
||||||
switch (preset) {
|
|
||||||
case PresetValues.PrivateChat:
|
|
||||||
this.setState({
|
|
||||||
preset: preset,
|
|
||||||
is_private: true,
|
|
||||||
share_history: false,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case PresetValues.PublicChat:
|
|
||||||
this.setState({
|
|
||||||
preset: preset,
|
|
||||||
is_private: false,
|
|
||||||
share_history: true,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case PresetValues.Custom:
|
|
||||||
this.setState({
|
|
||||||
preset: preset,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onPrivateChanged: function(ev) {
|
|
||||||
this.setState({
|
|
||||||
preset: PresetValues.Custom,
|
|
||||||
is_private: ev.target.checked,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onShareHistoryChanged: function(ev) {
|
|
||||||
this.setState({
|
|
||||||
preset: PresetValues.Custom,
|
|
||||||
share_history: ev.target.checked,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onTopicChange: function(ev) {
|
|
||||||
this.setState({
|
|
||||||
topic: ev.target.value,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onNameChange: function(ev) {
|
|
||||||
this.setState({
|
|
||||||
room_name: ev.target.value,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onInviteChanged: function(invited_users) {
|
|
||||||
this.setState({
|
|
||||||
invited_users: invited_users,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onAliasChanged: function(alias) {
|
|
||||||
this.setState({
|
|
||||||
alias: alias,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onEncryptChanged: function(ev) {
|
|
||||||
this.setState({
|
|
||||||
encrypt: ev.target.checked,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
const curr_phase = this.state.phase;
|
|
||||||
if (curr_phase == this.phases.CREATING) {
|
|
||||||
const Loader = sdk.getComponent("elements.Spinner");
|
|
||||||
return (
|
|
||||||
<Loader />
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let error_box = "";
|
|
||||||
if (curr_phase == this.phases.ERROR) {
|
|
||||||
error_box = (
|
|
||||||
<div className="mx_Error">
|
|
||||||
{ _t('An error occurred: %(error_string)s', {error_string: this.state.error_string}) }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const CreateRoomButton = sdk.getComponent("create_room.CreateRoomButton");
|
|
||||||
const RoomAlias = sdk.getComponent("create_room.RoomAlias");
|
|
||||||
const Presets = sdk.getComponent("create_room.Presets");
|
|
||||||
const UserSelector = sdk.getComponent("elements.UserSelector");
|
|
||||||
const SimpleRoomHeader = sdk.getComponent("rooms.SimpleRoomHeader");
|
|
||||||
|
|
||||||
const domain = MatrixClientPeg.get().getDomain();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="mx_CreateRoom">
|
|
||||||
<SimpleRoomHeader title={_t("Create Room")} collapsedRhs={this.props.collapsedRhs} />
|
|
||||||
<div className="mx_CreateRoom_body">
|
|
||||||
<input type="text" ref="room_name" value={this.state.room_name} onChange={this.onNameChange} placeholder={_t('Name')} /> <br />
|
|
||||||
<textarea className="mx_CreateRoom_description" ref="topic" value={this.state.topic} onChange={this.onTopicChange} placeholder={_t('Topic')} /> <br />
|
|
||||||
<RoomAlias ref="alias" alias={this.state.alias} homeserver={domain} onChange={this.onAliasChanged} /> <br />
|
|
||||||
<UserSelector ref="user_selector" selected_users={this.state.invited_users} onChange={this.onInviteChanged} /> <br />
|
|
||||||
<Presets ref="presets" onChange={this.onPresetChanged} preset={this.state.preset} /> <br />
|
|
||||||
<div>
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" ref="is_private" checked={this.state.is_private} onChange={this.onPrivateChanged} />
|
|
||||||
{ _t('Make this room private') }
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" ref="share_history" checked={this.state.share_history} onChange={this.onShareHistoryChanged} />
|
|
||||||
{ _t('Share message history with new users') }
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="mx_CreateRoom_encrypt">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" ref="encrypt" checked={this.state.encrypt} onChange={this.onEncryptChanged} />
|
|
||||||
{ _t('Encrypt room') }
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<CreateRoomButton onCreateRoom={this.onCreateRoom} /> <br />
|
|
||||||
</div>
|
|
||||||
{ error_box }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -24,6 +24,9 @@ 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 MainSplit from './MainSplit';
|
||||||
|
import RightPanel from './RightPanel';
|
||||||
import Modal from '../../Modal';
|
import Modal from '../../Modal';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
@ -1280,6 +1283,8 @@ export default React.createClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rightPanel = !this.props.collapsedRhs ? <RightPanel groupId={this.props.groupId} /> : undefined;
|
||||||
|
|
||||||
const headerClasses = {
|
const headerClasses = {
|
||||||
mx_GroupView_header: true,
|
mx_GroupView_header: true,
|
||||||
mx_GroupView_header_view: !this.state.editing,
|
mx_GroupView_header_view: !this.state.editing,
|
||||||
|
@ -1287,7 +1292,7 @@ export default React.createClass({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_GroupView">
|
<main className="mx_GroupView">
|
||||||
<div className={classnames(headerClasses)}>
|
<div className={classnames(headerClasses)}>
|
||||||
<div className="mx_GroupView_header_leftCol">
|
<div className="mx_GroupView_header_leftCol">
|
||||||
<div className="mx_GroupView_header_avatar">
|
<div className="mx_GroupView_header_avatar">
|
||||||
|
@ -1305,12 +1310,15 @@ export default React.createClass({
|
||||||
<div className="mx_GroupView_header_rightCol">
|
<div className="mx_GroupView_header_rightCol">
|
||||||
{ rightButtons }
|
{ rightButtons }
|
||||||
</div>
|
</div>
|
||||||
|
<GroupHeaderButtons />
|
||||||
</div>
|
</div>
|
||||||
|
<MainSplit collapsedRhs={this.props.collapsedRhs} panel={rightPanel}>
|
||||||
<GeminiScrollbarWrapper className="mx_GroupView_body">
|
<GeminiScrollbarWrapper className="mx_GroupView_body">
|
||||||
{ this._getMembershipSection() }
|
{ this._getMembershipSection() }
|
||||||
{ this._getGroupSection() }
|
{ this._getGroupSection() }
|
||||||
</GeminiScrollbarWrapper>
|
</GeminiScrollbarWrapper>
|
||||||
</div>
|
</MainSplit>
|
||||||
|
</main>
|
||||||
);
|
);
|
||||||
} else if (this.state.error) {
|
} else if (this.state.error) {
|
||||||
if (this.state.error.httpStatus === 404) {
|
if (this.state.error.httpStatus === 404) {
|
||||||
|
|
|
@ -173,11 +173,7 @@ const LoggedInView = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onResized: (size, item) => {
|
onResized: (size, item) => {
|
||||||
if (item.classList.contains("mx_LeftPanel_container")) {
|
|
||||||
window.localStorage.setItem("mx_lhs_size", '' + size);
|
window.localStorage.setItem("mx_lhs_size", '' + size);
|
||||||
} else if(item.classList.contains("mx_RightPanel")) {
|
|
||||||
window.localStorage.setItem("mx_rhs_size", '' + size);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const resizer = new Resizer(
|
const resizer = new Resizer(
|
||||||
|
@ -193,10 +189,6 @@ const LoggedInView = React.createClass({
|
||||||
if (lhsSize !== null) {
|
if (lhsSize !== null) {
|
||||||
this.resizer.forHandleAt(0).resize(parseInt(lhsSize, 10));
|
this.resizer.forHandleAt(0).resize(parseInt(lhsSize, 10));
|
||||||
}
|
}
|
||||||
const rhsSize = window.localStorage.getItem("mx_rhs_size");
|
|
||||||
if (rhsSize !== null) {
|
|
||||||
this.resizer.forHandleAt(1).resize(parseInt(rhsSize, 10));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onAccountData: function(event) {
|
onAccountData: function(event) {
|
||||||
|
@ -421,10 +413,8 @@ const LoggedInView = React.createClass({
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
const LeftPanel = sdk.getComponent('structures.LeftPanel');
|
const LeftPanel = sdk.getComponent('structures.LeftPanel');
|
||||||
const RightPanel = sdk.getComponent('structures.RightPanel');
|
|
||||||
const RoomView = sdk.getComponent('structures.RoomView');
|
const RoomView = sdk.getComponent('structures.RoomView');
|
||||||
const UserSettings = sdk.getComponent('structures.UserSettings');
|
const UserSettings = sdk.getComponent('structures.UserSettings');
|
||||||
const CreateRoom = sdk.getComponent('structures.CreateRoom');
|
|
||||||
const RoomDirectory = sdk.getComponent('structures.RoomDirectory');
|
const RoomDirectory = sdk.getComponent('structures.RoomDirectory');
|
||||||
const HomePage = sdk.getComponent('structures.HomePage');
|
const HomePage = sdk.getComponent('structures.HomePage');
|
||||||
const GroupView = sdk.getComponent('structures.GroupView');
|
const GroupView = sdk.getComponent('structures.GroupView');
|
||||||
|
@ -437,7 +427,6 @@ const LoggedInView = React.createClass({
|
||||||
const ServerLimitBar = sdk.getComponent('globals.ServerLimitBar');
|
const ServerLimitBar = sdk.getComponent('globals.ServerLimitBar');
|
||||||
|
|
||||||
let page_element;
|
let page_element;
|
||||||
let right_panel = '';
|
|
||||||
|
|
||||||
switch (this.props.page_type) {
|
switch (this.props.page_type) {
|
||||||
case PageTypes.RoomView:
|
case PageTypes.RoomView:
|
||||||
|
@ -454,9 +443,6 @@ const LoggedInView = React.createClass({
|
||||||
collapsedRhs={this.props.collapseRhs}
|
collapsedRhs={this.props.collapseRhs}
|
||||||
ConferenceHandler={this.props.ConferenceHandler}
|
ConferenceHandler={this.props.ConferenceHandler}
|
||||||
/>;
|
/>;
|
||||||
if (!this.props.collapseRhs) {
|
|
||||||
right_panel = <RightPanel roomId={this.props.currentRoomId} disabled={this.props.rightDisabled} />;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PageTypes.UserSettings:
|
case PageTypes.UserSettings:
|
||||||
|
@ -466,21 +452,12 @@ const LoggedInView = React.createClass({
|
||||||
referralBaseUrl={this.props.config.referralBaseUrl}
|
referralBaseUrl={this.props.config.referralBaseUrl}
|
||||||
teamToken={this.props.teamToken}
|
teamToken={this.props.teamToken}
|
||||||
/>;
|
/>;
|
||||||
if (!this.props.collapseRhs) right_panel = <RightPanel disabled={this.props.rightDisabled} />;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PageTypes.MyGroups:
|
case PageTypes.MyGroups:
|
||||||
page_element = <MyGroups />;
|
page_element = <MyGroups />;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PageTypes.CreateRoom:
|
|
||||||
page_element = <CreateRoom
|
|
||||||
onRoomCreated={this.props.onRoomCreated}
|
|
||||||
collapsedRhs={this.props.collapseRhs}
|
|
||||||
/>;
|
|
||||||
if (!this.props.collapseRhs) right_panel = <RightPanel disabled={this.props.rightDisabled} />;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PageTypes.RoomDirectory:
|
case PageTypes.RoomDirectory:
|
||||||
page_element = <RoomDirectory
|
page_element = <RoomDirectory
|
||||||
ref="roomDirectory"
|
ref="roomDirectory"
|
||||||
|
@ -506,7 +483,8 @@ const LoggedInView = React.createClass({
|
||||||
|
|
||||||
case PageTypes.UserView:
|
case PageTypes.UserView:
|
||||||
page_element = null; // deliberately null for now
|
page_element = null; // deliberately null for now
|
||||||
right_panel = <RightPanel disabled={this.props.rightDisabled} />;
|
// TODO: fix/remove UserView
|
||||||
|
// right_panel = <RightPanel disabled={this.props.rightDisabled} />;
|
||||||
break;
|
break;
|
||||||
case PageTypes.GroupView:
|
case PageTypes.GroupView:
|
||||||
page_element = <GroupView
|
page_element = <GroupView
|
||||||
|
@ -514,7 +492,6 @@ const LoggedInView = React.createClass({
|
||||||
isNew={this.props.currentGroupIsNew}
|
isNew={this.props.currentGroupIsNew}
|
||||||
collapsedRhs={this.props.collapseRhs}
|
collapsedRhs={this.props.collapseRhs}
|
||||||
/>;
|
/>;
|
||||||
if (!this.props.collapseRhs) right_panel = <RightPanel groupId={this.props.currentGroupId} disabled={this.props.rightDisabled} />;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,11 +549,7 @@ const LoggedInView = React.createClass({
|
||||||
disabled={this.props.leftDisabled}
|
disabled={this.props.leftDisabled}
|
||||||
/>
|
/>
|
||||||
<ResizeHandle/>
|
<ResizeHandle/>
|
||||||
<main className='mx_MatrixChat_middlePanel'>
|
|
||||||
{ page_element }
|
{ page_element }
|
||||||
</main>
|
|
||||||
<ResizeHandle reverse={true}/>
|
|
||||||
{ right_panel }
|
|
||||||
</div>
|
</div>
|
||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
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 ResizeHandle from '../views/elements/ResizeHandle';
|
||||||
|
import {Resizer, FixedDistributor} from '../../resizer';
|
||||||
|
|
||||||
|
export default class MainSplit extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this._setResizeContainerRef = this._setResizeContainerRef.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_createResizer() {
|
||||||
|
const classNames = {
|
||||||
|
handle: "mx_ResizeHandle",
|
||||||
|
vertical: "mx_ResizeHandle_vertical",
|
||||||
|
reverse: "mx_ResizeHandle_reverse",
|
||||||
|
};
|
||||||
|
const resizer = new Resizer(
|
||||||
|
this.resizeContainer,
|
||||||
|
FixedDistributor);
|
||||||
|
resizer.setClassNames(classNames);
|
||||||
|
const rhsSize = window.localStorage.getItem("mx_rhs_size");
|
||||||
|
if (rhsSize !== null) {
|
||||||
|
resizer.forHandleAt(0).resize(parseInt(rhsSize, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
resizer.attach();
|
||||||
|
this.resizer = resizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
_setResizeContainerRef(div) {
|
||||||
|
this.resizeContainer = div;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (this.props.panel && !this.collapsedRhs) {
|
||||||
|
this._createResizer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.resizer) {
|
||||||
|
this.resizer.detach();
|
||||||
|
this.resizer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
const wasExpanded = !this.props.collapsedRhs && prevProps.collapsedRhs;
|
||||||
|
const wasCollapsed = this.props.collapsedRhs && !prevProps.collapsedRhs;
|
||||||
|
const wasPanelSet = this.props.panel && !prevProps.panel;
|
||||||
|
const wasPanelCleared = !this.props.panel && prevProps.panel;
|
||||||
|
|
||||||
|
if (wasExpanded || wasPanelSet) {
|
||||||
|
this._createResizer();
|
||||||
|
} else if (wasCollapsed || wasPanelCleared) {
|
||||||
|
this.resizer.detach();
|
||||||
|
this.resizer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const bodyView = React.Children.only(this.props.children);
|
||||||
|
const panelView = this.props.panel;
|
||||||
|
|
||||||
|
if (this.props.collapsedRhs || !panelView) {
|
||||||
|
return bodyView;
|
||||||
|
} else {
|
||||||
|
return <div className="mx_MainSplit" ref={this._setResizeContainerRef}>
|
||||||
|
{ bodyView }
|
||||||
|
<ResizeHandle reverse={true} />
|
||||||
|
{ panelView }
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
|
||||||
this.onClick = this.onClick.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
onClick(ev) {
|
static get propTypes() {
|
||||||
Analytics.trackEvent(...this.props.analytics);
|
return {
|
||||||
dis.dispatch({
|
|
||||||
action: 'view_right_panel_phase',
|
|
||||||
phase: this.props.clickPhase,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
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
|
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
|
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: {
|
static get contextTypes() {
|
||||||
|
return {
|
||||||
matrixClient: PropTypes.instanceOf(MatrixClient),
|
matrixClient: PropTypes.instanceOf(MatrixClient),
|
||||||
},
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Phase: {
|
static Phase = Object.freeze({
|
||||||
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() {
|
|
||||||
this.forceUpdate(); // eslint-disable-line babel/no-invalid-this
|
|
||||||
}, 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") {
|
onAction(payload) {
|
||||||
this.setState({
|
if (payload.action === "view_right_panel_phase") {
|
||||||
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,98 +159,41 @@ 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 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}>
|
||||||
<div className="mx_RightPanel_icon" >
|
<div className="mx_RightPanel_icon" >
|
||||||
<TintableSvg src="img/icon-invite-people.svg" width="35" height="35" />
|
<TintableSvg src="img/icon-invite-people.svg" width="35" height="35" />
|
||||||
|
@ -372,13 +217,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>
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
|
|
@ -43,6 +43,8 @@ const Rooms = require('../../Rooms');
|
||||||
|
|
||||||
import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard';
|
import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard';
|
||||||
|
|
||||||
|
import MainSplit from './MainSplit';
|
||||||
|
import RightPanel from './RightPanel';
|
||||||
import RoomViewStore from '../../stores/RoomViewStore';
|
import RoomViewStore from '../../stores/RoomViewStore';
|
||||||
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
|
||||||
import WidgetEchoStore from '../../stores/WidgetEchoStore';
|
import WidgetEchoStore from '../../stores/WidgetEchoStore';
|
||||||
|
@ -1510,6 +1512,7 @@ module.exports = React.createClass({
|
||||||
oobData={this.props.oobData}
|
oobData={this.props.oobData}
|
||||||
collapsedRhs={this.props.collapsedRhs}
|
collapsedRhs={this.props.collapsedRhs}
|
||||||
/>
|
/>
|
||||||
|
<div className="mx_RoomView_body">
|
||||||
<div className="mx_RoomView_auxPanel">
|
<div className="mx_RoomView_auxPanel">
|
||||||
<RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
|
<RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
|
||||||
onForgetClick={this.onForgetClick}
|
onForgetClick={this.onForgetClick}
|
||||||
|
@ -1523,6 +1526,7 @@ module.exports = React.createClass({
|
||||||
room={this.state.room}
|
room={this.state.room}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="mx_RoomView_messagePanel"></div>
|
<div className="mx_RoomView_messagePanel"></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1555,6 +1559,7 @@ module.exports = React.createClass({
|
||||||
room={this.state.room}
|
room={this.state.room}
|
||||||
collapsedRhs={this.props.collapsedRhs}
|
collapsedRhs={this.props.collapsedRhs}
|
||||||
/>
|
/>
|
||||||
|
<div className="mx_RoomView_body">
|
||||||
<div className="mx_RoomView_auxPanel">
|
<div className="mx_RoomView_auxPanel">
|
||||||
<RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
|
<RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
|
||||||
onForgetClick={this.onForgetClick}
|
onForgetClick={this.onForgetClick}
|
||||||
|
@ -1566,6 +1571,7 @@ module.exports = React.createClass({
|
||||||
room={this.state.room}
|
room={this.state.room}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="mx_RoomView_messagePanel"></div>
|
<div className="mx_RoomView_messagePanel"></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1811,8 +1817,10 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const rightPanel = this.state.room ? <RightPanel roomId={this.state.room.roomId} /> : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref="roomView">
|
<main className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref="roomView">
|
||||||
<RoomHeader ref="header" room={this.state.room} searchInfo={searchInfo}
|
<RoomHeader ref="header" room={this.state.room} searchInfo={searchInfo}
|
||||||
oobData={this.props.oobData}
|
oobData={this.props.oobData}
|
||||||
editing={this.state.editingRoomSettings}
|
editing={this.state.editingRoomSettings}
|
||||||
|
@ -1827,8 +1835,9 @@ module.exports = React.createClass({
|
||||||
onForgetClick={(myMembership === "leave") ? this.onForgetClick : null}
|
onForgetClick={(myMembership === "leave") ? this.onForgetClick : null}
|
||||||
onLeaveClick={(myMembership === "join") ? this.onLeaveClick : null}
|
onLeaveClick={(myMembership === "join") ? this.onLeaveClick : null}
|
||||||
/>
|
/>
|
||||||
{ auxPanel }
|
<MainSplit panel={rightPanel} collapsedRhs={this.props.collapsedRhs}>
|
||||||
<div className={fadableSectionClasses}>
|
<div className={fadableSectionClasses}>
|
||||||
|
{ auxPanel }
|
||||||
{ topUnreadMessagesBar }
|
{ topUnreadMessagesBar }
|
||||||
{ messagePanel }
|
{ messagePanel }
|
||||||
{ searchResultsPanel }
|
{ searchResultsPanel }
|
||||||
|
@ -1840,7 +1849,8 @@ module.exports = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
{ messageComposer }
|
{ messageComposer }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</MainSplit>
|
||||||
|
</main>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -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']}
|
||||||
|
/>,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,
|
||||||
|
};
|
|
@ -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>;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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…
Reference in New Issue