Compare commits
3 Commits
healthdemo
...
verto
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4d83f644a | ||
|
|
6fc0498a57 | ||
|
|
05201e7d34 |
@@ -1,9 +0,0 @@
|
||||
Vector is written mainly by the Vector team, building upon the Matrix React
|
||||
SDK. Vector also welcomes external contributions. Third party contributors
|
||||
include:
|
||||
|
||||
* Nolan Darilek (https://github.com/ndarilek)
|
||||
Accessibility and semantic markup contributions
|
||||
|
||||
* https://github.com/neko259
|
||||
Improved scrollbar CSS
|
||||
20
CHANGES.rst
20
CHANGES.rst
@@ -1,20 +0,0 @@
|
||||
Changes in vector v0.1.1 (2015-08-10)
|
||||
======================================
|
||||
|
||||
* Support logging in with an email address
|
||||
* Use the Vector identity server
|
||||
* Fix a bug where the client was not stopped properly on logout
|
||||
* Fix bugs where field values would be forgotten if login or registration failed
|
||||
* Improve URL bar navigation
|
||||
* Add explanatory help text on advanced server options
|
||||
* Fix a bug which caused execptions on malformed VoIP invitations
|
||||
* Remove superfluous scrollbars on Firefox
|
||||
* Numerous CSS fixes
|
||||
* Improved accessibility
|
||||
* Support command-click / middle click to open image in a new tab
|
||||
* Improved room directory
|
||||
* Fix display of text with many combining unicode points
|
||||
|
||||
Changes in vector v0.1.0 (2015-08-10)
|
||||
======================================
|
||||
Initial release
|
||||
@@ -1,4 +0,0 @@
|
||||
Contributing code to Vector
|
||||
===========================
|
||||
|
||||
Vector follows the same pattern as https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.rst
|
||||
@@ -24,8 +24,6 @@ var React = require("react");
|
||||
// maps cannot pass through two stages).
|
||||
var MatrixReactSdk = require("../../src/index");
|
||||
|
||||
var lastLocationHashSet = null;
|
||||
|
||||
// Here, we do some crude URL analysis to allow
|
||||
// deep-linking. We only support registration
|
||||
// deep-links in this example.
|
||||
@@ -48,10 +46,6 @@ function routeUrl(location) {
|
||||
}
|
||||
|
||||
function onHashChange(ev) {
|
||||
if (decodeURIComponent(window.location.hash) == lastLocationHashSet) {
|
||||
// we just set this: no need to route it!
|
||||
return;
|
||||
}
|
||||
routeUrl(window.location);
|
||||
}
|
||||
|
||||
@@ -61,9 +55,7 @@ var loaded = false;
|
||||
// so a web page can update the URL bar appropriately.
|
||||
var onNewScreen = function(screen) {
|
||||
if (!loaded) return;
|
||||
var hash = '#/' + screen;
|
||||
lastLocationHashSet = hash;
|
||||
window.location.hash = hash;
|
||||
window.location.hash = '#/'+screen;
|
||||
}
|
||||
|
||||
// We use this to work out what URL the SDK should
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"browserify": "^10.2.3",
|
||||
"envify": "^3.4.0",
|
||||
"http-server": "^0.8.0",
|
||||
"matrix-react-sdk": "../../",
|
||||
"parallelshell": "^1.2.0",
|
||||
@@ -18,7 +19,7 @@
|
||||
"watchify": "^3.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production browserify --ignore olm -t reactify index.js | uglifyjs -c -m -o bundle.js",
|
||||
"build": "browserify --ignore olm -t [ envify --NODE_ENV production ] -t reactify index.js | uglifyjs -c -m -o bundle.js",
|
||||
"start": "parallelshell \"watchify --ignore olm -v -d -t reactify index.js -o bundle.js\" \"http-server\""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"classnames": "^2.1.2",
|
||||
"filesize": "^3.1.2",
|
||||
"flux": "^2.0.3",
|
||||
"matrix-js-sdk": "git://github.com/matrix-org/matrix-js-sdk.git#develop",
|
||||
"matrix-js-sdk": "git://github.com/matrix-org/matrix-js-sdk.git#no-trickle-ice",
|
||||
"q": "^1.4.1",
|
||||
"react": "^0.13.3",
|
||||
"react-loader": "^1.4.0",
|
||||
|
||||
@@ -14,24 +14,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_MImageTile_thumbnail {
|
||||
/*
|
||||
background-color: #fff;
|
||||
border: 2px solid #fff;
|
||||
border-radius: 1px;
|
||||
*/
|
||||
.mx_MImageTile {
|
||||
}
|
||||
|
||||
.mx_MImageTile_download {
|
||||
color: #80cef4;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_MImageTile_download a {
|
||||
color: #80cef4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mx_MImageTile_download img {
|
||||
padding-right: 8px;
|
||||
}
|
||||
@@ -25,11 +25,4 @@ limitations under the License.
|
||||
|
||||
.mx_MatrixToolbar button {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.mx_MatrixToolbar_close {
|
||||
float: right;
|
||||
margin-top: 3px;
|
||||
margin-right: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -31,6 +31,12 @@ limitations under the License.
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_MemberTile_avatarImg {
|
||||
z-index: 20;
|
||||
border-radius: 20px;
|
||||
background-color: #dbdbdb;
|
||||
}
|
||||
|
||||
.mx_MemberTile_inviteEditing {
|
||||
display: initial ! important;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ limitations under the License.
|
||||
-webkit-order: 1;
|
||||
order: 1;
|
||||
|
||||
-webkit-flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@@ -60,15 +59,9 @@ limitations under the License.
|
||||
-webkit-order: 2;
|
||||
order: 2;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
/*
|
||||
-webkit-flex: 0 0 90px;
|
||||
flex: 0 0 90px;
|
||||
*/
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_RoomHeader_rightRow {
|
||||
height: 48px;
|
||||
@@ -95,7 +88,7 @@ limitations under the License.
|
||||
color: #80cef4;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
overflow: hidden;
|
||||
overflow: scroll;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@@ -134,8 +127,7 @@ limitations under the License.
|
||||
font-weight: 300;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.mx_RoomHeader_avatar {
|
||||
|
||||
@@ -40,7 +40,6 @@ limitations under the License.
|
||||
order: 1;
|
||||
|
||||
overflow-y: scroll;
|
||||
-webkit-flex: 1 1 0;
|
||||
flex: 1 1 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,13 +40,12 @@ limitations under the License.
|
||||
|
||||
.mx_MemberList_border {
|
||||
border: 1px solid #a9dbf4;
|
||||
overflow-y: auto;
|
||||
overflow-y: scroll;
|
||||
border-radius: 8px;
|
||||
padding: 20px 14px 14px 24px;
|
||||
background-color: #fff;
|
||||
|
||||
order: 1;
|
||||
-webkit-flex: 1 1 0;
|
||||
flex: 1 1 0px;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ limitations under the License.
|
||||
}
|
||||
|
||||
.mx_RoomDirectory_list {
|
||||
-webkit-flex: 1;
|
||||
flex: 1;
|
||||
|
||||
display: -webkit-box;
|
||||
@@ -58,7 +57,6 @@ limitations under the License.
|
||||
|
||||
.mx_RoomDirectory_tableWrapper {
|
||||
overflow-y: scroll;
|
||||
-webkit-flex: 1 1 0;
|
||||
flex: 1 1 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,42 +40,6 @@ limitations under the License.
|
||||
flex: 0 0 88px;
|
||||
}
|
||||
|
||||
.mx_RoomView_fileDropTarget {
|
||||
min-width: 0px;
|
||||
max-width: 720px;
|
||||
width: 100%;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
|
||||
pointer-events: none;
|
||||
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
margin-left: -12px;
|
||||
|
||||
-webkit-border-top-left-radius: 10px;
|
||||
-webkit-border-top-right-radius: 10px;
|
||||
-moz-border-radius-topleft: 10px;
|
||||
-moz-border-radius-topright: 10px;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
border: 2px dashed #80cef4;
|
||||
border-bottom: none;
|
||||
position: absolute;
|
||||
top: 88px;
|
||||
bottom: 0px;
|
||||
z-index: 3000;
|
||||
}
|
||||
|
||||
.mx_RoomView_fileDropTargetLabel {
|
||||
top: 50%;
|
||||
width: 100%;
|
||||
margin-top: -50px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.mx_RoomView_auxPanel {
|
||||
-webkit-box-ordinal-group: 2;
|
||||
-moz-box-ordinal-group: 2;
|
||||
@@ -88,9 +52,9 @@ limitations under the License.
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
|
||||
overflow: auto;
|
||||
border-bottom: 1px solid #a8dbf3;
|
||||
|
||||
overflow: scroll;
|
||||
-webkit-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
@@ -119,8 +83,6 @@ limitations under the License.
|
||||
|
||||
.mx_RoomView_MessageList {
|
||||
width: 100%;
|
||||
list-style-type: none;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.mx_RoomView_MessageList h2 {
|
||||
@@ -165,22 +127,6 @@ limitations under the License.
|
||||
border-top: 1px solid #a8dbf3;
|
||||
}
|
||||
|
||||
.mx_RoomView_unreadMessagesBar {
|
||||
margin-top: 13px;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
background-color: #ff0064;
|
||||
border-radius: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_RoomView_unreadMessagesBar img {
|
||||
padding-left: 22px;
|
||||
padding-right: 22px;
|
||||
}
|
||||
|
||||
.mx_RoomView_typingBar {
|
||||
margin-top: 17px;
|
||||
margin-left: 56px;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 213 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -24,23 +24,6 @@ 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() {
|
||||
document.addEventListener("keydown", this.onKeyDown);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
document.removeEventListener("keydown", this.onKeyDown);
|
||||
},
|
||||
|
||||
onKeyDown: function(ev) {
|
||||
if (ev.keyCode == 27) { // escape
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
this.props.onFinished();
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
|
||||
// XXX: can't we just do max-width: 80%, max-height: 80% on the CSS?
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
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 MemberAvatarController = require("../../../../src/controllers/atoms/MemberAvatar");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MemberAvatar',
|
||||
mixins: [MemberAvatarController],
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<img className="mx_MemberAvatar" src={this.state.imageUrl}
|
||||
onError={this.onError}
|
||||
width={this.props.width} height={this.props.height} />
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -22,7 +22,6 @@ var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
|
||||
var EventAsTextTileController = require("../../../../src/controllers/molecules/EventAsTextTile");
|
||||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
var MessageTimestamp = ComponentBroker.get('atoms/MessageTimestamp');
|
||||
var MemberAvatar = ComponentBroker.get('atoms/MemberAvatar');
|
||||
var TextForEvent = require("../../../../src/TextForEvent");
|
||||
|
||||
module.exports = React.createClass({
|
||||
@@ -31,14 +30,11 @@ module.exports = React.createClass({
|
||||
|
||||
render: function() {
|
||||
var text = TextForEvent.textForEvent(this.props.mxEvent);
|
||||
if (text == null || text.length == 0) return null;
|
||||
|
||||
var timestamp = this.props.last ? <MessageTimestamp ts={this.props.mxEvent.getTs()} /> : null;
|
||||
var avatar = this.props.mxEvent.sender ? <MemberAvatar member={this.props.mxEvent.sender} /> : null;
|
||||
return (
|
||||
<div className="mx_MessageTile mx_MessageTile_notice">
|
||||
<div className="mx_MessageTile_avatar">
|
||||
{ avatar }
|
||||
<img src={ this.props.mxEvent.sender ? MatrixClientPeg.get().getAvatarUrlForMember(this.props.mxEvent.sender, 40, 40, "crop") : null } width="40" height="40" alt=""/>
|
||||
</div>
|
||||
{ timestamp }
|
||||
<span className="mx_SenderProfile"></span>
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
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 HealthDemoTileController = require("../../../../src/controllers/molecules/HealthDemoTile");
|
||||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
var MessageTimestamp = ComponentBroker.get('atoms/MessageTimestamp');
|
||||
var MemberAvatar = ComponentBroker.get('atoms/MemberAvatar');
|
||||
var TextForEvent = require("../../../../src/TextForEvent");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'HealthDemoTile',
|
||||
mixins: [HealthDemoTileController],
|
||||
|
||||
render: function() {
|
||||
var ts = this.props.mxEvent.getContent().ts;
|
||||
var date = new Date(ts*1000);
|
||||
var timeStr = date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
|
||||
//var timestamp = <MessageTimestamp ts={this.props.mxEvent.getContent().ts} />;
|
||||
|
||||
var imgStyle = { float: 'left' };
|
||||
|
||||
return (
|
||||
<div className="mx_HealthDemoTile">
|
||||
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wgSDys3IE3P1AAAA2lJREFUWMPNmMuLFUcUxn+n03ONzkRNxOhERQQfgxhXBhNiFB+ICxdZCSJkJbVS0LUIbgyBgLMQRAr8N1xIRCVmsogSETQZBYOPGZPAEIcRR8c7HjenoWyqr/dO9SX3QN/ue+r19VffOVXVkGBepC1fikkNAAX4BpgPXHOqL+sEmKU0dqoAB4BLwEXgZN0sZjX0cRCYZ30doWbLatDf2sC90IssNWb/X4ABiHWloq97RoNe5EOgUXJv6xmApekt7Ks6AyUV4PqIb0NJAj3HYJ8X2VhX4k4FuC7iawCbCnAFkwXQTgFniSkmBrAP2BzUHfAiV4EXXuSYU+0IZJaYYtZEij8otBmsNDtsKRz2Iis7AZmSqHNgoKL4My/ysT3vKpWd7SSIUjS4ytiK2TJgeQXAvV7ky3b1mAJwZQngX0DTnpcDS71IPzBYarcAONoui6kAc3ueBa4DM/Z/APg0wl5hO73IF+0EY5YQwSsCBqcM4OtSjtxT0c2gBc97gzH3ImJpYSfwpsUmVoCfnerNCINTwAjwElhkviFga9D+jrUpyg97kbWBLEJrWjCN5Bb+PwD7SgxUMbjFqd42FiQA+BT40wIEYHcQKAC/AneBM/Z/MfBti6EmgBuZ6fCTIMm+7/ouGKCwSeCFTXNMowCjTnUYGGtTTXnx0zT6hyIMFi/QHwy2y4s0gIUhQKc67UV+aTHgqN0PAT/aLrxVGF8Fmrnp5gRwIdIgs7X1OLDffKuBjcBHQb3/7D5SMdi4XTjVa15kr2mxCuAM8I9T1dxy0VO7qnT3eQCwYfoqACrwtw0+6UUmgCWlLt7p36k+A57VmWZGg2hrWH7rDyLucVA3Ns1jTnV8Lmt+uwDHA3H32bljIEjSofDL0/ym0N9c9obtAhwLQIjpZ17A4JOg7vWInm51dcPqVCeARxXFsyWA9yIAf5/rMSBrR6hmt1pk/XCKXwUpBWDaqf7RNQaDt75pg5dtyqnOlgCG03wp5WySd1D3twoGH4TnD6f6yot8b6lnBjifcsrLOgj5SeBhpOheGYBTfQCcAk471X9TTnZ5h/WvhAcis/sVL9SMyKTrx86fIr77dNE6BXi5pwE61ekIoJ5isDzNz53qbN3fpVOCBOAcsN3W4uE6PxQlW/B9ZdCLDNX5ma3roLtlbwGzvhTlwr9lXgAAAABJRU5ErkJggg==" style={imgStyle} />
|
||||
<div>
|
||||
<span className="mx_HealthDemoTile_ts">{timeStr}</span>
|
||||
<span className="mx_HealthDemoTile_content">
|
||||
{this.props.mxEvent.getContent().bpm} bpm
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -32,12 +32,9 @@ module.exports = React.createClass({
|
||||
|
||||
return (
|
||||
<span className="mx_MFileTile">
|
||||
<div className="mx_MImageTile_download">
|
||||
<a href={cli.mxcUrlToHttp(content.url)} target="_blank">
|
||||
<img src="img/download.png" width="10" height="12"/>
|
||||
Download {this.presentableTextForFile(content)}
|
||||
</a>
|
||||
</div>
|
||||
<a href={cli.mxcUrlToHttp(content.url)} target="_blank">
|
||||
{this.presentableTextForFile(content)}
|
||||
</a>
|
||||
</span>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -17,7 +17,6 @@ limitations under the License.
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var filesize = require('filesize');
|
||||
|
||||
var MImageTileController = require("../../../../src/controllers/molecules/MImageTile");
|
||||
|
||||
@@ -79,15 +78,9 @@ module.exports = React.createClass({
|
||||
|
||||
return (
|
||||
<span className="mx_MImageTile">
|
||||
<a href={cli.mxcUrlToHttp(content.url)} onClick={ this.onClick }>
|
||||
<img className="mx_MImageTile_thumbnail" src={cli.mxcUrlToHttp(content.url, 320, 240)} alt={content.body} style={imgStyle} />
|
||||
<a href={cli.mxcUrlToHttp(content.url)} onClick={this.onClick}>
|
||||
<img src={cli.mxcUrlToHttp(content.url, 320, 240)} alt={content.body} style={imgStyle} />
|
||||
</a>
|
||||
<div className="mx_MImageTile_download">
|
||||
<a href={cli.mxcUrlToHttp(content.url)} target="_blank">
|
||||
<img src="img/download.png" width="10" height="12"/>
|
||||
Download {content.body} ({ filesize(content.info.size) })
|
||||
</a>
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -24,7 +24,6 @@ var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
|
||||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
var TextForEvent = require('../../../../src/TextForEvent');
|
||||
var MessageTimestamp = ComponentBroker.get('atoms/MessageTimestamp');
|
||||
var MemberAvatar = ComponentBroker.get('atoms/MemberAvatar');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MRoomMemberTile',
|
||||
@@ -42,7 +41,7 @@ module.exports = React.createClass({
|
||||
return (
|
||||
<div className="mx_MessageTile mx_MessageTile_notice">
|
||||
<div className="mx_MessageTile_avatar">
|
||||
<MemberAvatar member={this.props.mxEvent.sender} />
|
||||
<img src={ this.props.mxEvent.target ? MatrixClientPeg.get().getAvatarUrlForMember(this.props.mxEvent.target, 40, 40, "crop") : null } width="40" height="40" alt=""/>
|
||||
</div>
|
||||
{ timestamp }
|
||||
<span className="mx_SenderProfile"></span>
|
||||
|
||||
@@ -24,21 +24,15 @@ var LogoutButton = ComponentBroker.get("atoms/LogoutButton");
|
||||
var EnableNotificationsButton = ComponentBroker.get("atoms/EnableNotificationsButton");
|
||||
|
||||
var MatrixToolbarController = require("../../../../src/controllers/molecules/MatrixToolbar");
|
||||
var Notifier = ComponentBroker.get('organisms/Notifier');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MatrixToolbar',
|
||||
mixins: [MatrixToolbarController],
|
||||
|
||||
hideToolbar: function() {
|
||||
Notifier.setToolbarHidden(true);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_MatrixToolbar">
|
||||
You are not receiving desktop notifications. <EnableNotificationsButton />
|
||||
<div className="mx_MatrixToolbar_close"><img src="img/close-white.png" width="16" height="16" onClick={ this.hideToolbar } /></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@ var React = require('react');
|
||||
|
||||
var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
|
||||
var MemberInfoController = require("../../../../src/controllers/molecules/MemberInfo");
|
||||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
var MemberAvatar = ComponentBroker.get('atoms/MemberAvatar');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MemberInfo',
|
||||
@@ -60,6 +58,11 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var power;
|
||||
if (this.props.member) {
|
||||
var img = "img/p/p" + Math.floor(20 * this.props.member.powerLevelNorm / 100) + ".png";
|
||||
power = <img src={ img } className="mx_MemberTile_power" width="48" height="48" alt=""/>;
|
||||
}
|
||||
var activeAgo = "unknown";
|
||||
if (this.state.active >= 0) {
|
||||
activeAgo = this.getDuration(this.state.active);
|
||||
@@ -98,7 +101,9 @@ module.exports = React.createClass({
|
||||
<img className="mx_MemberInfo_chevron" src="img/chevron-right.png" width="9" height="16" />
|
||||
<div className="mx_MemberInfo_shim"></div>
|
||||
<div className="mx_MemberInfo_avatar">
|
||||
<MemberAvatar member={this.props.member} width={128} height={128} />
|
||||
<img className="mx_MemberInfo_avatarImg"
|
||||
src={ this.props.member ? MatrixClientPeg.get().getAvatarUrlForMember(this.props.member, 128, 128, "crop") : null }
|
||||
width="128" height="128" alt=""/>
|
||||
</div>
|
||||
<div className="mx_MemberInfo_field">{this.props.member.userId}</div>
|
||||
{opLabel}
|
||||
|
||||
@@ -24,7 +24,6 @@ var Modal = require("../../../../src/Modal");
|
||||
var MemberTileController = require("../../../../src/controllers/molecules/MemberTile");
|
||||
var MemberInfo = ComponentBroker.get('molecules/MemberInfo');
|
||||
var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog");
|
||||
var MemberAvatar = ComponentBroker.get('atoms/MemberAvatar');
|
||||
|
||||
// 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.
|
||||
@@ -51,7 +50,7 @@ module.exports = React.createClass({
|
||||
var isMyUser = MatrixClientPeg.get().credentials.userId == this.props.member.userId;
|
||||
|
||||
var power;
|
||||
if (this.props.member && this.props.member.powerLevelNorm > 0) {
|
||||
if (this.props.member) {
|
||||
var img = "img/p/p" + Math.floor(20 * this.props.member.powerLevelNorm / 100) + ".png";
|
||||
power = <img src={ img } className="mx_MemberTile_power" width="48" height="48" alt=""/>;
|
||||
}
|
||||
@@ -96,8 +95,10 @@ module.exports = React.createClass({
|
||||
return (
|
||||
<div className={mainClassName} onMouseEnter={ this.mouseEnter } onMouseLeave={ this.mouseLeave }>
|
||||
<div className="mx_MemberTile_avatar">
|
||||
<MemberAvatar member={this.props.member} />
|
||||
{ power }
|
||||
<img className="mx_MemberTile_avatarImg"
|
||||
src={ this.props.member ? MatrixClientPeg.get().getAvatarUrlForMember(this.props.member, 40, 40, "crop") : null }
|
||||
width="40" height="40" alt=""/>
|
||||
{ power }
|
||||
</div>
|
||||
{ nameEl }
|
||||
</div>
|
||||
|
||||
@@ -22,9 +22,6 @@ var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
|
||||
var MessageComposerController = require("../../../../src/controllers/molecules/MessageComposer");
|
||||
var ContentMessages = require("../../../../src/ContentMessages");
|
||||
|
||||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
var MemberAvatar = ComponentBroker.get('atoms/MemberAvatar');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MessageComposer',
|
||||
mixins: [MessageComposerController],
|
||||
@@ -50,7 +47,7 @@ module.exports = React.createClass({
|
||||
<div className="mx_MessageComposer_wrapper">
|
||||
<div className="mx_MessageComposer_row">
|
||||
<div className="mx_MessageComposer_avatar">
|
||||
<MemberAvatar member={me} />
|
||||
<img src={ MatrixClientPeg.get().getAvatarUrlForMember(me, 40, 40, "crop") } width="40" height="40" alt=""/>
|
||||
</div>
|
||||
<div className="mx_MessageComposer_input">
|
||||
<textarea ref="textarea" onKeyDown={this.onKeyDown} placeholder="Type a message" />
|
||||
|
||||
@@ -25,7 +25,6 @@ var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
|
||||
var MessageTimestamp = ComponentBroker.get('atoms/MessageTimestamp');
|
||||
var SenderProfile = ComponentBroker.get('molecules/SenderProfile');
|
||||
var MemberAvatar = ComponentBroker.get('atoms/MemberAvatar');
|
||||
|
||||
var UnknownMessageTile = ComponentBroker.get('molecules/UnknownMessageTile');
|
||||
|
||||
@@ -61,20 +60,14 @@ module.exports = React.createClass({
|
||||
mx_MessageTile_last: this.props.last,
|
||||
});
|
||||
var timestamp = <MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
||||
|
||||
var aux = null;
|
||||
if (msgtype === 'm.image') aux = "sent an image";
|
||||
else if (msgtype === 'm.video') aux = "sent a video";
|
||||
else if (msgtype === 'm.file') aux = "uploaded a file";
|
||||
|
||||
var avatar, sender, resend;
|
||||
if (!this.props.continuation) {
|
||||
avatar = (
|
||||
<div className="mx_MessageTile_avatar">
|
||||
<MemberAvatar member={this.props.mxEvent.sender} />
|
||||
<img src={ this.props.mxEvent.sender ? MatrixClientPeg.get().getAvatarUrlForMember(this.props.mxEvent.sender, 40, 40, "crop") : null } width="40" height="40" alt=""/>
|
||||
</div>
|
||||
);
|
||||
sender = <SenderProfile mxEvent={this.props.mxEvent} aux={aux} />;
|
||||
sender = <SenderProfile mxEvent={this.props.mxEvent} />;
|
||||
}
|
||||
if (this.props.mxEvent.status === "not_sent" && !this.state.resending) {
|
||||
resend = <button className="mx_MessageTile_msgOption" onClick={this.onResend}>
|
||||
|
||||
@@ -22,7 +22,6 @@ var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
|
||||
var RoomHeaderController = require("../../../../src/controllers/molecules/RoomHeader");
|
||||
var EditableText = ComponentBroker.get("atoms/EditableText");
|
||||
var RoomAvatar = ComponentBroker.get('atoms/RoomAvatar');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomHeader',
|
||||
@@ -68,7 +67,6 @@ module.exports = React.createClass({
|
||||
|
||||
var name = null;
|
||||
var topic_el = null;
|
||||
var cancel_button = null;
|
||||
var save_button = null;
|
||||
var settings_button = null;
|
||||
var actual_name = this.props.room.currentState.getStateEvents('m.room.name', '');
|
||||
@@ -79,14 +77,12 @@ module.exports = React.createClass({
|
||||
<input className="mx_RoomHeader_nameInput" type="text" defaultValue={actual_name} placeholder="Name" ref="name_edit"/>
|
||||
</div>
|
||||
// if (topic) topic_el = <div className="mx_RoomHeader_topic"><textarea>{ topic.getContent().topic }</textarea></div>
|
||||
cancel_button = <div className="mx_RoomHeader_textButton" onClick={this.props.onCancelClick}>Cancel</div>
|
||||
save_button = <div className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>Save Changes</div>
|
||||
} else {
|
||||
name =
|
||||
<div className="mx_RoomHeader_name">
|
||||
<EditableText label={this.props.room.name} initialValue={actual_name} placeHolder="Name" onValueChanged={this.onNameChange} />
|
||||
</div>
|
||||
if (topic) topic_el = <div className="mx_RoomHeader_topic" title={topic.getContent().topic}>{ topic.getContent().topic }</div>;
|
||||
if (topic) topic_el = <div className="mx_RoomHeader_topic">{ topic.getContent().topic }</div>;
|
||||
settings_button = (
|
||||
<div className="mx_RoomHeader_button" onClick={this.props.onSettingsClick}>
|
||||
<img src="img/settings.png" width="32" height="32"/>
|
||||
@@ -94,18 +90,11 @@ module.exports = React.createClass({
|
||||
);
|
||||
}
|
||||
|
||||
var roomAvatar = null;
|
||||
if (this.props.room) {
|
||||
roomAvatar = (
|
||||
<RoomAvatar room={this.props.room} />
|
||||
);
|
||||
}
|
||||
|
||||
header =
|
||||
<div className="mx_RoomHeader_wrapper">
|
||||
<div className="mx_RoomHeader_leftRow">
|
||||
<div className="mx_RoomHeader_avatar">
|
||||
{ roomAvatar }
|
||||
<img src={ MatrixClientPeg.get().getAvatarUrlForRoom(this.props.room, 48, 48, "crop") } width="48" height="48" alt=""/>
|
||||
</div>
|
||||
<div className="mx_RoomHeader_info">
|
||||
{ name }
|
||||
@@ -113,8 +102,6 @@ module.exports = React.createClass({
|
||||
</div>
|
||||
</div>
|
||||
{callButtons}
|
||||
{cancel_button}
|
||||
{save_button}
|
||||
<div className="mx_RoomHeader_rightRow">
|
||||
{ settings_button }
|
||||
<div className="mx_RoomHeader_button mx_RoomHeader_search">
|
||||
|
||||
@@ -207,6 +207,12 @@ module.exports = React.createClass({
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="mx_RoomSettings_buttons">
|
||||
<div className="mx_RoomSettings_button" onClick={this.props.onSaveClick}>
|
||||
Save this room
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,9 +23,6 @@ var RoomTileController = require("../../../../src/controllers/molecules/RoomTile
|
||||
|
||||
var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
|
||||
|
||||
var ComponentBroker = require('../../../../src/ComponentBroker');
|
||||
var RoomAvatar = ComponentBroker.get('atoms/RoomAvatar');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomTile',
|
||||
mixins: [RoomTileController],
|
||||
@@ -60,10 +57,7 @@ module.exports = React.createClass({
|
||||
*/
|
||||
return (
|
||||
<div className={classes} onClick={this.onClick}>
|
||||
<div className="mx_RoomTile_avatar">
|
||||
<RoomAvatar room={this.props.room} />
|
||||
{ badge }
|
||||
</div>
|
||||
<div className="mx_RoomTile_avatar"><img src={ MatrixClientPeg.get().getAvatarUrlForRoom(this.props.room, 40, 40, "crop") } width="40" height="40" alt=""/>{ badge }</div>
|
||||
<div className="mx_RoomTile_name">{name}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -45,7 +45,7 @@ module.exports = React.createClass({
|
||||
}
|
||||
return (
|
||||
<span className={classes}>
|
||||
{name} { this.props.aux }
|
||||
{name}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
|
||||
50
skins/base/views/molecules/voip/MCallAnswerTile.js
Normal file
50
skins/base/views/molecules/voip/MCallAnswerTile.js
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
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 ComponentBroker = require('../../../../../src/ComponentBroker');
|
||||
var MCallAnswerTileController = require("../../../../../src/controllers/molecules/voip/MCallAnswerTile");
|
||||
var MessageTimestamp = ComponentBroker.get('atoms/MessageTimestamp');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MCallAnswerTile',
|
||||
mixins: [MCallAnswerTileController],
|
||||
|
||||
getAnswerText: function(event) {
|
||||
var senderName = event.sender ? event.sender.name : "Someone";
|
||||
return senderName + " answered the call.";
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// XXX: for now, just cheekily borrow the css from message tile...
|
||||
return (
|
||||
<div className="mx_MessageTile mx_MessageTile_notice">
|
||||
<div className="mx_MessageTile_avatar">
|
||||
<img src={ this.props.mxEvent.sender ? MatrixClientPeg.get().getAvatarUrlForMember(this.props.mxEvent.sender, 40, 40, "crop") : null } width="40" height="40" alt=""/>
|
||||
</div>
|
||||
<MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
||||
<span className="mx_SenderProfile"></span>
|
||||
<span className="mx_MessageTile_content">
|
||||
{this.getAnswerText(this.props.mxEvent)}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
50
skins/base/views/molecules/voip/MCallHangupTile.js
Normal file
50
skins/base/views/molecules/voip/MCallHangupTile.js
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
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 ComponentBroker = require('../../../../../src/ComponentBroker');
|
||||
var MCallHangupTileController = require("../../../../../src/controllers/molecules/voip/MCallHangupTile");
|
||||
var MessageTimestamp = ComponentBroker.get('atoms/MessageTimestamp');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MCallHangupTile',
|
||||
mixins: [MCallHangupTileController],
|
||||
|
||||
getHangupText: function(event) {
|
||||
var senderName = event.sender ? event.sender.name : "Someone";
|
||||
return senderName + " ended the call.";
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// XXX: for now, just cheekily borrow the css from message tile...
|
||||
return (
|
||||
<div className="mx_MessageTile mx_MessageTile_notice">
|
||||
<div className="mx_MessageTile_avatar">
|
||||
<img src={ this.props.mxEvent.sender ? MatrixClientPeg.get().getAvatarUrlForMember(this.props.mxEvent.sender, 40, 40, "crop") : null } width="40" height="40" alt=""/>
|
||||
</div>
|
||||
<MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
||||
<span className="mx_SenderProfile"></span>
|
||||
<span className="mx_MessageTile_content">
|
||||
{this.getHangupText(this.props.mxEvent)}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
56
skins/base/views/molecules/voip/MCallInviteTile.js
Normal file
56
skins/base/views/molecules/voip/MCallInviteTile.js
Normal file
@@ -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 MatrixClientPeg = require("../../../../../src/MatrixClientPeg");
|
||||
var ComponentBroker = require('../../../../../src/ComponentBroker');
|
||||
var MCallInviteTileController = require("../../../../../src/controllers/molecules/voip/MCallInviteTile");
|
||||
var MessageTimestamp = ComponentBroker.get('atoms/MessageTimestamp');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MCallInviteTile',
|
||||
mixins: [MCallInviteTileController],
|
||||
|
||||
getInviteText: function(event) {
|
||||
var senderName = event.sender ? event.sender.name : "Someone";
|
||||
// FIXME: Find a better way to determine this from the event?
|
||||
var type = "voice";
|
||||
if (event.getContent().offer &&
|
||||
event.getContent().offer.sdp.indexOf('m=video') !== -1) {
|
||||
type = "video";
|
||||
}
|
||||
return senderName + " placed a " + type + " call.";
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// XXX: for now, just cheekily borrow the css from message tile...
|
||||
return (
|
||||
<div className="mx_MessageTile mx_MessageTile_notice">
|
||||
<div className="mx_MessageTile_avatar">
|
||||
<img src={ this.props.mxEvent.sender ? MatrixClientPeg.get().getAvatarUrlForMember(this.props.mxEvent.sender, 40, 40, "crop") : null } width="40" height="40" alt=""/>
|
||||
</div>
|
||||
<MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
||||
<span className="mx_SenderProfile"></span>
|
||||
<span className="mx_MessageTile_content">
|
||||
{this.getInviteText(this.props.mxEvent)}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -29,12 +29,12 @@ module.exports = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<aside className="mx_LeftPanel">
|
||||
<div className="mx_LeftPanel">
|
||||
<img className="mx_LeftPanel_hideButton" src="img/hide.png" width="32" height="32" alt="<"/>
|
||||
<IncomingCallBox />
|
||||
<RoomList selectedRoom={this.props.selectedRoom} />
|
||||
<BottomLeftMenu />
|
||||
</aside>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -23,8 +23,6 @@ var TextForEvent = require("../../../../src/TextForEvent");
|
||||
var extend = require("../../../../src/extend");
|
||||
var dis = require("../../../../src/dispatcher");
|
||||
|
||||
var Avatar = require("../../../../src/Avatar");
|
||||
|
||||
|
||||
var NotifierView = {
|
||||
notificationMessageForEvent: function(ev) {
|
||||
@@ -59,15 +57,11 @@ var NotifierView = {
|
||||
if (ev.getContent().body) msg = ev.getContent().body;
|
||||
}
|
||||
|
||||
var avatarUrl = Avatar.avatarUrlForMember(
|
||||
ev.sender, 40, 40, 'crop'
|
||||
);
|
||||
|
||||
var notification = new global.Notification(
|
||||
title,
|
||||
{
|
||||
"body": msg,
|
||||
"icon": avatarUrl
|
||||
"icon": MatrixClientPeg.get().getAvatarUrlForMember(ev.sender)
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -66,12 +66,12 @@ module.exports = React.createClass({
|
||||
}
|
||||
|
||||
return (
|
||||
<aside className="mx_RightPanel">
|
||||
<div className="mx_RightPanel">
|
||||
<div className="mx_RightPanel_header">
|
||||
{ buttonGroup }
|
||||
</div>
|
||||
{ panel }
|
||||
</aside>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -64,21 +64,11 @@ module.exports = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
onCancelClick: function() {
|
||||
this.setState(this.getInitialState());
|
||||
},
|
||||
|
||||
getUnreadMessagesString: function() {
|
||||
if (!this.state.numUnreadMessages) {
|
||||
return "";
|
||||
}
|
||||
return this.state.numUnreadMessages + " new messages";
|
||||
},
|
||||
|
||||
scrollToBottom: function() {
|
||||
if (!this.refs.messageWrapper) return;
|
||||
var messageWrapper = this.refs.messageWrapper.getDOMNode();
|
||||
messageWrapper.scrollTop = messageWrapper.scrollHeight;
|
||||
return this.state.numUnreadMessages + " unread messages";
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@@ -144,8 +134,8 @@ module.exports = React.createClass({
|
||||
// set when you've scrolled up
|
||||
if (unreadMsgs) {
|
||||
statusBar = (
|
||||
<div className="mx_RoomView_unreadMessagesBar" onClick={ this.scrollToBottom }>
|
||||
<img src="img/newmessages.png" width="10" height="12" alt=""/>
|
||||
<div className="mx_RoomView_typingBar">
|
||||
<img src="img/typing.png" width="40" height="40" alt=""/>
|
||||
{unreadMsgs}
|
||||
</div>
|
||||
);
|
||||
@@ -161,39 +151,30 @@ module.exports = React.createClass({
|
||||
}
|
||||
|
||||
var roomEdit = null;
|
||||
|
||||
if (this.state.editingRoomSettings) {
|
||||
roomEdit = <RoomSettings ref="room_settings" onSaveClick={this.onSaveClick} room={this.state.room} />;
|
||||
}
|
||||
|
||||
if (this.state.uploadingRoomSettings) {
|
||||
roomEdit = <Loader/>;
|
||||
}
|
||||
|
||||
var fileDropTarget = null;
|
||||
if (this.state.draggingFile) {
|
||||
fileDropTarget = <div className="mx_RoomView_fileDropTarget">
|
||||
<div className="mx_RoomView_fileDropTargetLabel">
|
||||
<img src="img/upload-big.png" width="46" height="61" alt="Drop File Here"/><br/>
|
||||
Drop File Here
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_RoomView">
|
||||
<RoomHeader ref="header" room={this.state.room} editing={this.state.editingRoomSettings}
|
||||
onSettingsClick={this.onSettingsClick} onSaveClick={this.onSaveClick} onCancelClick={this.onCancelClick} />
|
||||
onSettingsClick={this.onSettingsClick}/>
|
||||
<div className="mx_RoomView_auxPanel">
|
||||
<CallView room={this.state.room}/>
|
||||
{ roomEdit }
|
||||
</div>
|
||||
<div ref="messageWrapper" className="mx_RoomView_messagePanel" onScroll={ this.onMessageListScroll }>
|
||||
<div className="mx_RoomView_messageListWrapper">
|
||||
{ fileDropTarget }
|
||||
<ol className="mx_RoomView_MessageList" aria-live="polite">
|
||||
<li className={scrollheader_classes}>
|
||||
</li>
|
||||
<div className="mx_RoomView_MessageList" aria-live="polite">
|
||||
<div className={scrollheader_classes}>
|
||||
</div>
|
||||
{this.getEventTiles()}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mx_RoomView_statusArea">
|
||||
|
||||
@@ -75,15 +75,15 @@ module.exports = React.createClass({
|
||||
break;
|
||||
}
|
||||
|
||||
if (Notifier.supportsDesktopNotifications() && !Notifier.isEnabled() && !Notifier.isToolbarHidden()) {
|
||||
if (Notifier.supportsDesktopNotifications() && !Notifier.isEnabled()) {
|
||||
return (
|
||||
<div className="mx_MatrixChat_wrapper">
|
||||
<MatrixToolbar />
|
||||
<div className="mx_MatrixChat mx_MatrixChat_toolbarShowing">
|
||||
<LeftPanel selectedRoom={this.state.currentRoom} />
|
||||
<main className="mx_MatrixChat_middlePanel">
|
||||
<div className="mx_MatrixChat_middlePanel">
|
||||
{page_element}
|
||||
</main>
|
||||
</div>
|
||||
{right_panel}
|
||||
</div>
|
||||
</div>
|
||||
@@ -93,9 +93,9 @@ module.exports = React.createClass({
|
||||
return (
|
||||
<div className="mx_MatrixChat">
|
||||
<LeftPanel selectedRoom={this.state.currentRoom} />
|
||||
<main className="mx_MatrixChat_middlePanel">
|
||||
<div className="mx_MatrixChat_middlePanel">
|
||||
{page_element}
|
||||
</main>
|
||||
</div>
|
||||
{right_panel}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -30,7 +30,7 @@ var ServerConfig = ComponentBroker.get("molecules/ServerConfig");
|
||||
|
||||
module.exports = React.createClass({
|
||||
DEFAULT_HS_URL: 'https://matrix.org',
|
||||
DEFAULT_IS_URL: 'https://vector.im',
|
||||
DEFAULT_IS_URL: 'https://matrix.org',
|
||||
|
||||
displayName: 'Login',
|
||||
mixins: [LoginController],
|
||||
|
||||
@@ -28,7 +28,7 @@ var ServerConfig = ComponentBroker.get("molecules/ServerConfig");
|
||||
|
||||
module.exports = React.createClass({
|
||||
DEFAULT_HS_URL: 'https://matrix.org',
|
||||
DEFAULT_IS_URL: 'https://vector.im',
|
||||
DEFAULT_IS_URL: 'https://matrix.org',
|
||||
|
||||
displayName: 'Register',
|
||||
mixins: [RegisterController],
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
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 MatrixClientPeg = require('./MatrixClientPeg');
|
||||
|
||||
module.exports = {
|
||||
avatarUrlForMember: function(member, width, height, resizeMethod) {
|
||||
var url = MatrixClientPeg.get().getAvatarUrlForMember(
|
||||
member, width, height, resizeMethod, false
|
||||
);
|
||||
if (url === null) {
|
||||
url = this.defaultAvatarUrlForString(member.userId);
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
defaultAvatarUrlForString: function(s) {
|
||||
var total = 0;
|
||||
for (var i = 0; i < s.length; ++i) {
|
||||
total += s.charCodeAt(i);
|
||||
}
|
||||
switch (total % 3) {
|
||||
case 0:
|
||||
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAIAAAADnC86AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrszQENADAIACB9QjNbxSKP4eagAFnTseHFErFYLBaLxWKxWCwWi8Vi8cX4CzAABSwCRWJw31gAAAAASUVORK5CYII=";
|
||||
break;
|
||||
case 1:
|
||||
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAIAAAADnC86AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrszQENADAIACB9chOaxgCP4eagAFk9seHFErFYLBaLxWKxWCwWi8Vi8cX4CzAAtKMCks/JG8MAAAAASUVORK5CYII=";
|
||||
break;
|
||||
case 2:
|
||||
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAIAAAADnC86AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrszQENADAIACB9YzNayQCP4eagADldseHFErFYLBaLxWKxWCwWi8Vi8cX4CzAAyiACeHwPiu4AAAAASUVORK5CYII=";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ var ComponentBroker = require('./ComponentBroker');
|
||||
var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog");
|
||||
var Matrix = require("matrix-js-sdk");
|
||||
var dis = require("./dispatcher");
|
||||
var q = require("q");
|
||||
|
||||
var calls = {
|
||||
//room_id: MatrixCall
|
||||
@@ -150,6 +151,29 @@ function _setCallState(call, roomId, status) {
|
||||
});
|
||||
}
|
||||
|
||||
function findOrMakeVertoRoom() {
|
||||
var VERTO_USERID = '@verto_1234:matrix.org';
|
||||
var defer = q.defer();
|
||||
|
||||
var allRooms = MatrixClientPeg.get().getRooms();
|
||||
for (var i = 0; i < Object.keys(allRooms).length; ++i) {
|
||||
var r = allRooms[i];
|
||||
var membs = r.getJoinedMembers();
|
||||
if (membs.length == 2 && (membs[0].userId == VERTO_USERID || membs[0].userId == VERTO_USERID)) {
|
||||
defer.resolve(r);
|
||||
return defer.promise;
|
||||
}
|
||||
}
|
||||
|
||||
MatrixClientPeg.get().createRoom({
|
||||
invite: [ VERTO_USERID ]
|
||||
}).done(function(result) {
|
||||
defer.resolve(MatrixClientPeg.get().getRoom(result.room_id));
|
||||
});
|
||||
|
||||
return defer.promise;
|
||||
}
|
||||
|
||||
dis.register(function(payload) {
|
||||
switch (payload.action) {
|
||||
case 'place_call':
|
||||
@@ -162,7 +186,29 @@ dis.register(function(payload) {
|
||||
return;
|
||||
}
|
||||
var members = room.getJoinedMembers();
|
||||
if (members.length !== 2) {
|
||||
if (members.length > 2) {
|
||||
var vertoRoom = findOrMakeVertoRoom().done(function(r) {
|
||||
console.log("Place %s conference call in %s", payload.type, payload.room_id);
|
||||
var call = Matrix.createNewMatrixCall(
|
||||
MatrixClientPeg.get(), r.roomId
|
||||
);
|
||||
_setCallListeners(call);
|
||||
_setCallState(call, call.roomId, "ringback");
|
||||
if (payload.type === 'voice') {
|
||||
call.placeVoiceCall();
|
||||
}
|
||||
else if (payload.type === 'video') {
|
||||
call.placeVideoCall(
|
||||
payload.remote_element,
|
||||
payload.local_element
|
||||
);
|
||||
}
|
||||
else {
|
||||
console.error("Unknown call type: %s", payload.type);
|
||||
}
|
||||
});
|
||||
return;
|
||||
} else if (members.length !== 2) {
|
||||
var text = members.length === 1 ? "yourself." : "more than 2 people.";
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
description: "You cannot place a call with " + text
|
||||
@@ -227,4 +273,4 @@ module.exports = {
|
||||
getCall: function(roomId) {
|
||||
return calls[roomId] || null;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -75,6 +75,7 @@ require('../skins/base/views/molecules/MNoticeTile');
|
||||
require('../skins/base/views/molecules/MEmoteTile');
|
||||
require('../skins/base/views/molecules/MImageTile');
|
||||
require('../skins/base/views/molecules/MFileTile');
|
||||
require('../skins/base/views/molecules/MRoomMemberTile');
|
||||
require('../skins/base/views/molecules/RoomHeader');
|
||||
require('../skins/base/views/molecules/MessageComposer');
|
||||
require('../skins/base/views/molecules/ProgressBar');
|
||||
@@ -102,14 +103,14 @@ require('../skins/base/views/molecules/RoomDropTarget');
|
||||
require('../skins/base/views/molecules/BottomLeftMenu');
|
||||
require('../skins/base/views/molecules/DateSeparator');
|
||||
require('../skins/base/views/atoms/voip/VideoFeed');
|
||||
require('../skins/base/views/atoms/MemberAvatar');
|
||||
require('../skins/base/views/atoms/RoomAvatar');
|
||||
require('../skins/base/views/atoms/ImageView');
|
||||
require('../skins/base/views/molecules/voip/VideoView');
|
||||
require('../skins/base/views/molecules/voip/CallView');
|
||||
require('../skins/base/views/molecules/voip/IncomingCallBox');
|
||||
require('../skins/base/views/molecules/voip/MCallInviteTile');
|
||||
require('../skins/base/views/molecules/voip/MCallAnswerTile');
|
||||
require('../skins/base/views/molecules/voip/MCallHangupTile');
|
||||
require('../skins/base/views/molecules/EventAsTextTile');
|
||||
require('../skins/base/views/molecules/HealthDemoTile');
|
||||
require('../skins/base/views/molecules/MemberInfo');
|
||||
require('../skins/base/views/organisms/ErrorDialog');
|
||||
require('../skins/base/views/organisms/QuestionDialog');
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
var MatrixClientPeg = require('./MatrixClientPeg');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Given a room object, return the canonical alias for it
|
||||
* if there is one. Otherwise return null;
|
||||
*/
|
||||
getCanonicalAliasForRoom: function(room) {
|
||||
var aliasEvents = room.currentState.getStateEvents(
|
||||
"m.room.aliases"
|
||||
);
|
||||
// Canonical aliases aren't implemented yet, so just return the first
|
||||
for (var j = 0; j < aliasEvents.length; j++) {
|
||||
var aliases = aliasEvents[j].getContent().aliases;
|
||||
if (aliases && aliases.length) {
|
||||
return aliases[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,34 +67,10 @@ function textForMessageEvent(ev) {
|
||||
return message;
|
||||
};
|
||||
|
||||
function textForCallAnswerEvent(event) {
|
||||
var senderName = event.sender ? event.sender.name : "Someone";
|
||||
return senderName + " answered the call.";
|
||||
};
|
||||
|
||||
function textForCallHangupEvent(event) {
|
||||
var senderName = event.sender ? event.sender.name : "Someone";
|
||||
return senderName + " ended the call.";
|
||||
};
|
||||
|
||||
function textForCallInviteEvent(event) {
|
||||
var senderName = event.sender ? event.sender.name : "Someone";
|
||||
// FIXME: Find a better way to determine this from the event?
|
||||
var type = "voice";
|
||||
if (event.getContent().offer && event.getContent().offer.sdp &&
|
||||
event.getContent().offer.sdp.indexOf('m=video') !== -1) {
|
||||
type = "video";
|
||||
}
|
||||
return senderName + " placed a " + type + " call.";
|
||||
};
|
||||
|
||||
var handlers = {
|
||||
'm.room.message': textForMessageEvent,
|
||||
'm.room.topic': textForTopicEvent,
|
||||
'm.room.member': textForMemberEvent,
|
||||
'm.call.invite': textForCallInviteEvent,
|
||||
'm.call.answer': textForCallAnswerEvent,
|
||||
'm.call.hangup': textForCallHangupEvent,
|
||||
'm.room.member': textForMemberEvent
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
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 Avatar = require('../../Avatar');
|
||||
|
||||
var React = require('react');
|
||||
|
||||
module.exports = {
|
||||
propTypes: {
|
||||
member: React.PropTypes.object.isRequired,
|
||||
width: React.PropTypes.number,
|
||||
height: React.PropTypes.number,
|
||||
resizeMethod: React.PropTypes.string,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
width: 40,
|
||||
height: 40,
|
||||
resizeMethod: 'crop'
|
||||
}
|
||||
},
|
||||
|
||||
defaultAvatarUrl: function(member) {
|
||||
return Avatar.defaultAvatarUrlForString(
|
||||
member.userId
|
||||
);
|
||||
},
|
||||
|
||||
onError: function(ev) {
|
||||
// don't tightloop if the browser can't load a data url
|
||||
if (ev.target.src == this.defaultAvatarUrl(this.props.member)) {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
imageUrl: this.defaultAvatarUrl(this.props.member)
|
||||
});
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
imageUrl: Avatar.avatarUrlForMember(
|
||||
this.props.member,
|
||||
this.props.width, this.props.height,
|
||||
this.props.resizeMethod
|
||||
)
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
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 MatrixClientPeg = require('../../MatrixClientPeg');
|
||||
var Avatar = require('../../Avatar');
|
||||
|
||||
module.exports = {
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
width: 40,
|
||||
height: 40,
|
||||
resizeMethod: 'crop'
|
||||
}
|
||||
},
|
||||
|
||||
avatarUrlForRoom: function(room) {
|
||||
var url = MatrixClientPeg.get().getAvatarUrlForRoom(
|
||||
room,
|
||||
this.props.width, this.props.height, this.props.resizeMethod,
|
||||
false
|
||||
);
|
||||
if (url === null) {
|
||||
url = this.defaultAvatarUrl(room);
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
defaultAvatarUrl: function(room) {
|
||||
return Avatar.defaultAvatarUrlForString(
|
||||
this.props.room.roomId
|
||||
);
|
||||
},
|
||||
|
||||
onError: function(ev) {
|
||||
// don't tightloop if the browser can't load a data url
|
||||
if (ev.target.src == this.defaultAvatarUrl(this.props.room)) {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
imageUrl: this.defaultAvatarUrl(this.props.room)
|
||||
});
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
imageUrl: this.avatarUrlForRoom(this.props.room)
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -293,7 +293,7 @@ module.exports = {
|
||||
};
|
||||
var canAffectUser = them.powerLevel < me.powerLevel;
|
||||
if (!canAffectUser) {
|
||||
//console.log("Cannot affect user: %s >= %s", them.powerLevel, me.powerLevel);
|
||||
console.log("Cannot affect user: %s >= %s", them.powerLevel, me.powerLevel);
|
||||
return can;
|
||||
}
|
||||
var editPowerLevel = (
|
||||
|
||||
@@ -182,12 +182,12 @@ module.exports = {
|
||||
|
||||
var self = this;
|
||||
setTimeout(function() {
|
||||
if (self.refs.textarea && self.refs.textarea.getDOMNode().value != '') {
|
||||
if (self.refs.textarea.getDOMNode().value != '') {
|
||||
self.onTypingActivity();
|
||||
} else {
|
||||
self.onFinishedTyping();
|
||||
}
|
||||
}, 10); // XXX: what is this 10ms setTimeout doing? Looks hacky :(
|
||||
}, 10);
|
||||
},
|
||||
|
||||
onEnter: function(ev) {
|
||||
|
||||
@@ -14,9 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_MemberAvatar {
|
||||
z-index: 20;
|
||||
border-radius: 20px;
|
||||
background-color: #dbdbdb;
|
||||
}
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
};
|
||||
@@ -14,25 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_HealthDemoTile {
|
||||
border: 1px solid black;
|
||||
width: 200px;
|
||||
height: 70px;
|
||||
margin: 5px;
|
||||
background-color: #ddd;
|
||||
padding: 5px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.mx_HealthDemoTile .mx_HealthDemoTile_ts {
|
||||
display: block;
|
||||
text-align: right;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
.mx_HealthDemoTile_content {
|
||||
text-align: right;
|
||||
font-size: 200%;
|
||||
font-weight: bold;
|
||||
}
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
};
|
||||
@@ -16,19 +16,5 @@ limitations under the License.
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var RoomAvatarController = require("../../../../src/controllers/atoms/RoomAvatar");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomAvatar',
|
||||
mixins: [RoomAvatarController],
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<img className="mx_RoomAvatar" src={this.state.imageUrl} onError={this.onError}
|
||||
width={this.props.width} height={this.props.height}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
module.exports = {
|
||||
};
|
||||
@@ -27,14 +27,10 @@ var dis = require("../../dispatcher");
|
||||
* }
|
||||
*/
|
||||
|
||||
// XXX: This isn't an organism surely in the atomic sense of the word
|
||||
// what on earth is it doing here?!
|
||||
|
||||
module.exports = {
|
||||
start: function() {
|
||||
this.boundOnRoomTimeline = this.onRoomTimeline.bind(this);
|
||||
MatrixClientPeg.get().on('Room.timeline', this.boundOnRoomTimeline);
|
||||
this.state = { 'toolbarHidden' : false };
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
@@ -86,8 +82,6 @@ module.exports = {
|
||||
value: false
|
||||
});
|
||||
}
|
||||
|
||||
this.setToolbarHidden(false);
|
||||
},
|
||||
|
||||
isEnabled: function() {
|
||||
@@ -100,18 +94,6 @@ module.exports = {
|
||||
return enabled === 'true';
|
||||
},
|
||||
|
||||
setToolbarHidden: function(hidden) {
|
||||
this.state.toolbarHidden = hidden;
|
||||
dis.dispatch({
|
||||
action: "notifier_enabled",
|
||||
value: this.isEnabled()
|
||||
});
|
||||
},
|
||||
|
||||
isToolbarHidden: function() {
|
||||
return this.state.toolbarHidden;
|
||||
},
|
||||
|
||||
onRoomTimeline: function(ev, room, toStartOfTimeline) {
|
||||
if (toStartOfTimeline) return;
|
||||
if (ev.sender && ev.sender.userId == MatrixClientPeg.get().credentials.userId) return;
|
||||
|
||||
@@ -73,11 +73,13 @@ module.exports = {
|
||||
if (actions && actions.tweaks && actions.tweaks.highlight) {
|
||||
hl = 2;
|
||||
}
|
||||
// obviously this won't deep copy but this shouldn't be necessary
|
||||
var amap = this.state.activityMap;
|
||||
amap[room.roomId] = Math.max(amap[room.roomId] || 0, hl);
|
||||
if (actions.notify) {
|
||||
// obviously this won't deep copy but this shouldn't be necessary
|
||||
var amap = this.state.activityMap;
|
||||
amap[room.roomId] = Math.max(amap[room.roomId] || 0, hl);
|
||||
|
||||
newState.activityMap = amap;
|
||||
newState.activityMap = amap;
|
||||
}
|
||||
}
|
||||
this.setState(newState);
|
||||
},
|
||||
|
||||
@@ -36,12 +36,11 @@ var Notifier = ComponentBroker.get('organisms/Notifier');
|
||||
|
||||
var tileTypes = {
|
||||
'm.room.message': ComponentBroker.get('molecules/MessageTile'),
|
||||
'm.room.member' : ComponentBroker.get('molecules/EventAsTextTile'),
|
||||
'm.call.invite' : ComponentBroker.get('molecules/EventAsTextTile'),
|
||||
'm.call.answer' : ComponentBroker.get('molecules/EventAsTextTile'),
|
||||
'm.call.hangup' : ComponentBroker.get('molecules/EventAsTextTile'),
|
||||
'm.room.topic' : ComponentBroker.get('molecules/EventAsTextTile'),
|
||||
'org.matrix.demo.health' : ComponentBroker.get('molecules/HealthDemoTile'),
|
||||
'm.room.member': ComponentBroker.get('molecules/MRoomMemberTile'),
|
||||
'm.call.invite': ComponentBroker.get('molecules/voip/MCallInviteTile'),
|
||||
'm.call.answer': ComponentBroker.get('molecules/voip/MCallAnswerTile'),
|
||||
'm.call.hangup': ComponentBroker.get('molecules/voip/MCallHangupTile'),
|
||||
'm.room.topic': ComponentBroker.get('molecules/EventAsTextTile'),
|
||||
};
|
||||
|
||||
var DateSeparator = ComponentBroker.get('molecules/DateSeparator');
|
||||
@@ -53,8 +52,7 @@ module.exports = {
|
||||
messageCap: INITIAL_SIZE,
|
||||
editingRoomSettings: false,
|
||||
uploadingRoomSettings: false,
|
||||
numUnreadMessages: 0,
|
||||
draggingFile: false,
|
||||
numUnreadMessages: 0
|
||||
}
|
||||
},
|
||||
|
||||
@@ -71,8 +69,6 @@ module.exports = {
|
||||
var messageWrapper = this.refs.messageWrapper.getDOMNode();
|
||||
messageWrapper.removeEventListener('drop', this.onDrop);
|
||||
messageWrapper.removeEventListener('dragover', this.onDragOver);
|
||||
messageWrapper.removeEventListener('dragleave', this.onDragLeaveOrEnd);
|
||||
messageWrapper.removeEventListener('dragend', this.onDragLeaveOrEnd);
|
||||
}
|
||||
dis.unregister(this.dispatcherRef);
|
||||
if (MatrixClientPeg.get()) {
|
||||
@@ -177,8 +173,6 @@ module.exports = {
|
||||
|
||||
messageWrapper.addEventListener('drop', this.onDrop);
|
||||
messageWrapper.addEventListener('dragover', this.onDragOver);
|
||||
messageWrapper.addEventListener('dragleave', this.onDragLeaveOrEnd);
|
||||
messageWrapper.addEventListener('dragend', this.onDragLeaveOrEnd);
|
||||
|
||||
messageWrapper.scrollTop = messageWrapper.scrollHeight;
|
||||
|
||||
@@ -207,7 +201,6 @@ module.exports = {
|
||||
},
|
||||
|
||||
fillSpace: function() {
|
||||
if (!this.refs.messageWrapper) return;
|
||||
var messageWrapper = this.refs.messageWrapper.getDOMNode();
|
||||
if (messageWrapper.scrollTop < messageWrapper.clientHeight && this.state.room.oldState.paginationToken) {
|
||||
this.setState({paginating: true});
|
||||
@@ -278,7 +271,6 @@ module.exports = {
|
||||
var items = ev.dataTransfer.items;
|
||||
if (items.length == 1) {
|
||||
if (items[0].kind == 'file') {
|
||||
this.setState({ draggingFile : true });
|
||||
ev.dataTransfer.dropEffect = 'copy';
|
||||
}
|
||||
}
|
||||
@@ -287,19 +279,12 @@ module.exports = {
|
||||
onDrop: function(ev) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
this.setState({ draggingFile : false });
|
||||
var files = ev.dataTransfer.files;
|
||||
if (files.length == 1) {
|
||||
this.uploadFile(files[0]);
|
||||
}
|
||||
},
|
||||
|
||||
onDragLeaveOrEnd: function(ev) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
this.setState({ draggingFile : false });
|
||||
},
|
||||
|
||||
uploadFile: function(file) {
|
||||
this.setState({
|
||||
upload: {
|
||||
@@ -367,8 +352,7 @@ module.exports = {
|
||||
}
|
||||
if (!TileType) continue;
|
||||
ret.unshift(
|
||||
// XXX: don't wrap everything in a needless li - make the TileType a li if we must :(
|
||||
<li key={mxEv.getId()}><TileType mxEvent={mxEv} continuation={continuation} last={last}/></li>
|
||||
<TileType key={mxEv.getId()} mxEvent={mxEv} continuation={continuation} last={last}/>
|
||||
);
|
||||
if (dateSeparator) {
|
||||
ret.unshift(dateSeparator);
|
||||
|
||||
@@ -23,11 +23,9 @@ var MatrixClientPeg = require("../../MatrixClientPeg");
|
||||
var RoomListSorter = require("../../RoomListSorter");
|
||||
var Presence = require("../../Presence");
|
||||
var dis = require("../../dispatcher");
|
||||
var q = require("q");
|
||||
|
||||
var ComponentBroker = require('../../ComponentBroker');
|
||||
var Notifier = ComponentBroker.get('organisms/Notifier');
|
||||
var MatrixTools = require('../../MatrixTools');
|
||||
|
||||
module.exports = {
|
||||
PageTypes: {
|
||||
@@ -138,20 +136,7 @@ module.exports = {
|
||||
currentRoom: payload.room_id,
|
||||
page_type: this.PageTypes.RoomView,
|
||||
});
|
||||
if (this.sdkReady) {
|
||||
// if the SDK is not ready yet, remember what room
|
||||
// we're supposed to be on but don't notify about
|
||||
// the new screen yet (we won't be showing it yet)
|
||||
// The normal case where this happens is navigating
|
||||
// to the room in the URL bar on page load.
|
||||
var presentedId = payload.room_id;
|
||||
var room = MatrixClientPeg.get().getRoom(payload.room_id);
|
||||
if (room) {
|
||||
var theAlias = MatrixTools.getCanonicalAliasForRoom(room);
|
||||
if (theAlias) presentedId = theAlias;
|
||||
}
|
||||
this.notifyNewScreen('room/'+presentedId);
|
||||
}
|
||||
this.notifyNewScreen('room/'+payload.room_id);
|
||||
break;
|
||||
case 'view_prev_room':
|
||||
roomIndexDelta = -1;
|
||||
@@ -167,26 +152,11 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
roomIndex = (roomIndex + roomIndexDelta) % allRooms.length;
|
||||
if (roomIndex < 0) roomIndex = allRooms.length - 1;
|
||||
this.focusComposer = true;
|
||||
this.setState({
|
||||
currentRoom: allRooms[roomIndex].roomId
|
||||
});
|
||||
this.notifyNewScreen('room/'+allRooms[roomIndex].roomId);
|
||||
break;
|
||||
case 'view_indexed_room':
|
||||
var allRooms = RoomListSorter.mostRecentActivityFirst(
|
||||
MatrixClientPeg.get().getRooms()
|
||||
);
|
||||
var roomIndex = payload.roomIndex;
|
||||
if (allRooms[roomIndex]) {
|
||||
this.focusComposer = true;
|
||||
this.setState({
|
||||
currentRoom: allRooms[roomIndex].roomId
|
||||
});
|
||||
this.notifyNewScreen('room/'+allRooms[roomIndex].roomId);
|
||||
}
|
||||
break;
|
||||
case 'view_user_settings':
|
||||
this.setState({
|
||||
page_type: this.PageTypes.UserSettings,
|
||||
@@ -221,30 +191,20 @@ module.exports = {
|
||||
var cli = MatrixClientPeg.get();
|
||||
var self = this;
|
||||
cli.on('syncComplete', function() {
|
||||
self.sdkReady = true;
|
||||
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, page_type: self.PageTypes.RoomView});
|
||||
self.setState({ready: true, currentRoom: firstRoom});
|
||||
self.notifyNewScreen('room/'+firstRoom);
|
||||
} else {
|
||||
self.setState({ready: true, page_type: self.PageTypes.RoomDirectory});
|
||||
self.setState({ready: true});
|
||||
}
|
||||
} else {
|
||||
self.setState({ready: true, currentRoom: self.state.currentRoom});
|
||||
self.setState({ready: true});
|
||||
}
|
||||
|
||||
// we notifyNewScreen now because now the room will actually be displayed,
|
||||
// and (mostly) now we can get the correct alias.
|
||||
var presentedId = self.state.currentRoom;
|
||||
var room = MatrixClientPeg.get().getRoom(self.state.currentRoom);
|
||||
if (room) {
|
||||
var theAlias = MatrixTools.getCanonicalAliasForRoom(room);
|
||||
if (theAlias) presentedId = theAlias;
|
||||
}
|
||||
self.notifyNewScreen('room/'+presentedId);
|
||||
dis.dispatch({action: 'focus_composer'});
|
||||
});
|
||||
cli.on('Call.incoming', function(call) {
|
||||
@@ -260,25 +220,14 @@ module.exports = {
|
||||
|
||||
onKeyDown: function(ev) {
|
||||
if (ev.altKey) {
|
||||
if (ev.ctrlKey && ev.keyCode > 48 && ev.keyCode < 58) {
|
||||
dis.dispatch({
|
||||
action: 'view_indexed_room',
|
||||
roomIndex: ev.keyCode - 49,
|
||||
});
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
return;
|
||||
}
|
||||
switch (ev.keyCode) {
|
||||
case 38:
|
||||
dis.dispatch({action: 'view_prev_room'});
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
break;
|
||||
case 40:
|
||||
dis.dispatch({action: 'view_next_room'});
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -300,26 +249,10 @@ module.exports = {
|
||||
params: params
|
||||
});
|
||||
} else if (screen.indexOf('room/') == 0) {
|
||||
var roomString = screen.split('/')[1];
|
||||
var defer = q.defer();
|
||||
if (roomString[0] == '#') {
|
||||
var self = this;
|
||||
MatrixClientPeg.get().getRoomIdForAlias(roomString).done(function(result) {
|
||||
if (self.sdkReady) self.setState({ready: true});
|
||||
defer.resolve(result.room_id);
|
||||
}, function() {
|
||||
if (self.sdkReady) self.setState({ready: true});
|
||||
defer.resolve(null);
|
||||
});
|
||||
this.setState({ready: false});
|
||||
} else {
|
||||
defer.resolve(roomString);
|
||||
}
|
||||
defer.promise.done(function(roomId) {
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: roomId
|
||||
});
|
||||
var roomId = screen.split('/')[1];
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: roomId
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -71,17 +71,10 @@ module.exports = {
|
||||
|
||||
var formVals = this.getFormVals();
|
||||
|
||||
var loginParams = {
|
||||
password: formVals.password
|
||||
};
|
||||
if (formVals.username.indexOf('@') > 0) {
|
||||
loginParams.medium = 'email';
|
||||
loginParams.address = formVals.username;
|
||||
} else {
|
||||
loginParams.user = formVals.username;
|
||||
}
|
||||
|
||||
MatrixClientPeg.get().login('m.login.password', loginParams).done(function(data) {
|
||||
MatrixClientPeg.get().login('m.login.password', {
|
||||
'user': formVals.username,
|
||||
'password': formVals.password
|
||||
}).done(function(data) {
|
||||
MatrixClientPeg.replaceUsingAccessToken(
|
||||
self.state.hs_url, self.state.is_url,
|
||||
data.user_id, data.access_token
|
||||
@@ -91,11 +84,7 @@ module.exports = {
|
||||
}
|
||||
}, function(error) {
|
||||
self.setStep("stage_m.login.password");
|
||||
if (error.httpStatus == 400 && loginParams.medium) {
|
||||
self.setState({errorText: 'This Home Server does not support login using email address.'});
|
||||
} else {
|
||||
self.setState({errorText: 'Login failed.'});
|
||||
}
|
||||
self.setState({errorText: 'Login failed.'});
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user