diff --git a/README.md b/README.md
index 690e1041..a15917a4 100644
--- a/README.md
+++ b/README.md
@@ -22,18 +22,34 @@ into the `vector` directory and run your own server.
Development
===========
-You can work on any of the source files within Vector with the setup above,
-and your changes will cause an instant rebuild. If you also need to make
-changes to the react sdk, you can:
-1. Link the react sdk package into the example:
+For simple tweaks, you can work on any of the source files within Vector with the
+setup above, and your changes will cause an instant rebuild.
+
+However, all serious development on Vector happens on the `develop` branch. This typically
+depends on the `develop` snapshot versions of `matrix-react-sdk` and `matrix-js-sdk`
+too, which isn't expressed in Vector's `package.json`. To do this, check out
+the `develop` branches of these libraries and then use `npm link` to tell Vector
+about them:
+
+1. `git clone git@github.com:matrix-org/matrix-react-sdk.git`
+2. `cd matrix-react-sdk`
+3. `git checkout develop`
+4. `npm install`
+5. `npm start` (to start the dev rebuilder)
+6. `cd ../vector-web`
+7. Link the react sdk package into the example:
`npm link path/to/your/react/sdk`
-2. Start the development rebuilder in your react SDK directory:
- `npm start`
+
+Similarly, you may need to `npm link path/to/your/js/sdk` in your `matrix-react-sdk`
+directory.
If you add or remove any components from the Vector skin, you will need to rebuild
the skin's index by running, `npm run reskindex`.
+You may need to run `npm i source-map-loader` in matrix-js-sdk if you get errors
+about "Cannot resolve module 'source-map-loader'" due to shortcomings in webpack.
+
Deployment
==========
diff --git a/package.json b/package.json
index 429e6139..02f793a1 100644
--- a/package.json
+++ b/package.json
@@ -27,8 +27,8 @@
"filesize": "^3.1.2",
"flux": "~2.0.3",
"linkifyjs": "^2.0.0-beta.4",
- "matrix-js-sdk": "^0.2.1",
- "matrix-react-sdk": "^0.0.1",
+ "matrix-js-sdk": "^0.3.0",
+ "matrix-react-sdk": "^0.0.2",
"q": "^1.4.1",
"react": "^0.13.3",
"react-loader": "^1.4.0"
diff --git a/src/Avatar.js b/src/Avatar.js
index 2f83ebd9..afc5e9dd 100644
--- a/src/Avatar.js
+++ b/src/Avatar.js
@@ -20,14 +20,17 @@ var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
module.exports = {
avatarUrlForMember: function(member, width, height, resizeMethod) {
- var url = MatrixClientPeg.get().getAvatarUrlForMember(
- member,
+ var url = member.getAvatarUrl(
+ MatrixClientPeg.get().getHomeserverUrl(),
width,
height,
resizeMethod
);
if (!url) {
- url = this.defaultAvatarUrlForString(member.userId);
+ // member can be null here currently since on invites, the JS SDK
+ // does not have enough info to build a RoomMember object for
+ // the inviter.
+ url = this.defaultAvatarUrlForString(member ? member.userId : '');
}
return url;
},
diff --git a/src/ContextualMenu.js b/src/ContextualMenu.js
index cdfff952..7865e45a 100644
--- a/src/ContextualMenu.js
+++ b/src/ContextualMenu.js
@@ -49,15 +49,25 @@ module.exports = {
var position = {
top: props.top - 20,
- right: props.right + 8,
};
+ var chevron = null;
+ if (props.left) {
+ chevron =
+ position.left = props.left + 8;
+ } else {
+ chevron =
+ position.right = props.right + 8;
+ }
+
+ var className = 'mx_ContextualMenu_wrapper';
+
// FIXME: If a menu uses getDefaultProps it clobbers the onFinished
// property set here so you can't close the menu from a button click!
var menu = (
-
+
-
+ {chevron}
diff --git a/src/controllers/molecules/voip/CallView.js b/src/controllers/molecules/voip/CallView.js
index d511b9d4..ab712148 100644
--- a/src/controllers/molecules/voip/CallView.js
+++ b/src/controllers/molecules/voip/CallView.js
@@ -74,8 +74,10 @@ module.exports = {
);
if (call) {
call.setLocalVideoElement(this.getVideoView().getLocalVideoElement());
- // N.B. the remote video element is used for playback for audio for voice calls
call.setRemoteVideoElement(this.getVideoView().getRemoteVideoElement());
+ // give a separate element for audio stream playback - both for voice calls
+ // and for the voice stream of screen captures
+ call.setRemoteAudioElement(this.getVideoView().getRemoteAudioElement());
}
if (call && call.type === "video" && call.state !== 'ended') {
// if this call is a conf call, don't display local video as the
@@ -88,6 +90,7 @@ module.exports = {
else {
this.getVideoView().getLocalVideoElement().style.display = "none";
this.getVideoView().getRemoteVideoElement().style.display = "none";
+ dis.dispatch({action: 'video_fullscreen', fullscreen: false});
}
}
};
diff --git a/src/controllers/organisms/RoomList.js b/src/controllers/organisms/RoomList.js
index 2602315a..151a6ca2 100644
--- a/src/controllers/organisms/RoomList.js
+++ b/src/controllers/organisms/RoomList.js
@@ -33,6 +33,8 @@ module.exports = {
cli.on("Room", this.onRoom);
cli.on("Room.timeline", this.onRoomTimeline);
cli.on("Room.name", this.onRoomName);
+ cli.on("RoomState.events", this.onRoomStateEvents);
+ cli.on("RoomMember.name", this.onRoomMemberName);
var rooms = this.getRoomList();
this.setState({
@@ -52,6 +54,11 @@ module.exports = {
case 'call_state':
this._recheckCallElement(this.props.selectedRoom);
break;
+ case 'view_tooltip':
+ this.tooltip = payload.tooltip;
+ this._repositionTooltip();
+ if (this.tooltip) this.tooltip.style.display = 'block';
+ break
}
},
@@ -61,6 +68,7 @@ module.exports = {
MatrixClientPeg.get().removeListener("Room", this.onRoom);
MatrixClientPeg.get().removeListener("Room.timeline", this.onRoomTimeline);
MatrixClientPeg.get().removeListener("Room.name", this.onRoomName);
+ MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents);
}
},
@@ -105,6 +113,15 @@ module.exports = {
this.refreshRoomList();
},
+ onRoomStateEvents: function(ev, state) {
+ setTimeout(this.refreshRoomList, 0);
+ },
+
+ onRoomMemberName: function(ev, member) {
+ setTimeout(this.refreshRoomList, 0);
+ },
+
+
refreshRoomList: function() {
var rooms = this.getRoomList();
this.setState({
@@ -150,6 +167,13 @@ module.exports = {
});
},
+ _repositionTooltip: function(e) {
+ if (this.tooltip && this.tooltip.parentElement) {
+ var scroll = this.getDOMNode();
+ this.tooltip.style.top = (scroll.parentElement.offsetTop + this.tooltip.parentElement.offsetTop - scroll.scrollTop) + "px";
+ }
+ },
+
makeRoomTiles: function() {
var self = this;
var RoomTile = sdk.getComponent("molecules.RoomTile");
@@ -159,6 +183,7 @@ module.exports = {
= 0 && count < this.state.messageCap; --i) {
+ var mxEv = this.state.room.timeline[i];
+
+ if (!EventTile.supportsEventType(mxEv.getType())) {
+ continue;
+ }
+
+ var continuation = false;
+ var last = false;
+ var dateSeparator = null;
+ if (i == this.state.room.timeline.length - 1) {
+ last = true;
+ }
+ if (i > 0 && count < this.state.messageCap - 1) {
+ if (this.state.room.timeline[i].sender &&
+ this.state.room.timeline[i - 1].sender &&
+ (this.state.room.timeline[i].sender.userId ===
+ this.state.room.timeline[i - 1].sender.userId) &&
+ (this.state.room.timeline[i].getType() ==
+ this.state.room.timeline[i - 1].getType())
+ )
+ {
+ continuation = true;
+ }
+
+ var ts0 = this.state.room.timeline[i - 1].getTs();
+ var ts1 = this.state.room.timeline[i].getTs();
+ if (new Date(ts0).toDateString() !== new Date(ts1).toDateString()) {
+ dateSeparator = ;
+ continuation = false;
+ }
+ }
+
+ if (i === 1) { // n.b. 1, not 0, as the 0th event is an m.room.create and so doesn't show on the timeline
+ var ts1 = this.state.room.timeline[i].getTs();
+ dateSeparator =
;
+ continuation = false;
+ }
+
+ ret.unshift(
+
+ );
+ if (dateSeparator) {
+ ret.unshift(dateSeparator);
+ }
+ ++count;
+ }
+ return ret;
+ },
+
+ uploadNewState: function(new_name, new_topic, new_join_rule, new_history_visibility, new_power_levels) {
+ var old_name = this.state.room.name;
+
+ var old_topic = this.state.room.currentState.getStateEvents('m.room.topic', '');
+ if (old_topic) {
+ old_topic = old_topic.getContent().topic;
+ } else {
+ old_topic = "";
+ }
+
+ var old_join_rule = this.state.room.currentState.getStateEvents('m.room.join_rules', '');
+ if (old_join_rule) {
+ old_join_rule = old_join_rule.getContent().join_rule;
+ } else {
+ old_join_rule = "invite";
+ }
+
+ var old_history_visibility = this.state.room.currentState.getStateEvents('m.room.history_visibility', '');
+ if (old_history_visibility) {
+ old_history_visibility = old_history_visibility.getContent().history_visibility;
+ } else {
+ old_history_visibility = "shared";
+ }
+
+ var deferreds = [];
+
+ if (old_name != new_name && new_name != undefined && new_name) {
+ deferreds.push(
+ MatrixClientPeg.get().setRoomName(this.state.room.roomId, new_name)
+ );
+ }
+
+ if (old_topic != new_topic && new_topic != undefined) {
+ deferreds.push(
+ MatrixClientPeg.get().setRoomTopic(this.state.room.roomId, new_topic)
+ );
+ }
+
+ if (old_join_rule != new_join_rule && new_join_rule != undefined) {
+ deferreds.push(
+ MatrixClientPeg.get().sendStateEvent(
+ this.state.room.roomId, "m.room.join_rules", {
+ join_rule: new_join_rule,
+ }, ""
+ )
+ );
+ }
+
+ if (old_history_visibility != new_history_visibility && new_history_visibility != undefined) {
+ deferreds.push(
+ MatrixClientPeg.get().sendStateEvent(
+ this.state.room.roomId, "m.room.history_visibility", {
+ history_visibility: new_history_visibility,
+ }, ""
+ )
+ );
+ }
+
+ if (new_power_levels) {
+ deferreds.push(
+ MatrixClientPeg.get().sendStateEvent(
+ this.state.room.roomId, "m.room.power_levels", new_power_levels, ""
+ )
+ );
+ }
+
+ if (deferreds.length) {
+ var self = this;
+ q.all(deferreds).fail(function(err) {
+ var ErrorDialog = sdk.getComponent("organisms.ErrorDialog");
+ Modal.createDialog(ErrorDialog, {
+ title: "Failed to set state",
+ description: err.toString()
+ });
+ }).finally(function() {
+ self.setState({
+ uploadingRoomSettings: false,
+ });
+ });
+ } else {
+ this.setState({
+ editingRoomSettings: false,
+ uploadingRoomSettings: false,
+ });
+ }
+ }
+};
diff --git a/src/controllers/templates/Register.js b/src/controllers/templates/Register.js
new file mode 100644
index 00000000..5f88d590
--- /dev/null
+++ b/src/controllers/templates/Register.js
@@ -0,0 +1,58 @@
+/*
+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 extend = require('matrix-react-sdk/lib/extend');
+var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
+var BaseRegisterController = require('matrix-react-sdk/lib/controllers/templates/Register.js');
+
+var RegisterController = {};
+extend(RegisterController, BaseRegisterController);
+
+RegisterController.onRegistered = function(user_id, access_token) {
+ MatrixClientPeg.replaceUsingAccessToken(
+ this.state.hs_url, this.state.is_url, user_id, access_token
+ );
+
+ this.setState({
+ step: 'profile',
+ busy: true
+ });
+
+ var self = this;
+ var cli = MatrixClientPeg.get();
+ cli.getProfileInfo(cli.credentials.userId).done(function(result) {
+ self.setState({
+ avatarUrl: result.avatar_url,
+ busy: false
+ });
+ },
+ function(err) {
+ console.err(err);
+ self.setState({
+ busy: false
+ });
+ });
+};
+
+RegisterController.onAccountReady = function() {
+ if (this.props.onLoggedIn) {
+ this.props.onLoggedIn();
+ }
+};
+
+module.exports = RegisterController;
diff --git a/src/skins/vector/css/common.css b/src/skins/vector/css/common.css
index 8afba88e..93012c0f 100644
--- a/src/skins/vector/css/common.css
+++ b/src/skins/vector/css/common.css
@@ -14,6 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
+html {
+ /* hack to stop overscroll bounce on OSX and iOS.
+ N.B. Breaks things when we have legitimate horizontal overscroll */
+ height: 100%;
+ overflow: hidden;
+}
+
body {
font-family: 'Lato', Helvetica, Arial, Sans-Serif;
font-size: 16px;
@@ -34,6 +41,12 @@ h2 {
margin-bottom: 16px;
}
+a:hover,
+a:link,
+a:visited {
+ color: #80CEF4;
+}
+
.mx_ContextualMenu_background {
position: fixed;
top: 0;
@@ -54,18 +67,29 @@ h2 {
padding: 6px;
}
-.mx_ContextualMenu_chevron {
+.mx_ContextualMenu_chevron_right {
padding: 12px;
position: absolute;
right: -21px;
top: 0px;
}
+.mx_ContextualMenu_chevron_left {
+ padding: 12px;
+ position: absolute;
+ left: -21px;
+ top: 0px;
+}
+
.mx_ContextualMenu_field {
padding: 3px 6px 3px 6px;
cursor: pointer;
}
+.mx_ContextualMenu_spinner {
+ display: block;
+ margin: 0 auto;
+}
.mx_Dialog_background {
position: fixed;
diff --git a/src/skins/vector/css/hide.css b/src/skins/vector/css/hide.css
index 381f9a18..fbc2db20 100644
--- a/src/skins/vector/css/hide.css
+++ b/src/skins/vector/css/hide.css
@@ -1,7 +1,6 @@
.mx_RoomDropTarget,
.mx_RoomList_favourites_label,
.mx_RoomList_archive_label,
-.mx_LeftPanel_hideButton,
.mx_RoomHeader_search,
.mx_RoomSettings_encrypt,
.mx_CreateRoom_encrypt,
diff --git a/src/skins/vector/css/molecules/MessageTile.css b/src/skins/vector/css/molecules/EventTile.css
similarity index 61%
rename from src/skins/vector/css/molecules/MessageTile.css
rename to src/skins/vector/css/molecules/EventTile.css
index 50a12c3a..1cd2fa46 100644
--- a/src/skins/vector/css/molecules/MessageTile.css
+++ b/src/skins/vector/css/molecules/EventTile.css
@@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-.mx_MessageTile {
+.mx_EventTile {
max-width: 100%;
clear: both;
margin-top: 32px;
margin-left: 56px;
}
-.mx_MessageTile_avatar {
+.mx_EventTile_avatar {
padding-left: 12px;
padding-right: 12px;
margin-left: -64px;
@@ -29,17 +29,17 @@ limitations under the License.
float: left;
}
-.mx_MessageTile_avatar img {
+.mx_EventTile_avatar img {
background-color: #dbdbdb;
border-radius: 20px;
border: 0px;
}
-.mx_MessageTile_continuation {
+.mx_EventTile_continuation {
margin-top: 8px ! important;
}
-.mx_MessageTile .mx_SenderProfile {
+.mx_EventTile .mx_SenderProfile {
color: #454545;
opacity: 0.5;
font-size: 14px;
@@ -47,35 +47,35 @@ limitations under the License.
display: block;
}
-.mx_MessageTile .mx_MessageTimestamp {
+.mx_EventTile .mx_MessageTimestamp {
color: #454545;
opacity: 0.5;
font-size: 14px;
float: right;
}
-.mx_MessageTile_content {
+.mx_EventTile_content {
padding-right: 100px;
display: block;
}
-.mx_MessageTile_notice .mx_MessageTile_content {
+.mx_EventTile_notice .mx_MessageTile_content {
opacity: 0.5;
}
-.mx_MessageTile_sending {
+.mx_EventTile_sending {
color: #ddd;
}
-.mx_MessageTile_notSent {
+.mx_EventTile_notSent {
color: #f11;
}
-.mx_MessageTile_highlight {
- color: #00f;
+.mx_EventTile_highlight {
+ color: #FF0064;
}
-.mx_MessageTile_msgOption {
+.mx_EventTile_msgOption {
float: right;
}
@@ -83,10 +83,30 @@ limitations under the License.
display: none;
}
-.mx_MessageTile_last .mx_MessageTimestamp {
+.mx_EventTile_last .mx_MessageTimestamp {
display: block;
}
-.mx_MessageTile:hover .mx_MessageTimestamp {
+.mx_EventTile:hover .mx_MessageTimestamp {
display: block;
}
+
+.mx_EventTile_editButton {
+ float: right;
+ display: none;
+ border: 0px;
+ outline: none;
+ margin-right: 3px;
+}
+
+.mx_EventTile:hover .mx_EventTile_editButton {
+ display: inline-block;
+}
+
+.mx_EventTile.menu .mx_EventTile_editButton {
+ display: inline-block;
+}
+
+.mx_EventTile.menu .mx_MessageTimestamp {
+ display: inline-block;
+}
diff --git a/src/skins/vector/css/molecules/MatrixToolbar.css b/src/skins/vector/css/molecules/MatrixToolbar.css
index 76845e4b..99c28240 100644
--- a/src/skins/vector/css/molecules/MatrixToolbar.css
+++ b/src/skins/vector/css/molecules/MatrixToolbar.css
@@ -15,7 +15,6 @@ limitations under the License.
*/
.mx_MatrixToolbar {
- width: 100%;
text-align: center;
background-color: #ff0064;
color: #fff;
diff --git a/src/skins/vector/css/molecules/MemberTile.css b/src/skins/vector/css/molecules/MemberTile.css
index a4310d20..faae142a 100644
--- a/src/skins/vector/css/molecules/MemberTile.css
+++ b/src/skins/vector/css/molecules/MemberTile.css
@@ -128,3 +128,7 @@ limitations under the License.
.mx_MemberTile_zalgo {
font-family: Helvetica, Arial, Sans-Serif;
}
+
+.mx_MemberTile:hover .mx_MessageTimestamp {
+ display: block;
+}
diff --git a/src/skins/vector/css/molecules/RoomHeader.css b/src/skins/vector/css/molecules/RoomHeader.css
index c0c8567d..f7adb618 100644
--- a/src/skins/vector/css/molecules/RoomHeader.css
+++ b/src/skins/vector/css/molecules/RoomHeader.css
@@ -116,13 +116,16 @@ limitations under the License.
margin-top: -5px;
}
-.mx_RoomHeader_nameInput {
+.mx_RoomHeader_name input, .mx_RoomHeader_nameInput {
border-radius: 3px;
width: 260px;
border: 1px solid #c7c7c7;
font-weight: 300;
font-size: 14px;
padding: 9px;
+}
+
+.mx_RoomHeader_nameInput {
margin-top: 6px;
}
@@ -160,3 +163,11 @@ limitations under the License.
.mx_RoomHeader_button img {
cursor: pointer;
}
+
+.mx_RoomHeader_voipButton {
+ display: table-cell;
+}
+
+.mx_RoomHeader_voipButtons {
+ margin-top: 18px;
+}
\ No newline at end of file
diff --git a/src/skins/vector/css/molecules/RoomTile.css b/src/skins/vector/css/molecules/RoomTile.css
index d43945c3..511fc94f 100644
--- a/src/skins/vector/css/molecules/RoomTile.css
+++ b/src/skins/vector/css/molecules/RoomTile.css
@@ -22,13 +22,13 @@ limitations under the License.
.mx_RoomTile_avatar {
display: table-cell;
- padding-right: 12px;
+ padding-right: 10px;
padding-top: 3px;
padding-bottom: 3px;
- padding-left: 16px;
+ padding-left: 10px;
vertical-align: middle;
- width: 40px;
- height: 40px;
+ width: 36px;
+ height: 36px;
position: relative;
}
@@ -45,6 +45,10 @@ limitations under the License.
padding-right: 16px;
}
+.collapsed .mx_RoomTile_name {
+ display: none;
+}
+
/*
.mx_RoomTile_nameBadge {
display: table;
diff --git a/src/controllers/atoms/ImageView.js b/src/skins/vector/css/molecules/RoomTooltip.css
similarity index 65%
rename from src/controllers/atoms/ImageView.js
rename to src/skins/vector/css/molecules/RoomTooltip.css
index d0977e00..f45970fe 100644
--- a/src/controllers/atoms/ImageView.js
+++ b/src/skins/vector/css/molecules/RoomTooltip.css
@@ -14,7 +14,20 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-'use strict';
+.mx_RoomTooltip {
+ display: none;
+ position: fixed;
+ border: 1px solid #a9dbf4;
+ border-radius: 8px;
+ background-color: #fff;
+ z-index: 1000;
+ margin-top: 6px;
+ left: 64px;
+ padding: 6px;
+}
-module.exports = {
-};
+.mx_RoomTooltip_chevron {
+ position: absolute;
+ left: -9px;
+ top: 8px;
+}
diff --git a/src/skins/vector/css/organisms/LeftPanel.css b/src/skins/vector/css/organisms/LeftPanel.css
index a00184dd..0e7e077e 100644
--- a/src/skins/vector/css/organisms/LeftPanel.css
+++ b/src/skins/vector/css/organisms/LeftPanel.css
@@ -29,7 +29,9 @@ limitations under the License.
.mx_LeftPanel_hideButton {
position: absolute;
top: 10px;
- right: 10px;
+ right: 0px;
+ padding: 8px;
+ cursor: pointer;
}
.mx_LeftPanel .mx_RoomList {
@@ -39,7 +41,7 @@ limitations under the License.
-webkit-order: 1;
order: 1;
- overflow-y: scroll;
+ overflow-y: auto;
-webkit-flex: 1 1 0;
flex: 1 1 0;
}
@@ -61,10 +63,6 @@ limitations under the License.
color: #378bb4;
}
-.mx_LeftPanel .mx_BottomLeftMenu .mx_RoomTile_avatar {
- padding-left: 14px;
-}
-
.mx_LeftPanel .mx_BottomLeftMenu .mx_BottomLeftMenu_options {
margin-top: 12px;
width: 100%;
diff --git a/src/skins/vector/css/organisms/RoomDirectory.css b/src/skins/vector/css/organisms/RoomDirectory.css
index 793ba5af..21985a25 100644
--- a/src/skins/vector/css/organisms/RoomDirectory.css
+++ b/src/skins/vector/css/organisms/RoomDirectory.css
@@ -57,7 +57,7 @@ limitations under the License.
}
.mx_RoomDirectory_tableWrapper {
- overflow-y: scroll;
+ overflow-y: auto;
-webkit-flex: 1 1 0;
flex: 1 1 0;
}
diff --git a/src/skins/vector/css/organisms/RoomList.css b/src/skins/vector/css/organisms/RoomList.css
index 35978e5b..21cb7812 100644
--- a/src/skins/vector/css/organisms/RoomList.css
+++ b/src/skins/vector/css/organisms/RoomList.css
@@ -27,4 +27,5 @@ limitations under the License.
.mx_RoomList h2 {
padding-left: 16px;
padding-right: 16px;
+ padding-bottom: 10px;
}
\ No newline at end of file
diff --git a/src/skins/vector/css/organisms/RoomView.css b/src/skins/vector/css/organisms/RoomView.css
index e1c589a2..2aab203a 100644
--- a/src/skins/vector/css/organisms/RoomView.css
+++ b/src/skins/vector/css/organisms/RoomView.css
@@ -106,10 +106,8 @@ limitations under the License.
flex: 1 1 0;
width: 100%;
- margin-top: 18px;
- margin-bottom: 18px;
- overflow-y: scroll;
+ overflow-y: auto;
}
.mx_RoomView_messageListWrapper {
@@ -123,6 +121,10 @@ limitations under the License.
padding: 0px;
}
+.mx_RoomView_MessageList li {
+ clear: both;
+}
+
.mx_RoomView_MessageList h2 {
clear: both;
margin-top: 32px;
@@ -210,13 +212,37 @@ limitations under the License.
.mx_RoomView_uploadProgressOuter {
width: 100%;
- background-color: black;
- height: 5px;
+ background-color: rgba(169, 219, 244, 0.5);
+ height: 4px;
}
.mx_RoomView_uploadProgressInner {
- background-color: blue;
- height: 5px;
+ background-color: #80cef4;
+ height: 4px;
+}
+
+.mx_RoomView_uploadFilename {
+ margin-top: 15px;
+ margin-left: 56px;
+}
+
+.mx_RoomView_uploadIcon {
+ float: left;
+ margin-top: 6px;
+ margin-left: 5px;
+}
+
+.mx_RoomView_uploadCancel {
+ float: right;
+ margin-top: 6px;
+ margin-right: 10px;
+}
+
+.mx_RoomView_uploadBytes {
+ float: right;
+ opacity: 0.5;
+ margin-top: 15px;
+ margin-right: 10px;
}
.mx_RoomView_ongoingConfCallNotification {
diff --git a/src/skins/vector/css/organisms/ViewSource.css b/src/skins/vector/css/organisms/ViewSource.css
new file mode 100644
index 00000000..ae61ae58
--- /dev/null
+++ b/src/skins/vector/css/organisms/ViewSource.css
@@ -0,0 +1,3 @@
+.mx_ViewSource pre {
+ text-align: left;
+}
diff --git a/src/skins/vector/css/pages/MatrixChat.css b/src/skins/vector/css/pages/MatrixChat.css
index 1c02d8cc..6fa0415a 100644
--- a/src/skins/vector/css/pages/MatrixChat.css
+++ b/src/skins/vector/css/pages/MatrixChat.css
@@ -73,6 +73,11 @@ limitations under the License.
flex: 0 0 230px;
}
+.mx_MatrixChat .mx_LeftPanel.collapsed {
+ -webkit-flex: 0 0 60px;
+ flex: 0 0 60px;
+}
+
.mx_MatrixChat .mx_MatrixChat_middlePanel {
-webkit-box-ordinal-group: 2;
-moz-box-ordinal-group: 2;
@@ -83,7 +88,9 @@ limitations under the License.
padding-left: 12px;
padding-right: 12px;
background-color: #f3f8fa;
- width: 100%;
+
+ -webkit-flex: 1;
+ flex: 1;
/* XXX: Hack: apparently if you try to nest a flex-box
* within a non-flex-box within a flex-box, the height
@@ -111,3 +118,8 @@ limitations under the License.
-webkit-flex: 0 0 230px;
flex: 0 0 230px;
}
+
+.mx_MatrixChat .mx_RightPanel.collapsed {
+ -webkit-flex: 0 0 72px;
+ flex: 0 0 72px;
+}
diff --git a/src/skins/vector/img/50e2c2.png b/src/skins/vector/img/50e2c2.png
new file mode 100644
index 00000000..ee0f8558
Binary files /dev/null and b/src/skins/vector/img/50e2c2.png differ
diff --git a/src/skins/vector/img/80cef4.png b/src/skins/vector/img/80cef4.png
new file mode 100644
index 00000000..637d03f6
Binary files /dev/null and b/src/skins/vector/img/80cef4.png differ
diff --git a/src/skins/vector/img/cancel.png b/src/skins/vector/img/cancel.png
new file mode 100644
index 00000000..c963a4b7
Binary files /dev/null and b/src/skins/vector/img/cancel.png differ
diff --git a/src/skins/vector/img/create-big.png b/src/skins/vector/img/create-big.png
index 9c4627b1..247b0030 100644
Binary files a/src/skins/vector/img/create-big.png and b/src/skins/vector/img/create-big.png differ
diff --git a/src/skins/vector/img/directory-big.png b/src/skins/vector/img/directory-big.png
index fb2bc388..bbcb16a4 100644
Binary files a/src/skins/vector/img/directory-big.png and b/src/skins/vector/img/directory-big.png differ
diff --git a/src/skins/vector/img/f4c371.png b/src/skins/vector/img/f4c371.png
new file mode 100644
index 00000000..ad3b8f16
Binary files /dev/null and b/src/skins/vector/img/f4c371.png differ
diff --git a/src/skins/vector/img/fileicon.png b/src/skins/vector/img/fileicon.png
new file mode 100644
index 00000000..be277a1c
Binary files /dev/null and b/src/skins/vector/img/fileicon.png differ
diff --git a/src/skins/vector/img/hide.png b/src/skins/vector/img/hide.png
index 3e64618b..c5aaf0dd 100644
Binary files a/src/skins/vector/img/hide.png and b/src/skins/vector/img/hide.png differ
diff --git a/src/skins/vector/img/menu.png b/src/skins/vector/img/menu.png
old mode 100644
new mode 100755
index 3550878b..b45f8895
Binary files a/src/skins/vector/img/menu.png and b/src/skins/vector/img/menu.png differ
diff --git a/src/skins/vector/img/settings-big.png b/src/skins/vector/img/settings-big.png
index 663ca163..3be13bc7 100644
Binary files a/src/skins/vector/img/settings-big.png and b/src/skins/vector/img/settings-big.png differ
diff --git a/src/skins/vector/img/spinner.gif b/src/skins/vector/img/spinner.gif
new file mode 100644
index 00000000..ab487121
Binary files /dev/null and b/src/skins/vector/img/spinner.gif differ
diff --git a/src/skins/vector/img/zoom.png b/src/skins/vector/img/zoom.png
new file mode 100644
index 00000000..f05ea959
Binary files /dev/null and b/src/skins/vector/img/zoom.png differ
diff --git a/src/skins/vector/skindex.js b/src/skins/vector/skindex.js
index 4f76ad62..8dba10cf 100644
--- a/src/skins/vector/skindex.js
+++ b/src/skins/vector/skindex.js
@@ -23,6 +23,9 @@ limitations under the License.
var skin = {};
+skin['atoms.create_room.CreateRoomButton'] = require('./views/atoms/create_room/CreateRoomButton');
+skin['atoms.create_room.Presets'] = require('./views/atoms/create_room/Presets');
+skin['atoms.create_room.RoomAlias'] = require('./views/atoms/create_room/RoomAlias');
skin['atoms.EditableText'] = require('./views/atoms/EditableText');
skin['atoms.EnableNotificationsButton'] = require('./views/atoms/EnableNotificationsButton');
skin['atoms.ImageView'] = require('./views/atoms/ImageView');
@@ -30,32 +33,34 @@ skin['atoms.LogoutButton'] = require('./views/atoms/LogoutButton');
skin['atoms.MemberAvatar'] = require('./views/atoms/MemberAvatar');
skin['atoms.MessageTimestamp'] = require('./views/atoms/MessageTimestamp');
skin['atoms.RoomAvatar'] = require('./views/atoms/RoomAvatar');
-skin['atoms.create_room.CreateRoomButton'] = require('./views/atoms/create_room/CreateRoomButton');
-skin['atoms.create_room.Presets'] = require('./views/atoms/create_room/Presets');
-skin['atoms.create_room.RoomAlias'] = require('./views/atoms/create_room/RoomAlias');
skin['atoms.voip.VideoFeed'] = require('./views/atoms/voip/VideoFeed');
skin['molecules.BottomLeftMenu'] = require('./views/molecules/BottomLeftMenu');
+skin['molecules.BottomLeftMenuTile'] = require('./views/molecules/BottomLeftMenuTile');
skin['molecules.ChangeAvatar'] = require('./views/molecules/ChangeAvatar');
+skin['molecules.ChangeDisplayName'] = require('./views/molecules/ChangeDisplayName');
skin['molecules.ChangePassword'] = require('./views/molecules/ChangePassword');
skin['molecules.DateSeparator'] = require('./views/molecules/DateSeparator');
skin['molecules.EventAsTextTile'] = require('./views/molecules/EventAsTextTile');
+skin['molecules.EventTile'] = require('./views/molecules/EventTile');
+skin['molecules.MatrixToolbar'] = require('./views/molecules/MatrixToolbar');
+skin['molecules.MemberInfo'] = require('./views/molecules/MemberInfo');
+skin['molecules.MemberTile'] = require('./views/molecules/MemberTile');
skin['molecules.MEmoteTile'] = require('./views/molecules/MEmoteTile');
+skin['molecules.MessageComposer'] = require('./views/molecules/MessageComposer');
+skin['molecules.MessageContextMenu'] = require('./views/molecules/MessageContextMenu');
+skin['molecules.MessageTile'] = require('./views/molecules/MessageTile');
skin['molecules.MFileTile'] = require('./views/molecules/MFileTile');
skin['molecules.MImageTile'] = require('./views/molecules/MImageTile');
skin['molecules.MNoticeTile'] = require('./views/molecules/MNoticeTile');
skin['molecules.MRoomMemberTile'] = require('./views/molecules/MRoomMemberTile');
skin['molecules.MTextTile'] = require('./views/molecules/MTextTile');
-skin['molecules.MatrixToolbar'] = require('./views/molecules/MatrixToolbar');
-skin['molecules.MemberInfo'] = require('./views/molecules/MemberInfo');
-skin['molecules.MemberTile'] = require('./views/molecules/MemberTile');
-skin['molecules.MessageComposer'] = require('./views/molecules/MessageComposer');
-skin['molecules.MessageTile'] = require('./views/molecules/MessageTile');
skin['molecules.ProgressBar'] = require('./views/molecules/ProgressBar');
skin['molecules.RoomCreate'] = require('./views/molecules/RoomCreate');
skin['molecules.RoomDropTarget'] = require('./views/molecules/RoomDropTarget');
skin['molecules.RoomHeader'] = require('./views/molecules/RoomHeader');
skin['molecules.RoomSettings'] = require('./views/molecules/RoomSettings');
skin['molecules.RoomTile'] = require('./views/molecules/RoomTile');
+skin['molecules.RoomTooltip'] = require('./views/molecules/RoomTooltip');
skin['molecules.SenderProfile'] = require('./views/molecules/SenderProfile');
skin['molecules.ServerConfig'] = require('./views/molecules/ServerConfig');
skin['molecules.UnknownMessageTile'] = require('./views/molecules/UnknownMessageTile');
@@ -63,6 +68,7 @@ skin['molecules.UserSelector'] = require('./views/molecules/UserSelector');
skin['molecules.voip.CallView'] = require('./views/molecules/voip/CallView');
skin['molecules.voip.IncomingCallBox'] = require('./views/molecules/voip/IncomingCallBox');
skin['molecules.voip.VideoView'] = require('./views/molecules/voip/VideoView');
+skin['organisms.CasLogin'] = require('./views/organisms/CasLogin');
skin['organisms.CreateRoom'] = require('./views/organisms/CreateRoom');
skin['organisms.ErrorDialog'] = require('./views/organisms/ErrorDialog');
skin['organisms.LeftPanel'] = require('./views/organisms/LeftPanel');
@@ -75,6 +81,7 @@ skin['organisms.RoomDirectory'] = require('./views/organisms/RoomDirectory');
skin['organisms.RoomList'] = require('./views/organisms/RoomList');
skin['organisms.RoomView'] = require('./views/organisms/RoomView');
skin['organisms.UserSettings'] = require('./views/organisms/UserSettings');
+skin['organisms.ViewSource'] = require('./views/organisms/ViewSource');
skin['pages.MatrixChat'] = require('./views/pages/MatrixChat');
skin['templates.Login'] = require('./views/templates/Login');
skin['templates.Register'] = require('./views/templates/Register');
diff --git a/src/skins/vector/views/atoms/ImageView.js b/src/skins/vector/views/atoms/ImageView.js
index a0d69bcc..676348c0 100644
--- a/src/skins/vector/views/atoms/ImageView.js
+++ b/src/skins/vector/views/atoms/ImageView.js
@@ -18,11 +18,8 @@ limitations under the License.
var React = require('react');
-var ImageViewController = require('../../../../controllers/atoms/ImageView')
-
module.exports = React.createClass({
displayName: 'ImageView',
- mixins: [ImageViewController],
// XXX: keyboard shortcuts for managing dialogs should be done by the modal dialog base class omehow, surely...
componentDidMount: function() {
diff --git a/src/skins/vector/views/atoms/MessageTimestamp.js b/src/skins/vector/views/atoms/MessageTimestamp.js
index ef866afa..98cfe4a1 100644
--- a/src/skins/vector/views/atoms/MessageTimestamp.js
+++ b/src/skins/vector/views/atoms/MessageTimestamp.js
@@ -18,17 +18,39 @@ limitations under the License.
var React = require('react');
-var MessageTimestampController = require('matrix-react-sdk/lib/controllers/atoms/MessageTimestamp')
+var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
+var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
module.exports = React.createClass({
displayName: 'MessageTimestamp',
- mixins: [MessageTimestampController],
+
+ formatDate: function(date) {
+ // date.toLocaleTimeString is completely system dependent.
+ // just go 24h for now
+ function pad(n) {
+ return (n < 10 ? '0' : '') + n;
+ }
+
+ var now = new Date();
+ if (date.toDateString() === now.toDateString()) {
+ return pad(date.getHours()) + ':' + pad(date.getMinutes());
+ }
+ else if (now.getTime() - date.getTime() < 6 * 24 * 60 * 60 * 1000) {
+ return days[date.getDay()] + " " + pad(date.getHours()) + ':' + pad(date.getMinutes());
+ }
+ else if (now.getFullYear() === date.getFullYear()) {
+ return days[date.getDay()] + ", " + months[date.getMonth()] + " " + (date.getDay()+1) + " " + pad(date.getHours()) + ':' + pad(date.getMinutes());
+ }
+ else {
+ return days[date.getDay()] + ", " + months[date.getMonth()] + " " + (date.getDay()+1) + " " + date.getFullYear() + " " + pad(date.getHours()) + ':' + pad(date.getMinutes());
+ }
+ },
render: function() {
var date = new Date(this.props.ts);
return (
- {date.toLocaleTimeString()}
+ { this.formatDate(date) }
);
},
diff --git a/src/skins/vector/views/atoms/RoomAvatar.js b/src/skins/vector/views/atoms/RoomAvatar.js
index ec2bf5ec..3b5d4634 100644
--- a/src/skins/vector/views/atoms/RoomAvatar.js
+++ b/src/skins/vector/views/atoms/RoomAvatar.js
@@ -24,10 +24,31 @@ module.exports = React.createClass({
displayName: 'RoomAvatar',
mixins: [RoomAvatarController],
+ getUrlList: function() {
+ return [
+ this.roomAvatarUrl(),
+ this.getOneToOneAvatar(),
+ this.getFallbackAvatar()
+ ];
+ },
+
+ getFallbackAvatar: function() {
+ var images = [ '80cef4', '50e2c2', 'f4c371' ];
+ var total = 0;
+ for (var i = 0; i < this.props.room.roomId.length; ++i) {
+ total += this.props.room.roomId.charCodeAt(i);
+ }
+ return 'img/' + images[total % images.length] + '.png';
+ },
+
render: function() {
+ var style = {
+ maxWidth: this.props.width,
+ maxHeight: this.props.height,
+ };
return (
);
}
diff --git a/src/skins/vector/views/atoms/Spinner.js b/src/skins/vector/views/atoms/Spinner.js
new file mode 100644
index 00000000..908f2678
--- /dev/null
+++ b/src/skins/vector/views/atoms/Spinner.js
@@ -0,0 +1,34 @@
+/*
+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');
+
+module.exports = React.createClass({
+ displayName: 'Spinner',
+
+ render: function() {
+ var w = this.props.w || 32;
+ var h = this.props.h || 32;
+ var imgClass = this.props.imgClassName || "";
+ return (
+
+ }
+ else if (this.state.hover) {
+ var RoomTooltip = sdk.getComponent("molecules.RoomTooltip");
+ return ;
+ }
+ },
+
render: function() {
+ var BottomLeftMenuTile = sdk.getComponent('molecules.BottomLeftMenuTile');
return (
-
-
-
-
-
Create new room
-
-
-
-
-
-
Directory
-
-
-
-
-
-
Settings
-
+
+
+
);
diff --git a/src/skins/vector/views/molecules/BottomLeftMenuTile.js b/src/skins/vector/views/molecules/BottomLeftMenuTile.js
new file mode 100644
index 00000000..2644769c
--- /dev/null
+++ b/src/skins/vector/views/molecules/BottomLeftMenuTile.js
@@ -0,0 +1,57 @@
+/*
+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 sdk = require('matrix-react-sdk')
+
+module.exports = React.createClass({
+ displayName: 'BottomLeftMenuTile',
+
+ getInitialState: function() {
+ return( { hover : false });
+ },
+
+ onMouseEnter: function() {
+ this.setState( { hover : true });
+ },
+
+ onMouseLeave: function() {
+ this.setState( { hover : false });
+ },
+
+ render: function() {
+ var label;
+ if (!this.props.collapsed) {
+ label =
+ );
+ }
+});
diff --git a/src/skins/vector/views/molecules/ChangeAvatar.js b/src/skins/vector/views/molecules/ChangeAvatar.js
index 8fafacc8..42c2d1fd 100644
--- a/src/skins/vector/views/molecules/ChangeAvatar.js
+++ b/src/skins/vector/views/molecules/ChangeAvatar.js
@@ -18,6 +18,7 @@ limitations under the License.
var React = require('react');
+var sdk = require('matrix-react-sdk')
var ChangeAvatarController = require('matrix-react-sdk/lib/controllers/molecules/ChangeAvatar')
var Loader = require("react-loader");
@@ -28,6 +29,7 @@ module.exports = React.createClass({
mixins: [ChangeAvatarController],
onFileSelected: function(ev) {
+ this.avatarSet = true;
this.setAvatarFromFile(ev.target.files[0]);
},
@@ -38,22 +40,33 @@ module.exports = React.createClass({
},
render: function() {
+ var RoomAvatar = sdk.getComponent('atoms.RoomAvatar');
+ var avatarImg;
+ // Having just set an avatar we just display that since it will take a little
+ // time to propagate through to the RoomAvatar.
+ if (this.props.room && !this.avatarSet) {
+ avatarImg = ;
+ } else {
+ var style = {
+ maxWidth: 320,
+ maxHeight: 240,
+ };
+ avatarImg = ;
+ }
+
switch (this.state.phase) {
case this.Phases.Display:
case this.Phases.Error:
return (
-
+ {avatarImg}
Upload new:
{this.state.errorText}
-
-
-
);
case this.Phases.Uploading:
diff --git a/src/skins/vector/views/molecules/ChangeDisplayName.js b/src/skins/vector/views/molecules/ChangeDisplayName.js
new file mode 100644
index 00000000..1a094ec2
--- /dev/null
+++ b/src/skins/vector/views/molecules/ChangeDisplayName.js
@@ -0,0 +1,56 @@
+/*
+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 sdk = require('matrix-react-sdk');
+
+var ChangeDisplayNameController = require("matrix-react-sdk/lib/controllers/molecules/ChangeDisplayName");
+var Loader = require("react-loader");
+
+
+module.exports = React.createClass({
+ displayName: 'ChangeDisplayName',
+ mixins: [ChangeDisplayNameController],
+
+ edit: function() {
+ this.refs.displayname_edit.edit()
+ },
+
+ onValueChanged: function(new_value, shouldSubmit) {
+ if (shouldSubmit) {
+ this.changeDisplayname(new_value);
+ }
+ },
+
+ render: function() {
+ if (this.state.busy) {
+ return (
+
+ );
+ } else if (this.state.errorString) {
+ return (
+
{this.state.errorString}
+ );
+ } else {
+ var EditableText = sdk.getComponent('atoms.EditableText');
+ return (
+
+ );
+ }
+ }
+});
diff --git a/src/skins/vector/views/molecules/EventAsTextTile.js b/src/skins/vector/views/molecules/EventAsTextTile.js
index e8beddf2..ec644a4e 100644
--- a/src/skins/vector/views/molecules/EventAsTextTile.js
+++ b/src/skins/vector/views/molecules/EventAsTextTile.js
@@ -18,33 +18,24 @@ limitations under the License.
var React = require('react');
-var EventAsTextTileController = require('matrix-react-sdk/lib/controllers/molecules/EventAsTextTile')
-var sdk = require('matrix-react-sdk')
var TextForEvent = require('matrix-react-sdk/lib/TextForEvent');
module.exports = React.createClass({
displayName: 'EventAsTextTile',
- mixins: [EventAsTextTileController],
+
+ statics: {
+ needsSenderProfile: function() {
+ return false;
+ }
+ },
render: function() {
- var MessageTimestamp = sdk.getComponent('atoms.MessageTimestamp');
- var MemberAvatar = sdk.getComponent('atoms.MemberAvatar');
-
var text = TextForEvent.textForEvent(this.props.mxEvent);
if (text == null || text.length == 0) return null;
- var timestamp = this.props.last ? : null;
- var avatar = this.props.mxEvent.sender ? : null;
return (
-
;
}
*/
+
+ var label;
+ if (!this.props.collapsed) {
+ label =
{name}
;
+ }
+ else if (this.state.hover) {
+ var RoomTooltip = sdk.getComponent("molecules.RoomTooltip");
+ label = ;
+ }
+
var RoomAvatar = sdk.getComponent('atoms.RoomAvatar');
return (
-
+
{ badge }
-
{name}
+ { label }
);
}
diff --git a/src/skins/vector/views/molecules/RoomTooltip.js b/src/skins/vector/views/molecules/RoomTooltip.js
new file mode 100644
index 00000000..82e3e744
--- /dev/null
+++ b/src/skins/vector/views/molecules/RoomTooltip.js
@@ -0,0 +1,59 @@
+/*
+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 dis = require('matrix-react-sdk/lib/dispatcher');
+
+module.exports = React.createClass({
+ displayName: 'RoomTooltip',
+
+ componentDidMount: function() {
+ if (!this.props.bottom) {
+ // tell the roomlist about us so it can position us
+ dis.dispatch({
+ action: 'view_tooltip',
+ tooltip: this.getDOMNode(),
+ });
+ }
+ else {
+ var tooltip = this.getDOMNode();
+ tooltip.style.top = tooltip.parentElement.getBoundingClientRect().top + "px";
+ tooltip.style.display = "block";
+ }
+ },
+
+ componentDidUnmount: function() {
+ if (!this.props.bottom) {
+ dis.dispatch({
+ action: 'view_tooltip',
+ tooltip: null,
+ });
+ }
+ },
+
+ render: function() {
+ var label = this.props.room ? this.props.room.name : this.props.label;
+ return (
+
+
+ { label }
+
+ );
+ }
+});
diff --git a/src/skins/vector/views/molecules/SenderProfile.js b/src/skins/vector/views/molecules/SenderProfile.js
index 8be3adf2..c09685aa 100644
--- a/src/skins/vector/views/molecules/SenderProfile.js
+++ b/src/skins/vector/views/molecules/SenderProfile.js
@@ -19,15 +19,12 @@ limitations under the License.
var React = require('react');
var classNames = require("classnames");
-var SenderProfileController = require('matrix-react-sdk/lib/controllers/molecules/SenderProfile')
-
// The Lato WOFF doesn't include sensible combining diacritics, so Chrome chokes on rendering them.
// Revert to Arial when this happens, which on OSX works at least.
var zalgo = /[\u0300-\u036f\u1ab0-\u1aff\u1dc0-\u1dff\u20d0-\u20ff\ufe20-\ufe2f]/;
module.exports = React.createClass({
displayName: 'SenderProfile',
- mixins: [SenderProfileController],
render: function() {
var mxEvent = this.props.mxEvent;
diff --git a/src/skins/vector/views/molecules/UnknownMessageTile.js b/src/skins/vector/views/molecules/UnknownMessageTile.js
index d5a20c87..e8cd322a 100644
--- a/src/skins/vector/views/molecules/UnknownMessageTile.js
+++ b/src/skins/vector/views/molecules/UnknownMessageTile.js
@@ -18,11 +18,8 @@ limitations under the License.
var React = require('react');
-var UnknownMessageTileController = require('matrix-react-sdk/lib/controllers/molecules/UnknownMessageTile')
-
module.exports = React.createClass({
displayName: 'UnknownMessageTile',
- mixins: [UnknownMessageTileController],
render: function() {
var content = this.props.mxEvent.getContent();
diff --git a/src/skins/vector/views/molecules/voip/IncomingCallBox.js b/src/skins/vector/views/molecules/voip/IncomingCallBox.js
index ee437f0a..c3bcd825 100644
--- a/src/skins/vector/views/molecules/voip/IncomingCallBox.js
+++ b/src/skins/vector/views/molecules/voip/IncomingCallBox.js
@@ -31,24 +31,28 @@ module.exports = React.createClass({
},
render: function() {
+
+ // NB: This block MUST have a "key" so React doesn't clobber the elements
+ // between in-call / not-in-call.
+ var audioBlock = (
+
+ );
+
if (!this.state.incomingCall || !this.state.incomingCall.roomId) {
return (
-
+ {audioBlock}
);
}
var caller = MatrixClientPeg.get().getRoom(this.state.incomingCall.roomId).name;
return (
diff --git a/src/skins/vector/views/organisms/CasLogin.js b/src/skins/vector/views/organisms/CasLogin.js
new file mode 100644
index 00000000..ad9dbed9
--- /dev/null
+++ b/src/skins/vector/views/organisms/CasLogin.js
@@ -0,0 +1,35 @@
+/*
+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 CasLoginController = require('matrix-react-sdk/lib/controllers/organisms/CasLogin');
+
+module.exports = React.createClass({
+ displayName: 'CasLogin',
+ mixins: [CasLoginController],
+
+ render: function() {
+ return (
+
+
+
+ );
+ },
+
+});
diff --git a/src/skins/vector/views/organisms/LeftPanel.js b/src/skins/vector/views/organisms/LeftPanel.js
index 15612704..a57f7a0a 100644
--- a/src/skins/vector/views/organisms/LeftPanel.js
+++ b/src/skins/vector/views/organisms/LeftPanel.js
@@ -18,21 +18,37 @@ limitations under the License.
var React = require('react');
var sdk = require('matrix-react-sdk')
+var dis = require('matrix-react-sdk/lib/dispatcher');
module.exports = React.createClass({
displayName: 'LeftPanel',
+ onHideClick: function() {
+ dis.dispatch({
+ action: 'hide_left_panel',
+ });
+ },
+
render: function() {
var RoomList = sdk.getComponent('organisms.RoomList');
var BottomLeftMenu = sdk.getComponent('molecules.BottomLeftMenu');
var IncomingCallBox = sdk.getComponent('molecules.voip.IncomingCallBox');
+ var collapseButton;
+ var classes = "mx_LeftPanel";
+ if (this.props.collapsed) {
+ classes += " collapsed";
+ }
+ else {
+ collapseButton =
+ }
+
return (
-