rename DirectoryMenu as BottomLeftMenu and implement a really really really basic RoomDirectory
This commit is contained in:
parent
fe71f69f0a
commit
12c824323d
12 changed files with 280 additions and 39 deletions
1
examples/trivial/fonts
Symbolic link
1
examples/trivial/fonts
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../skins/base/fonts/
|
|
@ -86,6 +86,15 @@ limitations under the License.
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_simpleHeader {
|
||||
line-height: 88px;
|
||||
color: #80cef4;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
overflow: scroll;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_name {
|
||||
vertical-align: middle;
|
||||
height: 28px;
|
||||
|
|
|
@ -43,7 +43,7 @@ limitations under the License.
|
|||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_DirectoryMenu {
|
||||
.mx_LeftPanel .mx_BottomLeftMenu {
|
||||
-webkit-box-ordinal-group: 3;
|
||||
-moz-box-ordinal-group: 3;
|
||||
-ms-flex-order: 3;
|
||||
|
@ -56,15 +56,15 @@ limitations under the License.
|
|||
border-top: 1px solid #f3f8fa;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_DirectoryMenu .mx_RoomTile {
|
||||
.mx_LeftPanel .mx_BottomLeftMenu .mx_RoomTile {
|
||||
color: #378bb4;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_DirectoryMenu .mx_RoomTile_avatar {
|
||||
.mx_LeftPanel .mx_BottomLeftMenu .mx_RoomTile_avatar {
|
||||
padding-left: 14px;
|
||||
}
|
||||
|
||||
.mx_LeftPanel .mx_DirectoryMenu .mx_DirectoryMenu_options {
|
||||
.mx_LeftPanel .mx_BottomLeftMenu .mx_BottomLeftMenu_options {
|
||||
margin-top: 12px;
|
||||
width: 100%;
|
||||
}
|
40
skins/base/css/organisms/RoomDirectory.css
Normal file
40
skins/base/css/organisms/RoomDirectory.css
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright 2015 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.
|
||||
*/
|
||||
|
||||
.mx_RoomDirectory {
|
||||
max-width: 720px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_input {
|
||||
margin: auto;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #c7c7c7;
|
||||
font-weight: 300;
|
||||
font-size: 14px;
|
||||
padding: 9px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_table td,
|
||||
.mx_RoomDirectory_table th, {
|
||||
padding: 6px;
|
||||
}
|
|
@ -21,34 +21,34 @@ var classNames = require('classnames');
|
|||
|
||||
var dis = require("../../../../src/dispatcher");
|
||||
|
||||
//var DirectoryMenuController = require("../../../../src/controllers/molecules/DirectoryMenuController");
|
||||
|
||||
var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'DirectoryMenu',
|
||||
// mixins: [DirectoryMenuController],
|
||||
displayName: 'BottomLeftMenu',
|
||||
|
||||
// FIXME: should these onClicks be in the controller instead?
|
||||
onSettingsClick: function() {
|
||||
dis.dispatch({action: 'view_user_settings'});
|
||||
},
|
||||
|
||||
onRoomDirectoryClick: function() {
|
||||
dis.dispatch({action: 'view_room_directory'});
|
||||
},
|
||||
|
||||
onCreateRoomClick: function() {
|
||||
dis.dispatch({action: 'view_create_room'});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_DirectoryMenu">
|
||||
<div className="mx_DirectoryMenu_options">
|
||||
<div className="mx_BottomLeftMenu">
|
||||
<div className="mx_BottomLeftMenu_options">
|
||||
<div className="mx_RoomTile" onClick={this.onCreateRoomClick}>
|
||||
<div className="mx_RoomTile_avatar">
|
||||
<img src="img/create-big.png" width="42" height="42"/>
|
||||
</div>
|
||||
<div className="mx_RoomTile_name">Create new room</div>
|
||||
</div>
|
||||
<div className="mx_RoomTile">
|
||||
<div className="mx_RoomTile" onClick={this.onRoomDirectoryClick}>
|
||||
<div className="mx_RoomTile_avatar">
|
||||
<img src="img/directory-big.png" width="42" height="42"/>
|
||||
</div>
|
|
@ -35,25 +35,34 @@ module.exports = React.createClass({
|
|||
|
||||
render: function() {
|
||||
|
||||
var topic = this.props.room.currentState.getStateEvents('m.room.topic', '');
|
||||
topic = topic ? <div className="mx_RoomHeader_topic">{ topic.getContent().topic }</div> : null;
|
||||
|
||||
var callButtons;
|
||||
if (this.state) {
|
||||
switch (this.state.call_state) {
|
||||
case "ringback":
|
||||
case "connected":
|
||||
callButtons = (
|
||||
<div className="mx_RoomHeader_hangupButton" onClick={this.onHangupClick}>
|
||||
End call
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
}
|
||||
var header;
|
||||
if (this.props.simpleHeader) {
|
||||
header =
|
||||
<div className="mx_RoomHeader_wrapper">
|
||||
<div className="mx_RoomHeader_simpleHeader">
|
||||
{ this.props.simpleHeader }
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else {
|
||||
var topic = this.props.room.currentState.getStateEvents('m.room.topic', '');
|
||||
topic = topic ? <div className="mx_RoomHeader_topic">{ topic.getContent().topic }</div> : null;
|
||||
|
||||
return (
|
||||
<div className="mx_RoomHeader">
|
||||
var callButtons;
|
||||
if (this.state) {
|
||||
switch (this.state.call_state) {
|
||||
case "ringback":
|
||||
case "connected":
|
||||
callButtons = (
|
||||
<div className="mx_RoomHeader_hangupButton" onClick={this.onHangupClick}>
|
||||
End call
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
header =
|
||||
<div className="mx_RoomHeader_wrapper">
|
||||
<div className="mx_RoomHeader_leftRow">
|
||||
<div className="mx_RoomHeader_avatar">
|
||||
|
@ -82,6 +91,11 @@ module.exports = React.createClass({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_RoomHeader">
|
||||
{ header }
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -20,7 +20,7 @@ var React = require('react');
|
|||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
|
||||
var RoomList = ComponentBroker.get('organisms/RoomList');
|
||||
var DirectoryMenu = ComponentBroker.get('molecules/DirectoryMenu');
|
||||
var BottomLeftMenu = ComponentBroker.get('molecules/BottomLeftMenu');
|
||||
var IncomingCallBox = ComponentBroker.get('molecules/voip/IncomingCallBox');
|
||||
var RoomCreate = ComponentBroker.get('molecules/RoomCreate');
|
||||
|
||||
|
@ -33,7 +33,7 @@ module.exports = React.createClass({
|
|||
<img className="mx_LeftPanel_hideButton" src="img/hide.png" width="32" height="32" alt="<"/>
|
||||
<IncomingCallBox />
|
||||
<RoomList selectedRoom={this.props.selectedRoom} />
|
||||
<DirectoryMenu />
|
||||
<BottomLeftMenu />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,20 +24,53 @@ var MemberList = ComponentBroker.get('organisms/MemberList');
|
|||
module.exports = React.createClass({
|
||||
displayName: 'RightPanel',
|
||||
|
||||
Phase : {
|
||||
Blank: 'Blank',
|
||||
None: 'None',
|
||||
MemberList: 'MemberList',
|
||||
FileList: 'FileList',
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
phase : this.Phase.None
|
||||
}
|
||||
},
|
||||
|
||||
onMemberListButtonClick: function() {
|
||||
if (this.state.phase == this.Phase.None) {
|
||||
this.setState({ phase: this.Phase.MemberList });
|
||||
}
|
||||
else {
|
||||
this.setState({ phase: this.Phase.None });
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_RightPanel">
|
||||
<div className="mx_RightPanel_header">
|
||||
var buttonGroup;
|
||||
var panel;
|
||||
if (this.props.roomId) {
|
||||
buttonGroup =
|
||||
<div className="mx_RightPanel_headerButtonGroup">
|
||||
<div className="mx_RightPanel_headerButton">
|
||||
<img src="img/file.png" width="32" height="32" alt="Files"/>
|
||||
</div>
|
||||
<div className="mx_RightPanel_headerButton">
|
||||
<div className="mx_RightPanel_headerButton" onClick={ this.onMemberListButtonClick }>
|
||||
<img src="img/members.png" width="32" height="32" alt="Members"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
if (this.state.phase == this.Phase.MemberList) {
|
||||
panel = <MemberList roomId={this.props.roomId} key={this.props.roomId} />
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_RightPanel">
|
||||
<div className="mx_RightPanel_header">
|
||||
{ buttonGroup }
|
||||
</div>
|
||||
<MemberList roomId={this.props.roomId} key={this.props.roomId} />
|
||||
{ panel }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
130
skins/base/views/organisms/RoomDirectory.js
Normal file
130
skins/base/views/organisms/RoomDirectory.js
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
Copyright 2015 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';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
|
||||
var Modal = require("../../../../src/Modal");
|
||||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog");
|
||||
var RoomHeader = ComponentBroker.get('molecules/RoomHeader');
|
||||
var dis = require("../../../../src/dispatcher");
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomDirectory',
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
publicRooms: [],
|
||||
roomAlias: '',
|
||||
}
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
var self = this;
|
||||
MatrixClientPeg.get().publicRooms(function (err, data) {
|
||||
if (err) {
|
||||
console.error("Failed to get publicRooms: %s", JSON.stringify(err));
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to get public room list",
|
||||
description: err.message
|
||||
});
|
||||
}
|
||||
else {
|
||||
self.setState({
|
||||
publicRooms: data.chunk
|
||||
});
|
||||
self.forceUpdate();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
joinRoom: function(roomId) {
|
||||
// XXX: check that JS SDK suppresses duplicate attempts to join the same room
|
||||
MatrixClientPeg.get().joinRoom(roomId).done(function() {
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: roomId
|
||||
});
|
||||
}, function(err) {
|
||||
console.error("Failed to join room: %s", JSON.stringify(err));
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Failed to join room",
|
||||
description: err.message
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getRows: function(filter) {
|
||||
if (!this.state.publicRooms) return [];
|
||||
|
||||
var rooms = this.state.publicRooms.filter(function(a) {
|
||||
// FIXME: if incrementally typing, keep narrowing down the search set
|
||||
return (a.aliases[0].search(filter) >= 0);
|
||||
}).sort(function(a,b) {
|
||||
return a.num_joined_members > b.num_joined_members;
|
||||
});
|
||||
var rows = [];
|
||||
var self = this;
|
||||
for (var i = 0; i < rooms.length; i++) {
|
||||
var name = rooms[i].name;
|
||||
if (!name) {
|
||||
if (rooms[i].aliases[0]) name = rooms[i].aliases[0]
|
||||
}
|
||||
else {
|
||||
if (rooms[i].aliases[0]) name += " (" + rooms[i].aliases[0] + ")";
|
||||
}
|
||||
rows.unshift(
|
||||
<tr key={ rooms[i].room_id } onClick={ function() { self.joinRoom(rooms[i].room_id); } }>
|
||||
<td><img src={ MatrixClientPeg.get().getAvatarUrlForRoom(rooms[i].room_id, 40, 40, "crop") } width="40" height="40" alt=""/> { name }</td>
|
||||
<td>{ rooms[i].topic }</td>
|
||||
<td style={ {'text-align' : 'center'} }>{ rooms[i].num_joined_members }</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
return rows;
|
||||
},
|
||||
|
||||
onKeyUp: function(ev) {
|
||||
this.forceUpdate();
|
||||
this.setState({ roomAlias : this.refs.roomAlias.getDOMNode().value })
|
||||
if (ev.key == "Enter") {
|
||||
this.joinRoom(this.refs.roomAlias.getDOMNode().value);
|
||||
}
|
||||
if (ev.key == "Down") {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_RoomDirectory">
|
||||
<RoomHeader simpleHeader="Public Rooms" />
|
||||
<div className="mx_RoomDirectory_list">
|
||||
<input ref="roomAlias" placeholder="Join a room (e.g. #foo:domain.com)" className="mx_RoomDirectory_input" size="64" onKeyUp={ this.onKeyUp }/>
|
||||
<table className="mx_RoomDirectory_table">
|
||||
<tr><th>Room</th><th>Topic</th><th>Users</th></tr>
|
||||
{ this.getRows(this.state.roomAlias) }
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
@ -26,6 +26,7 @@ var Login = ComponentBroker.get('templates/Login');
|
|||
var UserSettings = ComponentBroker.get('organisms/UserSettings');
|
||||
var Register = ComponentBroker.get('templates/Register');
|
||||
var CreateRoom = ComponentBroker.get('organisms/CreateRoom');
|
||||
var RoomDirectory = ComponentBroker.get('organisms/RoomDirectory');
|
||||
|
||||
var MatrixChatController = require("../../../../src/controllers/pages/MatrixChat");
|
||||
|
||||
|
@ -59,9 +60,15 @@ module.exports = React.createClass({
|
|||
break;
|
||||
case this.PageTypes.UserSettings:
|
||||
page_element = <UserSettings />
|
||||
right_panel = <RightPanel/>
|
||||
break;
|
||||
case this.PageTypes.CreateRoom:
|
||||
page_element = <CreateRoom onRoomCreated={this.onRoomCreated}/>
|
||||
right_panel = <RightPanel/>
|
||||
break;
|
||||
case this.PageTypes.RoomDirectory:
|
||||
page_element = <RoomDirectory />
|
||||
right_panel = <RightPanel/>
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,9 +96,10 @@ require('../skins/base/views/molecules/ChangePassword');
|
|||
require('../skins/base/views/organisms/LeftPanel');
|
||||
require('../skins/base/views/organisms/RightPanel');
|
||||
require('../skins/base/views/organisms/LogoutPrompt');
|
||||
require('../skins/base/views/organisms/RoomDirectory');
|
||||
require('../skins/base/views/molecules/RoomCreate');
|
||||
require('../skins/base/views/molecules/RoomDropTarget');
|
||||
require('../skins/base/views/molecules/DirectoryMenu');
|
||||
require('../skins/base/views/molecules/BottomLeftMenu');
|
||||
require('../skins/base/views/molecules/DateSeparator');
|
||||
require('../skins/base/views/atoms/voip/VideoFeed');
|
||||
require('../skins/base/views/molecules/voip/VideoView');
|
||||
|
|
|
@ -33,6 +33,7 @@ module.exports = {
|
|||
RoomView: "room_view",
|
||||
UserSettings: "user_settings",
|
||||
CreateRoom: "create_room",
|
||||
RoomDirectory: "room_directory",
|
||||
},
|
||||
|
||||
AuxPanel: {
|
||||
|
@ -43,7 +44,7 @@ module.exports = {
|
|||
return {
|
||||
logged_in: !!(MatrixClientPeg.get() && MatrixClientPeg.get().credentials),
|
||||
ready: false,
|
||||
page_type: this.PageTypes.RoomView,
|
||||
page_type: MatrixClientPeg.get().getRooms().length ? this.PageTypes.RoomView : this.PageTypes.RoomDirectory,
|
||||
aux_panel: null,
|
||||
};
|
||||
},
|
||||
|
@ -157,6 +158,11 @@ module.exports = {
|
|||
page_type: this.PageTypes.CreateRoom,
|
||||
});
|
||||
break;
|
||||
case 'view_room_directory':
|
||||
this.setState({
|
||||
page_type: this.PageTypes.RoomDirectory,
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
Loading…
Reference in a new issue