mirror of
https://github.com/SchildiChat/element-web.git
synced 2024-10-01 01:26:12 -04:00
Merge remote-tracking branch 'origin/develop' into read_receipts
This commit is contained in:
commit
bb59e9276b
@ -37,9 +37,8 @@
|
||||
"react-dnd-html5-backend": "^2.0.0",
|
||||
"react-dom": "^0.14.2",
|
||||
"react-gemini-scrollbar": "^2.0.1",
|
||||
"react-loader": "^1.4.0",
|
||||
"sanitize-html": "^1.0.0",
|
||||
"velocity-animate": "^1.2.3"
|
||||
"sanitize-html": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "^5.8.23",
|
||||
|
@ -61,12 +61,12 @@ module.exports = {
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
if (this.refs.messageWrapper) {
|
||||
var messageWrapper = ReactDOM.findDOMNode(this.refs.messageWrapper);
|
||||
messageWrapper.removeEventListener('drop', this.onDrop);
|
||||
messageWrapper.removeEventListener('dragover', this.onDragOver);
|
||||
messageWrapper.removeEventListener('dragleave', this.onDragLeaveOrEnd);
|
||||
messageWrapper.removeEventListener('dragend', this.onDragLeaveOrEnd);
|
||||
if (this.refs.messagePanel) {
|
||||
var messagePanel = ReactDOM.findDOMNode(this.refs.messagePanel);
|
||||
messagePanel.removeEventListener('drop', this.onDrop);
|
||||
messagePanel.removeEventListener('dragover', this.onDragOver);
|
||||
messagePanel.removeEventListener('dragleave', this.onDragLeaveOrEnd);
|
||||
messagePanel.removeEventListener('dragend', this.onDragLeaveOrEnd);
|
||||
}
|
||||
dis.unregister(this.dispatcherRef);
|
||||
if (MatrixClientPeg.get()) {
|
||||
@ -100,10 +100,9 @@ module.exports = {
|
||||
// Call state has changed so we may be loading video elements
|
||||
// which will obscure the message log.
|
||||
// scroll to bottom
|
||||
var messageWrapper = this.refs.messageWrapper;
|
||||
if (messageWrapper) {
|
||||
var messageWrapperScroll = ReactDOM.findDOMNode(messageWrapper).children[2];
|
||||
messageWrapperScroll.scrollTop = messageWrapperScroll.scrollHeight;
|
||||
var scrollNode = this._getScrollNode();
|
||||
if (scrollNode) {
|
||||
scrollNode.scrollTop = scrollNode.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,6 +116,17 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
_getScrollNode: function() {
|
||||
var panel = ReactDOM.findDOMNode(this.refs.messagePanel);
|
||||
if (!panel) return null;
|
||||
|
||||
if (panel.classList.contains('gm-prevented')) {
|
||||
return panel;
|
||||
} else {
|
||||
return panel.children[2]; // XXX: Fragile!
|
||||
}
|
||||
},
|
||||
|
||||
onSyncStateChange: function(state) {
|
||||
this.setState({
|
||||
syncState: state
|
||||
@ -143,11 +153,11 @@ module.exports = {
|
||||
if (this.state.joining) return;
|
||||
if (room.roomId != this.props.roomId) return;
|
||||
|
||||
if (this.refs.messageWrapper) {
|
||||
var messageWrapperScroll = ReactDOM.findDOMNode(this.refs.messageWrapper).children[2];
|
||||
var scrollNode = this._getScrollNode();
|
||||
if (scrollNode) {
|
||||
this.atBottom = (
|
||||
messageWrapperScroll.scrollHeight - messageWrapperScroll.scrollTop <=
|
||||
(messageWrapperScroll.clientHeight + 150)
|
||||
scrollNode.scrollHeight - scrollNode.scrollTop <=
|
||||
(scrollNode.clientHeight + 150) // 150?
|
||||
);
|
||||
}
|
||||
|
||||
@ -236,15 +246,15 @@ module.exports = {
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
if (this.refs.messageWrapper) {
|
||||
var messageWrapper = ReactDOM.findDOMNode(this.refs.messageWrapper);
|
||||
if (this.refs.messagePanel) {
|
||||
var messagePanel = ReactDOM.findDOMNode(this.refs.messagePanel);
|
||||
|
||||
messageWrapper.addEventListener('drop', this.onDrop);
|
||||
messageWrapper.addEventListener('dragover', this.onDragOver);
|
||||
messageWrapper.addEventListener('dragleave', this.onDragLeaveOrEnd);
|
||||
messageWrapper.addEventListener('dragend', this.onDragLeaveOrEnd);
|
||||
messagePanel.addEventListener('drop', this.onDrop);
|
||||
messagePanel.addEventListener('dragover', this.onDragOver);
|
||||
messagePanel.addEventListener('dragleave', this.onDragLeaveOrEnd);
|
||||
messagePanel.addEventListener('dragend', this.onDragLeaveOrEnd);
|
||||
|
||||
var messageWrapperScroll = messageWrapper.children[2];
|
||||
var messageWrapperScroll = this._getScrollNode();
|
||||
|
||||
messageWrapperScroll.scrollTop = messageWrapperScroll.scrollHeight;
|
||||
|
||||
@ -257,9 +267,9 @@ module.exports = {
|
||||
},
|
||||
|
||||
componentDidUpdate: function() {
|
||||
if (!this.refs.messageWrapper) return;
|
||||
if (!this.refs.messagePanel) return;
|
||||
|
||||
var messageWrapperScroll = ReactDOM.findDOMNode(this.refs.messageWrapper).children[2];
|
||||
var messageWrapperScroll = this._getScrollNode();
|
||||
|
||||
if (this.state.paginating && !this.waiting_for_paginate) {
|
||||
var heightGained = messageWrapperScroll.scrollHeight - this.oldScrollHeight;
|
||||
@ -277,8 +287,8 @@ module.exports = {
|
||||
},
|
||||
|
||||
fillSpace: function() {
|
||||
if (!this.refs.messageWrapper) return;
|
||||
var messageWrapperScroll = ReactDOM.findDOMNode(this.refs.messageWrapper).children[2];
|
||||
if (!this.refs.messagePanel) return;
|
||||
var messageWrapperScroll = this._getScrollNode();
|
||||
if (messageWrapperScroll.scrollTop < messageWrapperScroll.clientHeight && this.state.room.oldState.paginationToken) {
|
||||
this.setState({paginating: true});
|
||||
|
||||
@ -335,10 +345,10 @@ module.exports = {
|
||||
},
|
||||
|
||||
onMessageListScroll: function(ev) {
|
||||
if (this.refs.messageWrapper) {
|
||||
var messageWrapperScroll = ReactDOM.findDOMNode(this.refs.messageWrapper).children[2];
|
||||
if (this.refs.messagePanel) {
|
||||
var messageWrapperScroll = this._getScrollNode();
|
||||
var wasAtBottom = this.atBottom;
|
||||
this.atBottom = messageWrapperScroll.scrollHeight - messageWrapperScroll.scrollTop <= messageWrapperScroll.clientHeight;
|
||||
this.atBottom = messageWrapperScroll.scrollHeight - messageWrapperScroll.scrollTop <= messageWrapperScroll.clientHeight + 1;
|
||||
if (this.atBottom && !wasAtBottom) {
|
||||
this.forceUpdate(); // remove unread msg count
|
||||
}
|
||||
|
@ -17,12 +17,14 @@ limitations under the License.
|
||||
.mx_MemberAvatar_image {
|
||||
z-index: 20;
|
||||
border-radius: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mx_MemberAvatar_initial {
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
speak: none;
|
||||
}
|
||||
|
||||
.mx_MemberAvatar {
|
||||
|
@ -22,4 +22,5 @@ limitations under the License.
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
font-weight: normal ! important;
|
||||
speak: none;
|
||||
}
|
@ -21,5 +21,12 @@ limitations under the License.
|
||||
-webkit-justify-content: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
-webkit-flex: 1;
|
||||
}
|
||||
|
||||
.mx_MatrixChat_middlePanel .mx_Spinner {
|
||||
height: auto;
|
||||
}
|
@ -47,6 +47,14 @@ a:visited {
|
||||
color: #76cfa6;
|
||||
}
|
||||
|
||||
/* XXX: critical hack to GeminiScrollbar to allow them to work in FF 42 and Chrome 48.
|
||||
Stop the scrollbar view from pushing out the container's overall sizing, which causes
|
||||
flexbox to adapt to the new size and cause the view to keep growing.
|
||||
*/
|
||||
.gm-scrollbar-container .gm-scroll-view {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.mx_ContextualMenu_background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@ -99,7 +107,7 @@ a:visited {
|
||||
height: 100%;
|
||||
background-color: #000;
|
||||
opacity: 0.2;
|
||||
z-index: 2000;
|
||||
z-index: 4000;
|
||||
}
|
||||
|
||||
.mx_Dialog_wrapper {
|
||||
@ -124,7 +132,7 @@ a:visited {
|
||||
background-color: #fff;
|
||||
color: #747474;
|
||||
text-align: center;
|
||||
z-index: 2010;
|
||||
z-index: 4010;
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
|
@ -16,29 +16,25 @@ limitations under the License.
|
||||
|
||||
.mx_MessageComposer_wrapper {
|
||||
max-width: 960px;
|
||||
height: 70px;
|
||||
vertical-align: middle;
|
||||
margin: auto;
|
||||
background-color: #fff;
|
||||
border-top: 2px solid #e1dddd;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_row {
|
||||
display: table-row;
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.mx_MessageComposer .mx_MessageComposer_avatar {
|
||||
display: table-cell;
|
||||
padding-left: 10px;
|
||||
padding-right: 28px;
|
||||
height: 70px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mx_MessageComposer .mx_MessageComposer_avatar img {
|
||||
margin-top: 18px;
|
||||
border-radius: 20px;
|
||||
.mx_MessageComposer .mx_MessageComposer_avatar .mx_MemberAvatar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mx_MessageComposer_input {
|
||||
@ -49,17 +45,18 @@ limitations under the License.
|
||||
}
|
||||
|
||||
.mx_MessageComposer_input textarea {
|
||||
display: block;
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
height: 1.2em;
|
||||
padding-top: 0.7em;
|
||||
padding-bottom: 0.7em;
|
||||
padding: 0px;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 6px;
|
||||
border: 0px;
|
||||
resize: none;
|
||||
outline: none;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
box-shadow: none;
|
||||
|
||||
/* needed for FF */
|
||||
font-family: 'Myriad Pro', Helvetica, Arial, Sans-Serif;
|
||||
|
@ -90,9 +90,9 @@ limitations under the License.
|
||||
|
||||
.mx_RoomHeader_simpleHeader {
|
||||
line-height: 83px;
|
||||
color: #76cfa6;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
color: #454545;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
@ -102,7 +102,7 @@ limitations under the License.
|
||||
vertical-align: middle;
|
||||
height: 28px;
|
||||
color: #454545;
|
||||
font-weight: 800;
|
||||
font-weight: bold;
|
||||
font-size: 24px;
|
||||
padding-left: 19px;
|
||||
padding-right: 16px;
|
||||
|
@ -104,9 +104,7 @@ limitations under the License.
|
||||
}
|
||||
|
||||
.mx_RoomTile_unread,
|
||||
.mx_RoomTile_highlight,
|
||||
.mx_RoomTile_selected
|
||||
{
|
||||
.mx_RoomTile_highlight {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
@ -236,8 +236,8 @@ limitations under the License.
|
||||
order: 5;
|
||||
|
||||
width: 100%;
|
||||
-webkit-flex: 0 0 70px;
|
||||
flex: 0 0 70px;
|
||||
-webkit-flex: 0;
|
||||
flex: 0;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,8 @@ limitations under the License.
|
||||
/* XXX: Hack: apparently if you try to nest a flex-box
|
||||
* within a non-flex-box within a flex-box, the height
|
||||
* of the innermost element gets miscalculated if the
|
||||
* parents are both auto.
|
||||
* parents are both auto. Height has to be auto here
|
||||
* for RoomView to correctly fit when the Toolbar is shown.
|
||||
* Ideally we'd launch straight into the RoomView at this
|
||||
* point, but instead we fudge it and make the middlePanel
|
||||
* flex itself.
|
||||
|
@ -17,6 +17,18 @@ limitations under the License.
|
||||
.mx_Login {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
-webkit-justify-content: center;
|
||||
justify-content: center;
|
||||
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.mx_Login h2 {
|
||||
@ -28,8 +40,10 @@ limitations under the License.
|
||||
|
||||
.mx_Login_box {
|
||||
width: 300px;
|
||||
min-height: 450px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
margin: auto;
|
||||
padding-top: 100px;
|
||||
}
|
||||
|
||||
.mx_Login_logo {
|
||||
|
@ -50,7 +50,7 @@ module.exports = React.createClass({
|
||||
|
||||
return (
|
||||
<span className="mx_MemberAvatar" {...this.props}>
|
||||
<span className="mx_MemberAvatar_initial"
|
||||
<span className="mx_MemberAvatar_initial" aria-hidden="true"
|
||||
style={{ fontSize: (this.props.width * 0.75) + "px",
|
||||
width: this.props.width + "px",
|
||||
lineHeight: this.props.height*1.2 + "px" }}>{ initial }</span>
|
||||
|
@ -57,7 +57,7 @@ module.exports = React.createClass({
|
||||
|
||||
return (
|
||||
<span>
|
||||
<span className="mx_RoomAvatar_initial"
|
||||
<span className="mx_RoomAvatar_initial" aria-hidden="true"
|
||||
style={{ fontSize: (this.props.width * 0.75) + "px",
|
||||
width: this.props.width + "px",
|
||||
lineHeight: this.props.height*1.2 + "px" }}>{ initial }</span>
|
||||
|
@ -21,9 +21,6 @@ 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");
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'ChangeAvatar',
|
||||
mixins: [ChangeAvatarController],
|
||||
@ -70,6 +67,7 @@ module.exports = React.createClass({
|
||||
</div>
|
||||
);
|
||||
case this.Phases.Uploading:
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
return (
|
||||
<Loader />
|
||||
);
|
||||
|
@ -20,8 +20,6 @@ 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',
|
||||
@ -39,6 +37,7 @@ module.exports = React.createClass({
|
||||
|
||||
render: function() {
|
||||
if (this.state.busy) {
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
return (
|
||||
<Loader />
|
||||
);
|
||||
|
@ -19,8 +19,6 @@ limitations under the License.
|
||||
var React = require('react');
|
||||
|
||||
var ChangePasswordController = require('matrix-react-sdk/lib/controllers/molecules/ChangePassword')
|
||||
var Loader = require("react-loader");
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'ChangePassword',
|
||||
@ -64,6 +62,7 @@ module.exports = React.createClass({
|
||||
</div>
|
||||
);
|
||||
case this.Phases.Uploading:
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
return (
|
||||
<div className="mx_Dialog_content">
|
||||
<Loader />
|
||||
|
@ -30,15 +30,25 @@ module.exports = React.createClass({
|
||||
var content = this.props.mxEvent.getContent();
|
||||
var cli = MatrixClientPeg.get();
|
||||
|
||||
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>
|
||||
var httpUrl = cli.mxcUrlToHttp(content.url);
|
||||
var text = this.presentableTextForFile(content);
|
||||
|
||||
if (httpUrl) {
|
||||
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 {text}
|
||||
</a>
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
var extra = text ? ': '+text : '';
|
||||
return <span className="mx_MFileTile">
|
||||
Invalid file{extra}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -73,18 +73,33 @@ module.exports = React.createClass({
|
||||
var imgStyle = {};
|
||||
if (thumbHeight) imgStyle['height'] = thumbHeight;
|
||||
|
||||
return (
|
||||
<span className="mx_MImageTile">
|
||||
<a href={cli.mxcUrlToHttp(content.url)} onClick={ this.onClick }>
|
||||
<img className="mx_MImageTile_thumbnail" src={cli.mxcUrlToHttp(content.url, 480, 360)} 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} ({ content.info && content.info.size ? filesize(content.info.size) : "Unknown size" })
|
||||
var thumbUrl = cli.mxcUrlToHttp(content.url, 480, 360);
|
||||
if (thumbUrl) {
|
||||
return (
|
||||
<span className="mx_MImageTile">
|
||||
<a href={cli.mxcUrlToHttp(content.url)} onClick={ this.onClick }>
|
||||
<img className="mx_MImageTile_thumbnail" src={thumbUrl} alt={content.body} style={imgStyle} />
|
||||
</a>
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
<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} ({ content.info && content.info.size ? filesize(content.info.size) : "Unknown size" })
|
||||
</a>
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
} else if (content.body) {
|
||||
return (
|
||||
<span className="mx_MImageTile">
|
||||
Image '{content.body}' cannot be displayed.
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<span className="mx_MImageTile">
|
||||
This image cannot be displayed.
|
||||
</span>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -34,7 +34,6 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var EnableNotificationsButton = sdk.getComponent("atoms.EnableNotificationsButton");
|
||||
return (
|
||||
<div className="mx_MatrixToolbar">
|
||||
<img className="mx_MatrixToolbar_warning" src="img/warning.png" width="28" height="28" alt="/!\"/>
|
||||
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var Loader = require("../atoms/Spinner");
|
||||
|
||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
var sdk = require('matrix-react-sdk')
|
||||
@ -47,6 +46,7 @@ module.exports = React.createClass({
|
||||
}
|
||||
|
||||
if (this.state.creatingRoom) {
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
spinner = <Loader imgClassName="mx_ContextualMenu_spinner"/>;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ module.exports = React.createClass({
|
||||
<MemberAvatar member={me} width={24} height={24} />
|
||||
</div>
|
||||
<div className="mx_MessageComposer_input">
|
||||
<textarea ref="textarea" onKeyDown={this.onKeyDown} placeholder="Type a message..." />
|
||||
<textarea ref="textarea" rows="1" onKeyDown={this.onKeyDown} onKeyUp={this.onKeyUp} placeholder="Type a message..." />
|
||||
</div>
|
||||
<div className="mx_MessageComposer_upload" onClick={this.onUploadClick}>
|
||||
<img src="img/upload.png" width="17" height="22"/>
|
||||
|
@ -43,9 +43,9 @@ var roomTileSource = {
|
||||
originalList: props.roomSubList,
|
||||
originalIndex: props.roomSubList.findRoomTile(props.room).index,
|
||||
targetList: props.roomSubList, // at first target is same as original
|
||||
lastTargetRoom: null,
|
||||
lastYOffset: null,
|
||||
lastYDelta: null,
|
||||
// lastTargetRoom: null,
|
||||
// lastYOffset: null,
|
||||
// lastYDelta: null,
|
||||
};
|
||||
|
||||
if (props.roomSubList.debug) console.log("roomTile beginDrag for " + item.room.roomId);
|
||||
@ -123,7 +123,7 @@ var roomTileTarget = {
|
||||
|
||||
hover: function(props, monitor) {
|
||||
var item = monitor.getItem();
|
||||
var off = monitor.getClientOffset();
|
||||
//var off = monitor.getClientOffset();
|
||||
// console.log("hovering on room " + props.room.roomId + ", isOver=" + monitor.isOver());
|
||||
|
||||
//console.log("item.targetList=" + item.targetList + ", roomSubList=" + props.roomSubList);
|
||||
@ -150,7 +150,7 @@ var roomTileTarget = {
|
||||
|
||||
// stop us from flickering between our droptarget and the previous room.
|
||||
// whenever the cursor changes direction we have to reset the flicker-damping.
|
||||
|
||||
/*
|
||||
var yDelta = off.y - item.lastYOffset;
|
||||
|
||||
if ((yDelta > 0 && item.lastYDelta < 0) ||
|
||||
@ -170,6 +170,7 @@ var roomTileTarget = {
|
||||
|
||||
if (yDelta) item.lastYDelta = yDelta;
|
||||
item.lastYOffset = off.y;
|
||||
*/
|
||||
}
|
||||
else if (switchedTarget) {
|
||||
if (!props.roomSubList.findRoomTile(item.room).room) {
|
||||
@ -216,10 +217,12 @@ var RoomTile = React.createClass({
|
||||
// //console.log("room " + this.props.room.roomId + " has dropTarget clientOffset " + this.props.clientOffset.x + "," + this.props.clientOffset.y);
|
||||
// }
|
||||
|
||||
/*
|
||||
if (this.props.room._dragging) {
|
||||
var RoomDropTarget = sdk.getComponent("molecules.RoomDropTarget");
|
||||
return <RoomDropTarget placeholder={true}/>;
|
||||
}
|
||||
*/
|
||||
|
||||
var myUserId = MatrixClientPeg.get().credentials.userId;
|
||||
var me = this.props.room.currentState.members[myUserId];
|
||||
|
@ -29,10 +29,16 @@ module.exports = React.createClass({
|
||||
showHelpPopup: function() {
|
||||
var ErrorDialog = sdk.getComponent('organisms.ErrorDialog');
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: 'Custom Server Options',
|
||||
description: "You can use the custom server options to log into other Matrix servers by specifying a different Home server URL. This allows you to use Vector with an existing Matrix account on a different Home server. You can also set a cutom Identity server but this will affect people ability to find you if you use a server in a group other than tha main Matrix.org group.",
|
||||
button: "Dismiss",
|
||||
focus: true
|
||||
title: 'Custom Server Options',
|
||||
description: <span>
|
||||
You can use the custom server options to log into other Matrix servers by specifying a different Home server URL.<br/>
|
||||
This allows you to use Vector with an existing Matrix account on a different Home server.<br/>
|
||||
<br/>
|
||||
You can also set a custom Identity server but this will affect people's ability to find you
|
||||
if you use a server in a group other than the main Matrix.org group.
|
||||
</span>,
|
||||
button: "Dismiss",
|
||||
focus: true,
|
||||
});
|
||||
},
|
||||
|
||||
@ -40,9 +46,9 @@ module.exports = React.createClass({
|
||||
return (
|
||||
<div className="mx_ServerConfig">
|
||||
<label className="mx_Login_label mx_ServerConfig_hslabel" htmlFor="hsurl">Home server URL</label>
|
||||
<input className="mx_Login_field" id="hsurl" type="text" value={this.state.hs_url} onChange={this.hsChanged} />
|
||||
<input className="mx_Login_field" id="hsurl" type="text" placeholder={this.state.original_hs_url} value={this.state.hs_url} onChange={this.hsChanged} />
|
||||
<label className="mx_Login_label mx_ServerConfig_islabel" htmlFor="isurl">Identity server URL</label>
|
||||
<input className="mx_Login_field" type="text" value={this.state.is_url} onChange={this.isChanged} />
|
||||
<input className="mx_Login_field" id="isurl" type="text" placeholder={this.state.original_is_url} value={this.state.is_url} onChange={this.isChanged} />
|
||||
<a className="mx_ServerConfig_help" href="#" onClick={this.showHelpPopup}>What does this mean?</a>
|
||||
</div>
|
||||
);
|
||||
|
@ -24,9 +24,6 @@ var sdk = require('matrix-react-sdk')
|
||||
|
||||
var PresetValues = require('matrix-react-sdk/lib/controllers/atoms/create_room/Presets').Presets;
|
||||
|
||||
var Loader = require("react-loader");
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'CreateRoom',
|
||||
mixins: [CreateRoomController],
|
||||
@ -122,6 +119,7 @@ module.exports = React.createClass({
|
||||
render: function() {
|
||||
var curr_phase = this.state.phase;
|
||||
if (curr_phase == this.phases.CREATING) {
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
return (
|
||||
<Loader/>
|
||||
);
|
||||
|
@ -18,7 +18,6 @@ limitations under the License.
|
||||
|
||||
var React = require('react');
|
||||
var classNames = require('classnames');
|
||||
var Loader = require('react-loader');
|
||||
|
||||
var MemberListController = require('matrix-react-sdk/lib/controllers/organisms/MemberList')
|
||||
var GeminiScrollbar = require('react-gemini-scrollbar');
|
||||
@ -78,6 +77,7 @@ module.exports = React.createClass({
|
||||
|
||||
inviteTile: function() {
|
||||
if (this.state.inviting) {
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
return (
|
||||
<Loader />
|
||||
);
|
||||
|
@ -23,8 +23,6 @@ var Modal = require('matrix-react-sdk/lib/Modal');
|
||||
var sdk = require('matrix-react-sdk')
|
||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
|
||||
var Loader = require("react-loader");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomDirectory',
|
||||
|
||||
@ -121,6 +119,7 @@ module.exports = React.createClass({
|
||||
|
||||
render: function() {
|
||||
if (this.state.loading) {
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
return (
|
||||
<div className="mx_RoomDirectory">
|
||||
<Loader />
|
||||
@ -136,7 +135,9 @@ module.exports = React.createClass({
|
||||
<input ref="roomAlias" placeholder="Join a room (e.g. #foo:domain.com)" className="mx_RoomDirectory_input" size="64" onKeyUp={ this.onKeyUp }/>
|
||||
<div className="mx_RoomDirectory_tableWrapper">
|
||||
<table className="mx_RoomDirectory_table">
|
||||
<tr><th width="45%">Room</th><th width="45%">Alias</th><th width="10%">Members</th></tr>
|
||||
<thead>
|
||||
<tr><th width="45%">Room</th><th width="45%">Alias</th><th width="10%">Members</th></tr>
|
||||
</thead>
|
||||
{ this.getRows(this.state.roomAlias) }
|
||||
</table>
|
||||
</div>
|
||||
|
@ -224,7 +224,7 @@ var RoomSubList = React.createClass({
|
||||
room={ room }
|
||||
roomSubList={ self }
|
||||
key={ room.roomId }
|
||||
collapsed={ self.props.collapsed }
|
||||
collapsed={ self.props.collapsed || false}
|
||||
selected={ selected }
|
||||
unread={ self.props.activityMap[room.roomId] === 1 }
|
||||
highlight={ self.props.activityMap[room.roomId] === 2 }
|
||||
@ -265,7 +265,7 @@ var RoomSubList = React.createClass({
|
||||
return connectDropTarget(
|
||||
<div>
|
||||
<h2 onClick={ this.onClick } className="mx_RoomSubList_label">{ this.props.collapsed ? '' : this.props.label }
|
||||
<img className="mx_RoomSubList_chevron" src={ this.state.hidden ? "/img/list-open.png" : "/img/list-close.png" } width="10" height="10"/>
|
||||
<img className="mx_RoomSubList_chevron" src={ this.state.hidden ? "img/list-open.png" : "img/list-close.png" } width="10" height="10"/>
|
||||
</h2>
|
||||
{ subList }
|
||||
</div>
|
||||
|
@ -29,9 +29,6 @@ var filesize = require('filesize');
|
||||
var GeminiScrollbar = require('react-gemini-scrollbar');
|
||||
var RoomViewController = require('../../../../controllers/organisms/RoomView')
|
||||
|
||||
var Loader = require("react-loader");
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomView',
|
||||
mixins: [RoomViewController],
|
||||
@ -104,9 +101,9 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
scrollToBottom: function() {
|
||||
if (!this.refs.messageWrapper) return;
|
||||
var messageWrapper = ReactDOM.findDOMNode(this.refs.messageWrapper).children[2];
|
||||
messageWrapper.scrollTop = messageWrapper.scrollHeight;
|
||||
var scrollNode = this._getScrollNode();
|
||||
if (!scrollNode) return;
|
||||
scrollNode.scrollTop = scrollNode.scrollHeight;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@ -133,6 +130,7 @@ module.exports = React.createClass({
|
||||
var myUserId = MatrixClientPeg.get().credentials.userId;
|
||||
if (this.state.room.currentState.members[myUserId].membership == 'invite') {
|
||||
if (this.state.joining || this.state.rejecting) {
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
return (
|
||||
<div className="mx_RoomView">
|
||||
<Loader />
|
||||
@ -262,6 +260,7 @@ module.exports = React.createClass({
|
||||
aux = <RoomSettings ref="room_settings" onSaveClick={this.onSaveClick} room={this.state.room} />;
|
||||
}
|
||||
else if (this.state.uploadingRoomSettings) {
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
aux = <Loader/>;
|
||||
}
|
||||
else if (this.state.searching) {
|
||||
@ -300,7 +299,7 @@ module.exports = React.createClass({
|
||||
{ conferenceCallNotification }
|
||||
{ aux }
|
||||
</div>
|
||||
<GeminiScrollbar autoshow={true} ref="messageWrapper" className="mx_RoomView_messagePanel" onScroll={ this.onMessageListScroll }>
|
||||
<GeminiScrollbar autoshow={true} ref="messagePanel" className="mx_RoomView_messagePanel" onScroll={ this.onMessageListScroll }>
|
||||
<div className="mx_RoomView_messageListWrapper">
|
||||
{ fileDropTarget }
|
||||
<ol className="mx_RoomView_MessageList" aria-live="polite">
|
||||
@ -316,7 +315,7 @@ module.exports = React.createClass({
|
||||
{statusBar}
|
||||
</div>
|
||||
</div>
|
||||
<MessageComposer room={this.state.room} uploadFile={this.uploadFile} />
|
||||
<MessageComposer room={this.state.room} roomView={this} uploadFile={this.uploadFile} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -19,8 +19,6 @@ var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
|
||||
var UserSettingsController = require('matrix-react-sdk/lib/controllers/organisms/UserSettings')
|
||||
|
||||
var Loader = require("react-loader");
|
||||
|
||||
var Modal = require('matrix-react-sdk/lib/Modal');
|
||||
|
||||
module.exports = React.createClass({
|
||||
@ -68,6 +66,7 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
switch (this.state.phase) {
|
||||
case this.Phases.Loading:
|
||||
return <Loader />
|
||||
|
@ -17,12 +17,11 @@ limitations under the License.
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
|
||||
var sdk = require('matrix-react-sdk')
|
||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
|
||||
var Loader = require("react-loader");
|
||||
|
||||
var LoginController = require('matrix-react-sdk/lib/controllers/templates/Login')
|
||||
|
||||
var config = require('../../../../../config.json');
|
||||
@ -32,20 +31,37 @@ module.exports = React.createClass({
|
||||
mixins: [LoginController],
|
||||
|
||||
getInitialState: function() {
|
||||
// TODO: factor out all localstorage stuff into its own home.
|
||||
// This is common to Login, Register and MatrixClientPeg
|
||||
var localStorage = window.localStorage;
|
||||
var hs_url, is_url;
|
||||
if (localStorage) {
|
||||
hs_url = localStorage.getItem("mx_hs_url");
|
||||
is_url = localStorage.getItem("mx_is_url");
|
||||
}
|
||||
|
||||
return {
|
||||
serverConfigVisible: false
|
||||
customHsUrl: hs_url || config.default_hs_url,
|
||||
customIsUrl: is_url || config.default_is_url,
|
||||
serverConfigVisible: (hs_url && hs_url !== config.default_hs_url ||
|
||||
is_url && is_url !== config.default_is_url)
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
componentDidMount: function() {
|
||||
this.onHSChosen();
|
||||
this.customHsUrl = config.default_hs_url;
|
||||
this.customIsUrl = config.default_is_url;
|
||||
},
|
||||
|
||||
componentDidUpdate: function() {
|
||||
if (!this.state.focusFired && this.refs.user) {
|
||||
this.refs.user.focus();
|
||||
this.setState({ focusFired: true });
|
||||
}
|
||||
},
|
||||
|
||||
getHsUrl: function() {
|
||||
if (this.state.serverConfigVisible) {
|
||||
return this.customHsUrl;
|
||||
return this.state.customHsUrl;
|
||||
} else {
|
||||
return config.default_hs_url;
|
||||
}
|
||||
@ -53,7 +69,7 @@ module.exports = React.createClass({
|
||||
|
||||
getIsUrl: function() {
|
||||
if (this.state.serverConfigVisible) {
|
||||
return this.customIsUrl;
|
||||
return this.state.customIsUrl;
|
||||
} else {
|
||||
return config.default_is_url;
|
||||
}
|
||||
@ -62,7 +78,7 @@ module.exports = React.createClass({
|
||||
onServerConfigVisibleChange: function(ev) {
|
||||
this.setState({
|
||||
serverConfigVisible: ev.target.checked
|
||||
}, this.onHsUrlChanged);
|
||||
}, this.onHSChosen);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -79,16 +95,22 @@ module.exports = React.createClass({
|
||||
var newHsUrl = this.refs.serverConfig.getHsUrl().trim();
|
||||
var newIsUrl = this.refs.serverConfig.getIsUrl().trim();
|
||||
|
||||
if (newHsUrl == this.customHsUrl &&
|
||||
newIsUrl == this.customIsUrl)
|
||||
if (newHsUrl == this.state.customHsUrl &&
|
||||
newIsUrl == this.state.customIsUrl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this.customHsUrl = newHsUrl;
|
||||
this.customIsUrl = newIsUrl;
|
||||
this.setState({
|
||||
customHsUrl: newHsUrl,
|
||||
customIsUrl: newIsUrl,
|
||||
});
|
||||
}
|
||||
|
||||
// XXX: why are we replacing the MatrixClientPeg here when we're about
|
||||
// to do it again 1s later in the setTimeout to onHSChosen? -- matthew
|
||||
// Commenting it out for now to see what breaks.
|
||||
/*
|
||||
MatrixClientPeg.replaceUsingUrls(
|
||||
this.getHsUrl(),
|
||||
this.getIsUrl()
|
||||
@ -97,6 +119,8 @@ module.exports = React.createClass({
|
||||
hs_url: this.getHsUrl(),
|
||||
is_url: this.getIsUrl()
|
||||
});
|
||||
*/
|
||||
|
||||
// XXX: HSes do not have to offer password auth, so we
|
||||
// need to update and maybe show a different component
|
||||
// when a new HS is entered.
|
||||
@ -123,7 +147,7 @@ module.exports = React.createClass({
|
||||
<label className="mx_Login_label" htmlFor="advanced">Use custom server options (advanced)</label>
|
||||
<div style={serverConfigStyle}>
|
||||
<ServerConfig ref="serverConfig"
|
||||
defaultHsUrl={this.customHsUrl} defaultIsUrl={this.customIsUrl}
|
||||
defaultHsUrl={this.state.customHsUrl} defaultIsUrl={this.state.customIsUrl}
|
||||
onHsUrlChanged={this.onHsUrlChanged}
|
||||
/>
|
||||
</div>
|
||||
@ -158,6 +182,7 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
loginContent: function() {
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
var loader = this.state.busy ? <div className="mx_Login_loader"><Loader /></div> : null;
|
||||
return (
|
||||
<div>
|
||||
|
@ -21,8 +21,6 @@ var React = require('react');
|
||||
var sdk = require('matrix-react-sdk')
|
||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg')
|
||||
|
||||
var Loader = require("react-loader");
|
||||
|
||||
var RegisterController = require('../../../../controllers/templates/Register')
|
||||
|
||||
var config = require('../../../../../config.json');
|
||||
@ -32,14 +30,28 @@ module.exports = React.createClass({
|
||||
mixins: [RegisterController],
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
serverConfigVisible: false
|
||||
};
|
||||
},
|
||||
// TODO: factor out all localstorage stuff into its own home.
|
||||
// This is common to Login, Register and MatrixClientPeg
|
||||
var localStorage = window.localStorage;
|
||||
var hs_url, is_url;
|
||||
if (localStorage) {
|
||||
hs_url = localStorage.getItem("mx_hs_url");
|
||||
is_url = localStorage.getItem("mx_is_url");
|
||||
}
|
||||
|
||||
componentWillMount: function() {
|
||||
this.customHsUrl = config.default_hs_url;
|
||||
this.customIsUrl = config.default_is_url;
|
||||
// make sure we have our MatrixClient set up whatever
|
||||
// Useful for debugging only.
|
||||
// MatrixClientPeg.replaceUsingUrls(
|
||||
// hs_url || config.default_hs_url,
|
||||
// is_url || config.default_is_url
|
||||
// );
|
||||
|
||||
return {
|
||||
customHsUrl: hs_url || config.default_hs_url,
|
||||
customIsUrl: is_url || config.default_is_url,
|
||||
serverConfigVisible: (hs_url && hs_url !== config.default_hs_url ||
|
||||
is_url && is_url !== config.default_is_url)
|
||||
}
|
||||
},
|
||||
|
||||
getRegFormVals: function() {
|
||||
@ -53,7 +65,7 @@ module.exports = React.createClass({
|
||||
|
||||
getHsUrl: function() {
|
||||
if (this.state.serverConfigVisible) {
|
||||
return this.customHsUrl;
|
||||
return this.state.customHsUrl;
|
||||
} else {
|
||||
return config.default_hs_url;
|
||||
}
|
||||
@ -61,7 +73,7 @@ module.exports = React.createClass({
|
||||
|
||||
getIsUrl: function() {
|
||||
if (this.state.serverConfigVisible) {
|
||||
return this.customIsUrl;
|
||||
return this.state.customIsUrl;
|
||||
} else {
|
||||
return config.default_is_url;
|
||||
}
|
||||
@ -74,8 +86,10 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
onServerUrlChanged: function(newUrl) {
|
||||
this.customHsUrl = this.refs.serverConfig.getHsUrl();
|
||||
this.customIsUrl = this.refs.serverConfig.getIsUrl();
|
||||
this.setState({
|
||||
customHsUrl: this.refs.serverConfig.getHsUrl(),
|
||||
customIsUrl: this.refs.serverConfig.getIsUrl(),
|
||||
});
|
||||
this.forceUpdate();
|
||||
},
|
||||
|
||||
@ -92,16 +106,16 @@ module.exports = React.createClass({
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={this.onInitialStageSubmit}>
|
||||
<input className="mx_Login_field" type="text" ref="email" placeholder="Email address" defaultValue={this.savedParams.email} /><br />
|
||||
<input className="mx_Login_field" type="text" ref="email" autoFocus={true} placeholder="Email address" defaultValue={this.savedParams.email} /><br />
|
||||
<input className="mx_Login_field" type="text" ref="username" placeholder="User name" defaultValue={this.savedParams.username} /><br />
|
||||
<input className="mx_Login_field" type="password" ref="password" placeholder="Password" defaultValue={this.savedParams.password} /><br />
|
||||
<input className="mx_Login_field" type="password" ref="confirmPassword" placeholder="Confirm password" defaultValue={this.savedParams.confirmPassword} /><br />
|
||||
|
||||
<input className="mx_Login_checkbox" id="advanced" type="checkbox" value={this.state.serverConfigVisible} onChange={this.onServerConfigVisibleChange} />
|
||||
<input className="mx_Login_checkbox" id="advanced" type="checkbox" checked={this.state.serverConfigVisible} onChange={this.onServerConfigVisibleChange} />
|
||||
<label htmlFor="advanced">Use custom server options (advanced)</label>
|
||||
<div style={serverConfigStyle}>
|
||||
<ServerConfig ref="serverConfig"
|
||||
defaultHsUrl={this.customHsUrl} defaultIsUrl={this.customIsUrl}
|
||||
defaultHsUrl={this.state.customHsUrl} defaultIsUrl={this.state.customIsUrl}
|
||||
onHsUrlChanged={this.onServerUrlChanged} onIsUrlChanged={this.onServerUrlChanged} />
|
||||
</div>
|
||||
<br />
|
||||
@ -128,6 +142,7 @@ module.exports = React.createClass({
|
||||
|
||||
registerContent: function() {
|
||||
if (this.state.busy) {
|
||||
var Loader = sdk.getComponent("atoms.Spinner");
|
||||
return (
|
||||
<Loader />
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user