Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
0601d65af7
7 changed files with 148 additions and 15 deletions
|
@ -34,7 +34,14 @@ export function getRoomNotifsState(roomId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// for everything else, look at the room rule.
|
// for everything else, look at the room rule.
|
||||||
const roomRule = MatrixClientPeg.get().getRoomPushRule('global', roomId);
|
let roomRule = null;
|
||||||
|
try {
|
||||||
|
roomRule = MatrixClientPeg.get().getRoomPushRule('global', roomId);
|
||||||
|
} catch (err) {
|
||||||
|
// Possible that the client doesn't have pushRules yet. If so, it
|
||||||
|
// hasn't started eiher, so indicate that this room is not notifying.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// XXX: We have to assume the default is to notify for all messages
|
// XXX: We have to assume the default is to notify for all messages
|
||||||
// (in particular this will be 'wrong' for one to one rooms because
|
// (in particular this will be 'wrong' for one to one rooms because
|
||||||
|
@ -130,6 +137,11 @@ function setRoomNotifsStateUnmuted(roomId, newState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function findOverrideMuteRule(roomId) {
|
function findOverrideMuteRule(roomId) {
|
||||||
|
if (!MatrixClientPeg.get().pushRules ||
|
||||||
|
!MatrixClientPeg.get().pushRules['global'] ||
|
||||||
|
!MatrixClientPeg.get().pushRules['global'].override) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
for (const rule of MatrixClientPeg.get().pushRules['global'].override) {
|
for (const rule of MatrixClientPeg.get().pushRules['global'].override) {
|
||||||
if (isRuleForRoom(roomId, rule)) {
|
if (isRuleForRoom(roomId, rule)) {
|
||||||
if (isMuteRule(rule) && rule.enabled) {
|
if (isMuteRule(rule) && rule.enabled) {
|
||||||
|
|
|
@ -44,6 +44,7 @@ const TagPanel = React.createClass({
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
this.unmounted = false;
|
this.unmounted = false;
|
||||||
this.context.matrixClient.on("Group.myMembership", this._onGroupMyMembership);
|
this.context.matrixClient.on("Group.myMembership", this._onGroupMyMembership);
|
||||||
|
this.context.matrixClient.on("sync", this.onClientSync);
|
||||||
|
|
||||||
this._tagOrderStoreToken = TagOrderStore.addListener(() => {
|
this._tagOrderStoreToken = TagOrderStore.addListener(() => {
|
||||||
if (this.unmounted) {
|
if (this.unmounted) {
|
||||||
|
@ -61,6 +62,7 @@ const TagPanel = React.createClass({
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.unmounted = true;
|
this.unmounted = true;
|
||||||
this.context.matrixClient.removeListener("Group.myMembership", this._onGroupMyMembership);
|
this.context.matrixClient.removeListener("Group.myMembership", this._onGroupMyMembership);
|
||||||
|
this.context.matrixClient.removeListener("sync", this.onClientSync);
|
||||||
if (this._filterStoreToken) {
|
if (this._filterStoreToken) {
|
||||||
this._filterStoreToken.remove();
|
this._filterStoreToken.remove();
|
||||||
}
|
}
|
||||||
|
@ -71,6 +73,16 @@ const TagPanel = React.createClass({
|
||||||
dis.dispatch(GroupActions.fetchJoinedGroups(this.context.matrixClient));
|
dis.dispatch(GroupActions.fetchJoinedGroups(this.context.matrixClient));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onClientSync(syncState, prevState) {
|
||||||
|
// Consider the client reconnected if there is no error with syncing.
|
||||||
|
// This means the state could be RECONNECTING, SYNCING or PREPARED.
|
||||||
|
const reconnected = syncState !== "ERROR" && prevState !== syncState;
|
||||||
|
if (reconnected) {
|
||||||
|
// Load joined groups
|
||||||
|
dis.dispatch(GroupActions.fetchJoinedGroups(this.context.matrixClient));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
onClick(e) {
|
onClick(e) {
|
||||||
// Ignore clicks on children
|
// Ignore clicks on children
|
||||||
if (e.target !== e.currentTarget) return;
|
if (e.target !== e.currentTarget) return;
|
||||||
|
|
|
@ -16,6 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { MatrixClient } from 'matrix-js-sdk';
|
||||||
import AvatarLogic from '../../../Avatar';
|
import AvatarLogic from '../../../Avatar';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
|
@ -36,6 +37,10 @@ module.exports = React.createClass({
|
||||||
defaultToInitialLetter: PropTypes.bool, // true to add default url
|
defaultToInitialLetter: PropTypes.bool, // true to add default url
|
||||||
},
|
},
|
||||||
|
|
||||||
|
contextTypes: {
|
||||||
|
matrixClient: PropTypes.instanceOf(MatrixClient),
|
||||||
|
},
|
||||||
|
|
||||||
getDefaultProps: function() {
|
getDefaultProps: function() {
|
||||||
return {
|
return {
|
||||||
width: 40,
|
width: 40,
|
||||||
|
@ -49,6 +54,16 @@ module.exports = React.createClass({
|
||||||
return this._getState(this.props);
|
return this._getState(this.props);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.unmounted = false;
|
||||||
|
this.context.matrixClient.on('sync', this.onClientSync);
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.unmounted = true;
|
||||||
|
this.context.matrixClient.removeListener('sync', this.onClientSync);
|
||||||
|
},
|
||||||
|
|
||||||
componentWillReceiveProps: function(nextProps) {
|
componentWillReceiveProps: function(nextProps) {
|
||||||
// work out if we need to call setState (if the image URLs array has changed)
|
// work out if we need to call setState (if the image URLs array has changed)
|
||||||
const newState = this._getState(nextProps);
|
const newState = this._getState(nextProps);
|
||||||
|
@ -67,6 +82,23 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onClientSync(syncState, prevState) {
|
||||||
|
if (this.unmounted) return;
|
||||||
|
|
||||||
|
// Consider the client reconnected if there is no error with syncing.
|
||||||
|
// This means the state could be RECONNECTING, SYNCING or PREPARED.
|
||||||
|
const reconnected = syncState !== "ERROR" && prevState !== syncState;
|
||||||
|
if (reconnected &&
|
||||||
|
// Did we fall back?
|
||||||
|
this.state.urlsIndex > 0
|
||||||
|
) {
|
||||||
|
// Start from the highest priority URL again
|
||||||
|
this.setState({
|
||||||
|
urlsIndex: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_getState: function(props) {
|
_getState: function(props) {
|
||||||
// work out the full set of urls to try to load. This is formed like so:
|
// work out the full set of urls to try to load. This is formed like so:
|
||||||
// imageUrls: [ props.url, props.urls, default image ]
|
// imageUrls: [ props.url, props.urls, default image ]
|
||||||
|
|
|
@ -17,7 +17,7 @@ import React from 'react';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
import dis from '../../../dispatcher';
|
import dis from '../../../dispatcher';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Room, RoomMember } from 'matrix-js-sdk';
|
import { Room, RoomMember, MatrixClient } from 'matrix-js-sdk';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||||
import { MATRIXTO_URL_PATTERN } from '../../../linkify-matrix';
|
import { MATRIXTO_URL_PATTERN } from '../../../linkify-matrix';
|
||||||
|
@ -61,6 +61,17 @@ const Pill = React.createClass({
|
||||||
shouldShowPillAvatar: PropTypes.bool,
|
shouldShowPillAvatar: PropTypes.bool,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
childContextTypes: {
|
||||||
|
matrixClient: PropTypes.instanceOf(MatrixClient),
|
||||||
|
},
|
||||||
|
|
||||||
|
getChildContext() {
|
||||||
|
return {
|
||||||
|
matrixClient: this._matrixClient,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return {
|
return {
|
||||||
// ID/alias of the room/user
|
// ID/alias of the room/user
|
||||||
|
@ -135,6 +146,7 @@ const Pill = React.createClass({
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this._unmounted = false;
|
this._unmounted = false;
|
||||||
|
this._matrixClient = MatrixClientPeg.get();
|
||||||
this.componentWillReceiveProps(this.props);
|
this.componentWillReceiveProps(this.props);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,9 @@ limitations under the License.
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { MatrixClient } from 'matrix-js-sdk';
|
||||||
|
|
||||||
import MFileBody from './MFileBody';
|
import MFileBody from './MFileBody';
|
||||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
|
||||||
import ImageUtils from '../../../ImageUtils';
|
import ImageUtils from '../../../ImageUtils';
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
|
@ -40,15 +41,37 @@ module.exports = React.createClass({
|
||||||
onWidgetLoad: PropTypes.func.isRequired,
|
onWidgetLoad: PropTypes.func.isRequired,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
contextTypes: {
|
||||||
|
matrixClient: PropTypes.instanceOf(MatrixClient),
|
||||||
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
decryptedUrl: null,
|
decryptedUrl: null,
|
||||||
decryptedThumbnailUrl: null,
|
decryptedThumbnailUrl: null,
|
||||||
decryptedBlob: null,
|
decryptedBlob: null,
|
||||||
error: null,
|
error: null,
|
||||||
|
imgError: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.unmounted = false;
|
||||||
|
this.context.matrixClient.on('sync', this.onClientSync);
|
||||||
|
},
|
||||||
|
|
||||||
|
onClientSync(syncState, prevState) {
|
||||||
|
if (this.unmounted) return;
|
||||||
|
// Consider the client reconnected if there is no error with syncing.
|
||||||
|
// This means the state could be RECONNECTING, SYNCING or PREPARED.
|
||||||
|
const reconnected = syncState !== "ERROR" && prevState !== syncState;
|
||||||
|
if (reconnected && this.state.imgError) {
|
||||||
|
// Load the image again
|
||||||
|
this.setState({
|
||||||
|
imgError: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
onClick: function onClick(ev) {
|
onClick: function onClick(ev) {
|
||||||
if (ev.button == 0 && !ev.metaKey) {
|
if (ev.button == 0 && !ev.metaKey) {
|
||||||
|
@ -97,12 +120,18 @@ module.exports = React.createClass({
|
||||||
imgElement.src = this._getThumbUrl();
|
imgElement.src = this._getThumbUrl();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onImageError: function() {
|
||||||
|
this.setState({
|
||||||
|
imgError: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
_getContentUrl: function() {
|
_getContentUrl: function() {
|
||||||
const content = this.props.mxEvent.getContent();
|
const content = this.props.mxEvent.getContent();
|
||||||
if (content.file !== undefined) {
|
if (content.file !== undefined) {
|
||||||
return this.state.decryptedUrl;
|
return this.state.decryptedUrl;
|
||||||
} else {
|
} else {
|
||||||
return MatrixClientPeg.get().mxcUrlToHttp(content.url);
|
return this.context.matrixClient.mxcUrlToHttp(content.url);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -115,7 +144,7 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
return this.state.decryptedUrl;
|
return this.state.decryptedUrl;
|
||||||
} else {
|
} else {
|
||||||
return MatrixClientPeg.get().mxcUrlToHttp(content.url, 800, 600);
|
return this.context.matrixClient.mxcUrlToHttp(content.url, 800, 600);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -156,7 +185,9 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
|
this.unmounted = true;
|
||||||
dis.unregister(this.dispatcherRef);
|
dis.unregister(this.dispatcherRef);
|
||||||
|
this.context.matrixClient.removeListener('sync', this.onClientSync);
|
||||||
},
|
},
|
||||||
|
|
||||||
onAction: function(payload) {
|
onAction: function(payload) {
|
||||||
|
@ -217,6 +248,14 @@ module.exports = React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.state.imgError) {
|
||||||
|
return (
|
||||||
|
<span className="mx_MImageBody">
|
||||||
|
{ _t("This image cannot be displayed.") }
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const contentUrl = this._getContentUrl();
|
const contentUrl = this._getContentUrl();
|
||||||
let thumbUrl;
|
let thumbUrl;
|
||||||
if (this._isGif() && SettingsStore.getValue("autoplayGifsAndVideos")) {
|
if (this._isGif() && SettingsStore.getValue("autoplayGifsAndVideos")) {
|
||||||
|
@ -231,6 +270,7 @@ module.exports = React.createClass({
|
||||||
<a href={contentUrl} onClick={this.onClick}>
|
<a href={contentUrl} onClick={this.onClick}>
|
||||||
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref="image"
|
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref="image"
|
||||||
alt={content.body}
|
alt={content.body}
|
||||||
|
onError={this.onImageError}
|
||||||
onLoad={this.props.onWidgetLoad}
|
onLoad={this.props.onWidgetLoad}
|
||||||
onMouseEnter={this.onImageEnter}
|
onMouseEnter={this.onImageEnter}
|
||||||
onMouseLeave={this.onImageLeave} />
|
onMouseLeave={this.onImageLeave} />
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
const expect = require('expect');
|
import expect from 'expect';
|
||||||
const React = require('react');
|
import React from 'react';
|
||||||
const ReactDOM = require("react-dom");
|
import ReactTestUtils from 'react-addons-test-utils';
|
||||||
const ReactTestUtils = require('react-addons-test-utils');
|
import sdk from 'matrix-react-sdk';
|
||||||
const sdk = require('matrix-react-sdk');
|
|
||||||
const MemberEventListSummary = sdk.getComponent('views.elements.MemberEventListSummary');
|
|
||||||
import * as languageHandler from '../../../../src/languageHandler';
|
import * as languageHandler from '../../../../src/languageHandler';
|
||||||
|
import * as testUtils from '../../../test-utils';
|
||||||
|
|
||||||
|
// Give MELS a matrixClient in its child context
|
||||||
|
const MemberEventListSummary = testUtils.wrapInMatrixClientContext(
|
||||||
|
sdk.getComponent('views.elements.MemberEventListSummary'),
|
||||||
|
);
|
||||||
|
|
||||||
const testUtils = require('../../../test-utils');
|
|
||||||
describe('MemberEventListSummary', function() {
|
describe('MemberEventListSummary', function() {
|
||||||
let sandbox;
|
let sandbox;
|
||||||
|
|
||||||
|
@ -113,7 +116,6 @@ describe('MemberEventListSummary', function() {
|
||||||
renderer.render(<MemberEventListSummary {...props} />);
|
renderer.render(<MemberEventListSummary {...props} />);
|
||||||
const result = renderer.getRenderOutput();
|
const result = renderer.getRenderOutput();
|
||||||
|
|
||||||
expect(result.type).toBe('div');
|
|
||||||
expect(result.props.children).toEqual([
|
expect(result.props.children).toEqual([
|
||||||
<div className="event_tile" key="event0">Expanded membership</div>,
|
<div className="event_tile" key="event0">Expanded membership</div>,
|
||||||
]);
|
]);
|
||||||
|
@ -136,7 +138,6 @@ describe('MemberEventListSummary', function() {
|
||||||
renderer.render(<MemberEventListSummary {...props} />);
|
renderer.render(<MemberEventListSummary {...props} />);
|
||||||
const result = renderer.getRenderOutput();
|
const result = renderer.getRenderOutput();
|
||||||
|
|
||||||
expect(result.type).toBe('div');
|
|
||||||
expect(result.props.children).toEqual([
|
expect(result.props.children).toEqual([
|
||||||
<div className="event_tile" key="event0">Expanded membership</div>,
|
<div className="event_tile" key="event0">Expanded membership</div>,
|
||||||
<div className="event_tile" key="event1">Expanded membership</div>,
|
<div className="event_tile" key="event1">Expanded membership</div>,
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import Promise from 'bluebird';
|
import Promise from 'bluebird';
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import peg from '../src/MatrixClientPeg';
|
import peg from '../src/MatrixClientPeg';
|
||||||
import dis from '../src/dispatcher';
|
import dis from '../src/dispatcher';
|
||||||
import jssdk from 'matrix-js-sdk';
|
import jssdk from 'matrix-js-sdk';
|
||||||
|
@ -265,3 +266,26 @@ export function getDispatchForStore(store) {
|
||||||
dis._isDispatching = false;
|
dis._isDispatching = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function wrapInMatrixClientContext(WrappedComponent) {
|
||||||
|
class Wrapper extends React.Component {
|
||||||
|
static childContextTypes = {
|
||||||
|
matrixClient: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
getChildContext() {
|
||||||
|
return {
|
||||||
|
matrixClient: this._matrixClient,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this._matrixClient = peg.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <WrappedComponent {...this.props} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Wrapper;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue