Merge branch 'develop' into matthew/preview_urls
This commit is contained in:
commit
f195d2eb24
6 changed files with 70 additions and 25 deletions
|
@ -99,7 +99,10 @@ module.exports = function (config) {
|
||||||
path.resolve('./test'),
|
path.resolve('./test'),
|
||||||
],
|
],
|
||||||
query: {
|
query: {
|
||||||
presets: ['react', 'es2015']
|
// we're using react 5, for consistency with
|
||||||
|
// the release build, which doesn't use the
|
||||||
|
// presets.
|
||||||
|
// presets: ['react', 'es2015'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
14
package.json
14
package.json
|
@ -30,7 +30,7 @@
|
||||||
"highlight.js": "^8.9.1",
|
"highlight.js": "^8.9.1",
|
||||||
"linkifyjs": "^2.0.0-beta.4",
|
"linkifyjs": "^2.0.0-beta.4",
|
||||||
"marked": "^0.3.5",
|
"marked": "^0.3.5",
|
||||||
"matrix-js-sdk": "^0.5.1",
|
"matrix-js-sdk": "matrix-org/matrix-js-sdk#develop",
|
||||||
"optimist": "^0.6.1",
|
"optimist": "^0.6.1",
|
||||||
"q": "^1.4.1",
|
"q": "^1.4.1",
|
||||||
"react": "^0.14.2",
|
"react": "^0.14.2",
|
||||||
|
@ -40,13 +40,15 @@
|
||||||
"velocity-animate": "^1.2.3",
|
"velocity-animate": "^1.2.3",
|
||||||
"velocity-ui-pack": "^1.2.2"
|
"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": {
|
"devDependencies": {
|
||||||
"babel": "^5.8.23",
|
"babel": "^5.8.23",
|
||||||
"babel-core": "^6.7.4",
|
"babel-core": "^5.8.38",
|
||||||
"babel-loader": "^6.2.4",
|
"babel-loader": "^5.4.0",
|
||||||
"babel-preset-es2015": "^6.6.0",
|
|
||||||
"babel-preset-react": "^6.5.0",
|
|
||||||
"babel-runtime": "^6.6.1",
|
|
||||||
"expect": "^1.16.0",
|
"expect": "^1.16.0",
|
||||||
"json-loader": "^0.5.3",
|
"json-loader": "^0.5.3",
|
||||||
"karma": "^0.13.22",
|
"karma": "^0.13.22",
|
||||||
|
|
|
@ -27,7 +27,7 @@ var sanitizeHtmlParams = {
|
||||||
'del', // for markdown
|
'del', // for markdown
|
||||||
// deliberately no h1/h2 to stop people shouting.
|
// deliberately no h1/h2 to stop people shouting.
|
||||||
'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
|
'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'
|
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre'
|
||||||
],
|
],
|
||||||
allowedAttributes: {
|
allowedAttributes: {
|
||||||
|
|
|
@ -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() {
|
render: function() {
|
||||||
var startChat, kickButton, banButton, muteButton, giveModButton, spinner;
|
var startChat, kickButton, banButton, muteButton, giveModButton, spinner;
|
||||||
if (this.props.member.userId !== MatrixClientPeg.get().credentials.userId) {
|
if (this.props.member.userId !== MatrixClientPeg.get().credentials.userId) {
|
||||||
|
@ -508,7 +522,7 @@ module.exports = React.createClass({
|
||||||
<div className="mx_MemberInfo">
|
<div className="mx_MemberInfo">
|
||||||
<img className="mx_MemberInfo_cancel" src="img/cancel.svg" width="18" height="18" onClick={this.onCancel}/>
|
<img className="mx_MemberInfo_cancel" src="img/cancel.svg" width="18" height="18" onClick={this.onCancel}/>
|
||||||
<div className="mx_MemberInfo_avatar">
|
<div className="mx_MemberInfo_avatar">
|
||||||
<MemberAvatar member={this.props.member} width={48} height={48} />
|
<MemberAvatar onClick={this.onMemberAvatarClick} member={this.props.member} width={48} height={48} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>{ this.props.member.name }</h2>
|
<h2>{ this.props.member.name }</h2>
|
||||||
|
|
|
@ -17,6 +17,7 @@ var React = require('react');
|
||||||
|
|
||||||
var CallHandler = require('../../../CallHandler');
|
var CallHandler = require('../../../CallHandler');
|
||||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||||
|
var Modal = require('../../../Modal');
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
var dis = require('../../../dispatcher');
|
var dis = require('../../../dispatcher');
|
||||||
|
|
||||||
|
@ -47,11 +48,40 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
onUploadFileSelected: function(ev) {
|
onUploadFileSelected: function(ev) {
|
||||||
var files = ev.target.files;
|
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) {
|
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
this.props.uploadFile(files[0]);
|
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||||
|
|
||||||
|
var fileList = [];
|
||||||
|
for(var i=0; i<files.length; i++) {
|
||||||
|
fileList.push(<li>
|
||||||
|
<TintableSvg src="img/files.svg" width="16" height="16" /> {files[i].name}
|
||||||
|
</li>);
|
||||||
}
|
}
|
||||||
this.refs.uploadInput.value = null;
|
|
||||||
|
Modal.createDialog(QuestionDialog, {
|
||||||
|
title: "Upload Files",
|
||||||
|
description: (
|
||||||
|
<div>
|
||||||
|
<p>Are you sure you want upload the following files?</p>
|
||||||
|
<ul style={{listStyle: 'none', textAlign: 'left'}}>
|
||||||
|
{fileList}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
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<files.length; i++) {
|
||||||
|
this.props.uploadFile(files[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refs.uploadInput.value = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onHangupClick: function() {
|
onHangupClick: function() {
|
||||||
|
@ -130,6 +160,7 @@ module.exports = React.createClass({
|
||||||
<TintableSvg src="img/upload.svg" width="19" height="24"/>
|
<TintableSvg src="img/upload.svg" width="19" height="24"/>
|
||||||
<input ref="uploadInput" type="file"
|
<input ref="uploadInput" type="file"
|
||||||
style={uploadInputStyle}
|
style={uploadInputStyle}
|
||||||
|
multiple
|
||||||
onChange={this.onUploadFileSelected} />
|
onChange={this.onUploadFileSelected} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -91,11 +91,13 @@ describe('MessagePanel', function () {
|
||||||
|
|
||||||
var tiles = TestUtils.scryRenderedComponentsWithType(
|
var tiles = TestUtils.scryRenderedComponentsWithType(
|
||||||
mp, sdk.getComponent('rooms.EventTile'));
|
mp, sdk.getComponent('rooms.EventTile'));
|
||||||
|
var tileContainers = tiles.map(function (t) {
|
||||||
|
return ReactDOM.findDOMNode(t).parentNode;
|
||||||
|
});
|
||||||
|
|
||||||
// find the <li> which wraps the read marker
|
// find the <li> which wraps the read marker
|
||||||
var rm = TestUtils.findRenderedDOMComponentWithClass(mp, 'mx_RoomView_myReadMarker_container');
|
var rm = TestUtils.findRenderedDOMComponentWithClass(mp, 'mx_RoomView_myReadMarker_container');
|
||||||
var eventContainer = ReactDOM.findDOMNode(tiles[4]).parentNode;
|
expect(rm.previousSibling).toEqual(tileContainers[4]);
|
||||||
expect(rm.previousSibling).toEqual(eventContainer);
|
|
||||||
|
|
||||||
// now move the RM
|
// now move the RM
|
||||||
mp = ReactDOM.render(
|
mp = ReactDOM.render(
|
||||||
|
@ -108,18 +110,11 @@ describe('MessagePanel', function () {
|
||||||
expect(found.length).toEqual(2);
|
expect(found.length).toEqual(2);
|
||||||
|
|
||||||
// the first should be the ghost
|
// the first should be the ghost
|
||||||
var ghost = found[0];
|
expect(found[0].previousSibling).toEqual(tileContainers[4]);
|
||||||
eventContainer = ReactDOM.findDOMNode(tiles[4]).parentNode;
|
var hr = found[0].children[0];
|
||||||
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);
|
|
||||||
|
|
||||||
// the second should be the real thing
|
// the second should be the real thing
|
||||||
eventContainer = ReactDOM.findDOMNode(tiles[4]).parentNode;
|
expect(found[1].previousSibling).toEqual(tileContainers[6]);
|
||||||
expect(ghost.previousSibling).toEqual(eventContainer);
|
|
||||||
|
|
||||||
// advance the clock, and then let the browser run an animation frame,
|
// advance the clock, and then let the browser run an animation frame,
|
||||||
// to let the animation start
|
// to let the animation start
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue