diff --git a/skins/base/views/molecules/MemberTile.js b/skins/base/views/molecules/MemberTile.js
index 1286173d38..8dd3f00ab1 100644
--- a/skins/base/views/molecules/MemberTile.js
+++ b/skins/base/views/molecules/MemberTile.js
@@ -59,8 +59,7 @@ module.exports = React.createClass({
mainClassName += presenceClass;
return (
-
+

+
+ { this.props.simpleHeader }
+
+
+ }
+ else {
+ var topic = this.props.room.currentState.getStateEvents('m.room.topic', '');
- var callButtons;
- if (this.state) {
- switch (this.state.call_state) {
- case "ringback":
- case "connected":
- callButtons = (
-
- BYEBYE
-
- );
- break;
+ var callButtons;
+ if (this.state) {
+ switch (this.state.call_state) {
+ case "ringback":
+ case "connected":
+ callButtons = (
+
+ End call
+
+ );
+ break;
+ }
}
- }
- var name = null;
- var topic_el = null;
- var save_button = null;
- var settings_button = null;
- if (this.props.editing) {
- name =
;
- // if (topic) topic_el =
- save_button = (
-
- Save
-
- );
- } else {
- name =
;
- if (topic) topic_el =
{ topic.getContent().topic }
;
- settings_button = (
-
-

-
- );
- }
+ var name = null;
+ var topic_el = null;
+ var save_button = null;
+ var settings_button = null;
+ if (this.props.editing) {
+ name =
;
+ // if (topic) topic_el =
+ save_button = (
+
+ Save
+
+ );
+ } else {
+ name =
;
+ if (topic) topic_el =
{ topic.getContent().topic }
;
+ settings_button = (
+
+

+
+ );
+ }
- return (
-
+ header =
@@ -91,13 +100,13 @@ module.exports = React.createClass({
{ topic_el }
+ {callButtons}
{ save_button }
{ settings_button }
- {callButtons}
@@ -106,6 +115,11 @@ module.exports = React.createClass({
+ }
+
+ return (
+
+ { header }
);
},
diff --git a/skins/base/views/organisms/LeftPanel.js b/skins/base/views/organisms/LeftPanel.js
index 252a5d064d..165759109c 100644
--- a/skins/base/views/organisms/LeftPanel.js
+++ b/skins/base/views/organisms/LeftPanel.js
@@ -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({
-
+
);
}
diff --git a/skins/base/views/organisms/MemberList.js b/skins/base/views/organisms/MemberList.js
index 3e586e569c..dfeecb0350 100644
--- a/skins/base/views/organisms/MemberList.js
+++ b/skins/base/views/organisms/MemberList.js
@@ -17,6 +17,7 @@ limitations under the License.
'use strict';
var React = require('react');
+var classNames = require('classnames');
var MemberListController = require("../../../../src/controllers/organisms/MemberList");
@@ -30,6 +31,10 @@ module.exports = React.createClass({
displayName: 'MemberList',
mixins: [MemberListController],
+ getInitialState: function() {
+ return { editing: false };
+ },
+
// FIXME: combine this more nicely with the MemberInfo positioning stuff...
onMemberListScroll: function(ev) {
if (this.refs.memberListScroll) {
@@ -55,23 +60,40 @@ module.exports = React.createClass({
onPopulateInvite: function(inputText, shouldSubmit) {
// reset back to placeholder
this.refs.invite.setValue("Invite", false, true);
+ this.setState({ editing: false });
if (!shouldSubmit) {
return; // enter key wasn't pressed
}
this.onInvite(inputText);
},
+ onClickInvite: function(ev) {
+ this.setState({ editing: true });
+ this.refs.invite.onClickDiv();
+ console.log("forcing update on memberlist after having clicked invite");
+ ev.stopPropagation();
+ ev.preventDefault();
+ },
+
inviteTile: function() {
- if (this.state.inviting) {
- return (
-
- );
- }
+ // if (this.state.inviting) {
+ // return (
+ //
+ // );
+ // }
+
+ var classes = classNames({
+ mx_MemberTile: true,
+ mx_MemberTile_inviteEditing: this.state.editing,
+ });
+
+ console.log("rendering inviteTile, with phase as " + (this.refs.invite ? this.refs.invite.state.phase : "unknown"));
+
return (
-
+
);
diff --git a/skins/base/views/organisms/RightPanel.js b/skins/base/views/organisms/RightPanel.js
index e1634adc1e..5b6477a0d0 100644
--- a/skins/base/views/organisms/RightPanel.js
+++ b/skins/base/views/organisms/RightPanel.js
@@ -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 (
-
-
+ var buttonGroup;
+ var panel;
+ if (this.props.roomId) {
+ buttonGroup =
;
+
+ if (this.state.phase == this.Phase.MemberList) {
+ panel =
+ }
+ }
+
+ return (
+
+
+ { buttonGroup }
-
+ { panel }
);
}
diff --git a/skins/base/views/organisms/RoomDirectory.js b/skins/base/views/organisms/RoomDirectory.js
new file mode 100644
index 0000000000..7ffb4977ad
--- /dev/null
+++ b/skins/base/views/organisms/RoomDirectory.js
@@ -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(
+
+ { name } |
+ { rooms[i].topic } |
+ { rooms[i].num_joined_members } |
+
+ );
+ }
+ 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 (
+
+
+
+
+
+ Room | Topic | Users |
+ { this.getRows(this.state.roomAlias) }
+
+
+
+ );
+ }
+});
+
diff --git a/skins/base/views/organisms/RoomView.js b/skins/base/views/organisms/RoomView.js
index 56699165ad..4f19b9b306 100644
--- a/skins/base/views/organisms/RoomView.js
+++ b/skins/base/views/organisms/RoomView.js
@@ -166,6 +166,7 @@ module.exports = React.createClass({
if (typingString) {
statusBar = (
+

{typingString}
);
diff --git a/skins/base/views/organisms/UserSettings.js b/skins/base/views/organisms/UserSettings.js
index 9afa3c0360..7a57ec768e 100644
--- a/skins/base/views/organisms/UserSettings.js
+++ b/skins/base/views/organisms/UserSettings.js
@@ -73,7 +73,7 @@ module.exports = React.createClass({
diff --git a/skins/base/views/pages/MatrixChat.js b/skins/base/views/pages/MatrixChat.js
index 85a29264b3..73af508243 100644
--- a/skins/base/views/pages/MatrixChat.js
+++ b/skins/base/views/pages/MatrixChat.js
@@ -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 =
+ right_panel =
break;
case this.PageTypes.CreateRoom:
page_element =
+ right_panel =
+ break;
+ case this.PageTypes.RoomDirectory:
+ page_element =
+ right_panel =
break;
}
diff --git a/src/ComponentBroker.js b/src/ComponentBroker.js
index a9ccebd12a..6e5d1e11eb 100644
--- a/src/ComponentBroker.js
+++ b/src/ComponentBroker.js
@@ -97,9 +97,10 @@ require('../skins/base/views/molecules/RoomSettings');
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');
diff --git a/src/controllers/atoms/EditableText.js b/src/controllers/atoms/EditableText.js
index 15ee58a7f3..5ea4ce8c4a 100644
--- a/src/controllers/atoms/EditableText.js
+++ b/src/controllers/atoms/EditableText.js
@@ -22,6 +22,7 @@ module.exports = {
propTypes: {
onValueChanged: React.PropTypes.func,
initialValue: React.PropTypes.string,
+ label: React.PropTypes.string,
placeHolder: React.PropTypes.string,
},
@@ -34,7 +35,8 @@ module.exports = {
return {
onValueChanged: function() {},
initialValue: '',
- placeHolder: 'Click to set',
+ label: 'Click to set',
+ placeholder: '',
};
},
@@ -77,6 +79,7 @@ module.exports = {
this.setState({
phase: this.Phases.Display,
});
+ this.onValueChanged(false);
},
onValueChanged: function(shouldSubmit) {
diff --git a/src/controllers/molecules/MessageComposer.js b/src/controllers/molecules/MessageComposer.js
index a9de008d6f..2ece5636ad 100644
--- a/src/controllers/molecules/MessageComposer.js
+++ b/src/controllers/molecules/MessageComposer.js
@@ -200,7 +200,7 @@ module.exports = {
}, function(err) {
console.error("Command failure: %s", err);
Modal.createDialog(ErrorDialog, {
- title: "Server Error",
+ title: "Server error",
description: err.message
});
});
@@ -208,7 +208,7 @@ module.exports = {
else if (cmd.error) {
console.error(cmd.error);
Modal.createDialog(ErrorDialog, {
- title: "Command Error",
+ title: "Command error",
description: cmd.error
});
}
diff --git a/src/controllers/organisms/MemberList.js b/src/controllers/organisms/MemberList.js
index 0695270066..29d4f20a60 100644
--- a/src/controllers/organisms/MemberList.js
+++ b/src/controllers/organisms/MemberList.js
@@ -101,7 +101,7 @@ module.exports = {
}, function(err) {
console.error("Failed to invite: %s", JSON.stringify(err));
Modal.createDialog(ErrorDialog, {
- title: "Invite Server Error",
+ title: "Server error whilst inviting",
description: err.message
});
self.setState({
diff --git a/src/controllers/pages/MatrixChat.js b/src/controllers/pages/MatrixChat.js
index 1e38a2150c..30135a2b87 100644
--- a/src/controllers/pages/MatrixChat.js
+++ b/src/controllers/pages/MatrixChat.js
@@ -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,
};
},
@@ -127,6 +128,7 @@ module.exports = {
currentRoom: payload.room_id,
page_type: this.PageTypes.RoomView,
});
+ this.notifyNewScreen('room/'+payload.room_id);
break;
case 'view_prev_room':
roomIndexDelta = -1;
@@ -156,6 +158,11 @@ module.exports = {
page_type: this.PageTypes.CreateRoom,
});
break;
+ case 'view_room_directory':
+ this.setState({
+ page_type: this.PageTypes.RoomDirectory,
+ });
+ break;
}
},
@@ -172,13 +179,18 @@ module.exports = {
var cli = MatrixClientPeg.get();
var self = this;
cli.on('syncComplete', function() {
- var firstRoom = null;
- if (cli.getRooms() && cli.getRooms().length) {
- firstRoom = RoomListSorter.mostRecentActivityFirst(
- cli.getRooms()
- )[0].roomId;
+ if (!self.state.currentRoom) {
+ var firstRoom = null;
+ if (cli.getRooms() && cli.getRooms().length) {
+ firstRoom = RoomListSorter.mostRecentActivityFirst(
+ cli.getRooms()
+ )[0].roomId;
+ }
+ self.setState({ready: true, currentRoom: firstRoom});
+ self.notifyNewScreen('room/'+firstRoom);
+ } else {
+ self.setState({ready: true});
}
- self.setState({ready: true, currentRoom: firstRoom});
dis.dispatch({action: 'focus_composer'});
});
cli.on('Call.incoming', function(call) {
@@ -222,6 +234,12 @@ module.exports = {
action: 'start_login',
params: params
});
+ } else if (screen.indexOf('room/') == 0) {
+ var roomId = screen.split('/')[1];
+ dis.dispatch({
+ action: 'view_room',
+ room_id: roomId
+ });
}
},