diff --git a/karma.conf.js b/karma.conf.js index e59a6c9e15..89437c203a 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -99,7 +99,10 @@ module.exports = function (config) { path.resolve('./test'), ], query: { - presets: ['react', 'es2015'] + // we're using react 5, for consistency with + // the release build, which doesn't use the + // presets. + // presets: ['react', 'es2015'], }, }, ], diff --git a/package.json b/package.json index 7c4bd714ef..c259700c92 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "highlight.js": "^8.9.1", "linkifyjs": "^2.0.0-beta.4", "marked": "^0.3.5", - "matrix-js-sdk": "^0.5.1", + "matrix-js-sdk": "matrix-org/matrix-js-sdk#develop", "optimist": "^0.6.1", "q": "^1.4.1", "react": "^0.14.2", @@ -40,13 +40,15 @@ "velocity-animate": "^1.2.3", "velocity-ui-pack": "^1.2.2" }, + "//babelversion": [ + "brief experiments with babel6 seems to show that it generates source ", + "maps which confuse chrome and make setting breakpoints tricky. So ", + "let's stick with v5 for now." + ], "devDependencies": { "babel": "^5.8.23", - "babel-core": "^6.7.4", - "babel-loader": "^6.2.4", - "babel-preset-es2015": "^6.6.0", - "babel-preset-react": "^6.5.0", - "babel-runtime": "^6.6.1", + "babel-core": "^5.8.38", + "babel-loader": "^5.4.0", "expect": "^1.16.0", "json-loader": "^0.5.3", "karma": "^0.13.22", diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index 82aea0bb76..dbcb59a20a 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -27,7 +27,7 @@ var sanitizeHtmlParams = { 'del', // for markdown // deliberately no h1/h2 to stop people shouting. 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', - 'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div', + 'nl', 'li', 'b', 'i', 'u', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div', 'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre' ], allowedAttributes: { diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 94bd5d6b8f..52313430d4 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -448,6 +448,20 @@ module.exports = React.createClass({ }); }, + onMemberAvatarClick: function () { + var avatarUrl = this.props.member.user.avatarUrl; + if(!avatarUrl) return; + + var httpUrl = MatrixClientPeg.get().mxcUrlToHttp(avatarUrl); + var ImageView = sdk.getComponent("elements.ImageView"); + var params = { + src: httpUrl, + name: this.props.member.name + }; + + Modal.createDialog(ImageView, params, "mx_Dialog_lightbox"); + }, + render: function() { var startChat, kickButton, banButton, muteButton, giveModButton, spinner; if (this.props.member.userId !== MatrixClientPeg.get().credentials.userId) { @@ -508,7 +522,7 @@ module.exports = React.createClass({
- +

{ this.props.member.name }

diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 7d5ce473d6..6d26e7884d 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -17,6 +17,7 @@ var React = require('react'); var CallHandler = require('../../../CallHandler'); var MatrixClientPeg = require('../../../MatrixClientPeg'); +var Modal = require('../../../Modal'); var sdk = require('../../../index'); var dis = require('../../../dispatcher'); @@ -47,11 +48,40 @@ module.exports = React.createClass({ onUploadFileSelected: function(ev) { var files = ev.target.files; - // MessageComposer shouldn't have to rely on its parent passing in a callback to upload a file - if (files && files.length > 0) { - this.props.uploadFile(files[0]); + + var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + var TintableSvg = sdk.getComponent("elements.TintableSvg"); + + var fileList = []; + for(var i=0; i + {files[i].name} + ); } - this.refs.uploadInput.value = null; + + Modal.createDialog(QuestionDialog, { + title: "Upload Files", + description: ( +
+

Are you sure you want upload the following files?

+
    + {fileList} +
+
+ ), + onFinished: (shouldUpload) => { + if(shouldUpload) { + // MessageComposer shouldn't have to rely on its parent passing in a callback to upload a file + if (files) { + for(var i=0; i
); diff --git a/test/components/structures/MessagePanel-test.js b/test/components/structures/MessagePanel-test.js index 3e984e8134..f775388617 100644 --- a/test/components/structures/MessagePanel-test.js +++ b/test/components/structures/MessagePanel-test.js @@ -91,11 +91,13 @@ describe('MessagePanel', function () { var tiles = TestUtils.scryRenderedComponentsWithType( mp, sdk.getComponent('rooms.EventTile')); + var tileContainers = tiles.map(function (t) { + return ReactDOM.findDOMNode(t).parentNode; + }); // find the
  • which wraps the read marker var rm = TestUtils.findRenderedDOMComponentWithClass(mp, 'mx_RoomView_myReadMarker_container'); - var eventContainer = ReactDOM.findDOMNode(tiles[4]).parentNode; - expect(rm.previousSibling).toEqual(eventContainer); + expect(rm.previousSibling).toEqual(tileContainers[4]); // now move the RM mp = ReactDOM.render( @@ -108,18 +110,11 @@ describe('MessagePanel', function () { expect(found.length).toEqual(2); // the first should be the ghost - var ghost = found[0]; - eventContainer = ReactDOM.findDOMNode(tiles[4]).parentNode; - expect(ghost.previousSibling).toEqual(eventContainer); - var hr = ghost.children[0]; - - // the first should be the ghost - eventContainer = ReactDOM.findDOMNode(tiles[4]).parentNode; - expect(found[0].previousSibling).toEqual(eventContainer); + expect(found[0].previousSibling).toEqual(tileContainers[4]); + var hr = found[0].children[0]; // the second should be the real thing - eventContainer = ReactDOM.findDOMNode(tiles[4]).parentNode; - expect(ghost.previousSibling).toEqual(eventContainer); + expect(found[1].previousSibling).toEqual(tileContainers[6]); // advance the clock, and then let the browser run an animation frame, // to let the animation start