diff --git a/package.json b/package.json index 7151aef8..532a5383 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js index a7833b3d..e128d07e 100644 --- a/src/controllers/organisms/RoomView.js +++ b/src/controllers/organisms/RoomView.js @@ -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 } diff --git a/src/skins/vector/css/atoms/MemberAvatar.css b/src/skins/vector/css/atoms/MemberAvatar.css index b8ecdef6..b7ea015b 100644 --- a/src/skins/vector/css/atoms/MemberAvatar.css +++ b/src/skins/vector/css/atoms/MemberAvatar.css @@ -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 { diff --git a/src/skins/vector/css/atoms/RoomAvatar.css b/src/skins/vector/css/atoms/RoomAvatar.css index f54a93ee..01425190 100644 --- a/src/skins/vector/css/atoms/RoomAvatar.css +++ b/src/skins/vector/css/atoms/RoomAvatar.css @@ -22,4 +22,5 @@ limitations under the License. color: #fff; text-align: center; font-weight: normal ! important; + speak: none; } \ No newline at end of file diff --git a/src/skins/vector/css/atoms/Spinner.css b/src/skins/vector/css/atoms/Spinner.css index 1c8aa97d..b2a04607 100644 --- a/src/skins/vector/css/atoms/Spinner.css +++ b/src/skins/vector/css/atoms/Spinner.css @@ -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; } \ No newline at end of file diff --git a/src/skins/vector/css/common.css b/src/skins/vector/css/common.css index a68d190d..121fbca7 100644 --- a/src/skins/vector/css/common.css +++ b/src/skins/vector/css/common.css @@ -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; diff --git a/src/skins/vector/css/molecules/MessageComposer.css b/src/skins/vector/css/molecules/MessageComposer.css index 2dbe05b5..fbbeef64 100644 --- a/src/skins/vector/css/molecules/MessageComposer.css +++ b/src/skins/vector/css/molecules/MessageComposer.css @@ -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; diff --git a/src/skins/vector/css/molecules/RoomHeader.css b/src/skins/vector/css/molecules/RoomHeader.css index e86bab2e..5519c14d 100644 --- a/src/skins/vector/css/molecules/RoomHeader.css +++ b/src/skins/vector/css/molecules/RoomHeader.css @@ -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; diff --git a/src/skins/vector/css/molecules/RoomTile.css b/src/skins/vector/css/molecules/RoomTile.css index 4bc71cb8..37d2e1b6 100644 --- a/src/skins/vector/css/molecules/RoomTile.css +++ b/src/skins/vector/css/molecules/RoomTile.css @@ -104,9 +104,7 @@ limitations under the License. } .mx_RoomTile_unread, -.mx_RoomTile_highlight, -.mx_RoomTile_selected -{ +.mx_RoomTile_highlight { font-weight: bold; } diff --git a/src/skins/vector/css/organisms/RoomView.css b/src/skins/vector/css/organisms/RoomView.css index 191742f5..94fff290 100644 --- a/src/skins/vector/css/organisms/RoomView.css +++ b/src/skins/vector/css/organisms/RoomView.css @@ -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; } diff --git a/src/skins/vector/css/pages/MatrixChat.css b/src/skins/vector/css/pages/MatrixChat.css index e6d7d30b..b95f6a41 100644 --- a/src/skins/vector/css/pages/MatrixChat.css +++ b/src/skins/vector/css/pages/MatrixChat.css @@ -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. diff --git a/src/skins/vector/css/templates/Login.css b/src/skins/vector/css/templates/Login.css index 93cb7433..11fba43f 100644 --- a/src/skins/vector/css/templates/Login.css +++ b/src/skins/vector/css/templates/Login.css @@ -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 { diff --git a/src/skins/vector/views/atoms/MemberAvatar.js b/src/skins/vector/views/atoms/MemberAvatar.js index 9d632d72..26b66004 100644 --- a/src/skins/vector/views/atoms/MemberAvatar.js +++ b/src/skins/vector/views/atoms/MemberAvatar.js @@ -50,7 +50,7 @@ module.exports = React.createClass({ return ( - diff --git a/src/skins/vector/views/atoms/RoomAvatar.js b/src/skins/vector/views/atoms/RoomAvatar.js index f61b6cec..bdd28bad 100644 --- a/src/skins/vector/views/atoms/RoomAvatar.js +++ b/src/skins/vector/views/atoms/RoomAvatar.js @@ -57,7 +57,7 @@ module.exports = React.createClass({ return ( - diff --git a/src/skins/vector/views/molecules/ChangeAvatar.js b/src/skins/vector/views/molecules/ChangeAvatar.js index 42c2d1fd..7afac77f 100644 --- a/src/skins/vector/views/molecules/ChangeAvatar.js +++ b/src/skins/vector/views/molecules/ChangeAvatar.js @@ -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({ ); case this.Phases.Uploading: + var Loader = sdk.getComponent("atoms.Spinner"); return ( ); diff --git a/src/skins/vector/views/molecules/ChangeDisplayName.js b/src/skins/vector/views/molecules/ChangeDisplayName.js index 1a094ec2..a10ba2a7 100644 --- a/src/skins/vector/views/molecules/ChangeDisplayName.js +++ b/src/skins/vector/views/molecules/ChangeDisplayName.js @@ -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 ( ); diff --git a/src/skins/vector/views/molecules/ChangePassword.js b/src/skins/vector/views/molecules/ChangePassword.js index 32315158..b1d8f28e 100644 --- a/src/skins/vector/views/molecules/ChangePassword.js +++ b/src/skins/vector/views/molecules/ChangePassword.js @@ -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({ ); case this.Phases.Uploading: + var Loader = sdk.getComponent("atoms.Spinner"); return (
diff --git a/src/skins/vector/views/molecules/MFileTile.js b/src/skins/vector/views/molecules/MFileTile.js index f7e8991f..9180bd6b 100644 --- a/src/skins/vector/views/molecules/MFileTile.js +++ b/src/skins/vector/views/molecules/MFileTile.js @@ -30,15 +30,25 @@ module.exports = React.createClass({ var content = this.props.mxEvent.getContent(); var cli = MatrixClientPeg.get(); - return ( - - + var httpUrl = cli.mxcUrlToHttp(content.url); + var text = this.presentableTextForFile(content); + + if (httpUrl) { + return ( + + + + ); + } else { + var extra = text ? ': '+text : ''; + return + Invalid file{extra} - ); + } }, }); diff --git a/src/skins/vector/views/molecules/MImageTile.js b/src/skins/vector/views/molecules/MImageTile.js index 0667dabd..2f3b7a55 100644 --- a/src/skins/vector/views/molecules/MImageTile.js +++ b/src/skins/vector/views/molecules/MImageTile.js @@ -73,18 +73,33 @@ module.exports = React.createClass({ var imgStyle = {}; if (thumbHeight) imgStyle['height'] = thumbHeight; - return ( - - - {content.body} - - - - ); + + + ); + } else if (content.body) { + return ( + + Image '{content.body}' cannot be displayed. + + ); + } else { + return ( + + This image cannot be displayed. + + ); + } }, }); diff --git a/src/skins/vector/views/molecules/MatrixToolbar.js b/src/skins/vector/views/molecules/MatrixToolbar.js index 361e39d6..5b613f56 100644 --- a/src/skins/vector/views/molecules/MatrixToolbar.js +++ b/src/skins/vector/views/molecules/MatrixToolbar.js @@ -34,7 +34,6 @@ module.exports = React.createClass({ }, render: function() { - var EnableNotificationsButton = sdk.getComponent("atoms.EnableNotificationsButton"); return (
/!\ diff --git a/src/skins/vector/views/molecules/MemberInfo.js b/src/skins/vector/views/molecules/MemberInfo.js index 5f8e806d..24fa1e91 100644 --- a/src/skins/vector/views/molecules/MemberInfo.js +++ b/src/skins/vector/views/molecules/MemberInfo.js @@ -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 = ; } diff --git a/src/skins/vector/views/molecules/MessageComposer.js b/src/skins/vector/views/molecules/MessageComposer.js index c75aaa14..2f0e7ac5 100644 --- a/src/skins/vector/views/molecules/MessageComposer.js +++ b/src/skins/vector/views/molecules/MessageComposer.js @@ -61,7 +61,7 @@ module.exports = React.createClass({
-