Merge branch 'release-v0.12.7'

This commit is contained in:
David Baker 2018-06-12 14:23:48 +01:00
commit 13d52065f5
27 changed files with 1363 additions and 202 deletions

View file

@ -432,11 +432,14 @@ export default React.createClass({
this._changeAvatarComponent = null;
this._initGroupStore(this.props.groupId, true);
this._dispatcherRef = dis.register(this._onAction);
},
componentWillUnmount: function() {
this._unmounted = true;
this._matrixClient.removeListener("Group.myMembership", this._onGroupMyMembership);
dis.unregister(this._dispatcherRef);
},
componentWillReceiveProps: function(newProps) {
@ -563,12 +566,22 @@ export default React.createClass({
this._closeSettings();
},
_onAction(payload) {
switch (payload.action) {
// NOTE: close_settings is an app-wide dispatch; as it is dispatched from MatrixChat
case 'close_settings':
this.setState({
editing: false,
profileForm: null,
});
break;
default:
break;
}
},
_closeSettings() {
this.setState({
editing: false,
profileForm: null,
});
dis.dispatch({action: 'panel_disable'});
dis.dispatch({action: 'close_settings'});
},
_onNameChange: function(value) {

View file

@ -255,6 +255,22 @@ const LoggedInView = React.createClass({
), true);
},
_onClick: function(ev) {
// When the panels are disabled, clicking on them results in a mouse event
// which bubbles to certain elements in the tree. When this happens, close
// any settings page that is currently open (user/room/group).
if (this.props.leftDisabled &&
this.props.rightDisabled &&
(
ev.target.className === 'mx_MatrixChat' ||
ev.target.className === 'mx_MatrixChat_middlePanel' ||
ev.target.className === 'mx_RoomView'
)
) {
dis.dispatch({ action: 'close_settings' });
}
},
render: function() {
const LeftPanel = sdk.getComponent('structures.LeftPanel');
const RightPanel = sdk.getComponent('structures.RightPanel');
@ -295,7 +311,7 @@ const LoggedInView = React.createClass({
case PageTypes.UserSettings:
page_element = <UserSettings
onClose={this.props.onUserSettingsClose}
onClose={this.props.onCloseAllSettings}
brand={this.props.config.brand}
referralBaseUrl={this.props.config.referralBaseUrl}
teamToken={this.props.teamToken}
@ -380,7 +396,7 @@ const LoggedInView = React.createClass({
}
return (
<div className='mx_MatrixChat_wrapper' aria-hidden={this.props.hideToSRUsers}>
<div className='mx_MatrixChat_wrapper' aria-hidden={this.props.hideToSRUsers} onClick={this._onClick}>
{ topBar }
<DragDropContext onDragEnd={this._onDragEnd}>
<div className={bodyClasses}>

View file

@ -398,6 +398,9 @@ export default React.createClass({
},
startPageChangeTimer() {
// Tor doesn't support performance
if (!performance || !performance.mark) return null;
// This shouldn't happen because componentWillUpdate and componentDidUpdate
// are used.
if (this._pageChanging) {
@ -409,6 +412,9 @@ export default React.createClass({
},
stopPageChangeTimer() {
// Tor doesn't support performance
if (!performance || !performance.mark) return null;
if (!this._pageChanging) {
console.warn('MatrixChat.stopPageChangeTimer: timer not started');
return;
@ -560,6 +566,27 @@ export default React.createClass({
this._setPage(PageTypes.UserSettings);
this.notifyNewScreen('settings');
break;
case 'close_settings':
this.setState({
leftDisabled: false,
rightDisabled: false,
middleDisabled: false,
});
if (this.state.page_type === PageTypes.UserSettings) {
// We do this to get setPage and notifyNewScreen
if (this.state.currentRoomId) {
this._viewRoom({
room_id: this.state.currentRoomId,
});
} else if (this.state.currentGroupId) {
this._viewGroup({
group_id: this.state.currentGroupId,
});
} else {
this._viewHome();
}
}
break;
case 'view_create_room':
this._createRoom();
break;
@ -577,19 +604,10 @@ export default React.createClass({
this.notifyNewScreen('groups');
break;
case 'view_group':
{
const groupId = payload.group_id;
this.setState({
currentGroupId: groupId,
currentGroupIsNew: payload.group_is_new,
});
this._setPage(PageTypes.GroupView);
this.notifyNewScreen('group/' + groupId);
}
this._viewGroup(payload);
break;
case 'view_home_page':
this._setPage(PageTypes.HomePage);
this.notifyNewScreen('home');
this._viewHome();
break;
case 'view_set_mxid':
this._setMxId(payload);
@ -632,7 +650,8 @@ export default React.createClass({
middleDisabled: payload.middleDisabled || false,
rightDisabled: payload.rightDisabled || payload.sideDisabled || false,
});
break; }
break;
}
case 'set_theme':
this._onSetTheme(payload.value);
break;
@ -781,7 +800,6 @@ export default React.createClass({
// @param {string=} roomInfo.room_id ID of the room to join. One of room_id or room_alias must be given.
// @param {string=} roomInfo.room_alias Alias of the room to join. One of room_id or room_alias must be given.
// @param {boolean=} roomInfo.auto_join If true, automatically attempt to join the room if not already a member.
// @param {boolean=} roomInfo.show_settings Makes RoomView show the room settings dialog.
// @param {string=} roomInfo.event_id ID of the event in this room to show: this will cause a switch to the
// context of that particular event.
// @param {boolean=} roomInfo.highlighted If true, add event_id to the hash of the URL
@ -848,6 +866,21 @@ export default React.createClass({
});
},
_viewGroup: function(payload) {
const groupId = payload.group_id;
this.setState({
currentGroupId: groupId,
currentGroupIsNew: payload.group_is_new,
});
this._setPage(PageTypes.GroupView);
this.notifyNewScreen('group/' + groupId);
},
_viewHome: function() {
this._setPage(PageTypes.HomePage);
this.notifyNewScreen('home');
},
_setMxId: function(payload) {
const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog');
const close = Modal.createTrackedDialog('Set MXID', '', SetMxIdDialog, {
@ -1606,19 +1639,8 @@ export default React.createClass({
this._setPageSubtitle(subtitle);
},
onUserSettingsClose: function() {
// XXX: use browser history instead to find the previous room?
// or maintain a this.state.pageHistory in _setPage()?
if (this.state.currentRoomId) {
dis.dispatch({
action: 'view_room',
room_id: this.state.currentRoomId,
});
} else {
dis.dispatch({
action: 'view_home_page',
});
}
onCloseAllSettings() {
dis.dispatch({ action: 'close_settings' });
},
onServerConfigChange(config) {
@ -1677,7 +1699,7 @@ export default React.createClass({
return (
<LoggedInView ref={this._collectLoggedInView} matrixClient={MatrixClientPeg.get()}
onRoomCreated={this.onRoomCreated}
onUserSettingsClose={this.onUserSettingsClose}
onCloseAllSettings={this.onCloseAllSettings}
onRegistered={this.onRegistered}
currentRoomId={this.state.currentRoomId}
teamToken={this._teamToken}

View file

@ -182,6 +182,7 @@ module.exports = React.createClass({
isInitialEventHighlighted: RoomViewStore.isInitialEventHighlighted(),
forwardingEvent: RoomViewStore.getForwardingEvent(),
shouldPeek: RoomViewStore.shouldPeek(),
editingRoomSettings: RoomViewStore.isEditingSettings(),
};
// Temporary logging to diagnose https://github.com/vector-im/riot-web/issues/4307
@ -1139,7 +1140,7 @@ module.exports = React.createClass({
},
onSettingsClick: function() {
this.showSettings(true);
dis.dispatch({ action: 'open_room_settings' });
},
onSettingsSaveClick: function() {
@ -1172,24 +1173,20 @@ module.exports = React.createClass({
});
// still editing room settings
} else {
this.setState({
editingRoomSettings: false,
});
dis.dispatch({ action: 'close_settings' });
}
}).finally(() => {
this.setState({
uploadingRoomSettings: false,
editingRoomSettings: false,
});
dis.dispatch({ action: 'close_settings' });
}).done();
},
onCancelClick: function() {
console.log("updateTint from onCancelClick");
this.updateTint();
this.setState({
editingRoomSettings: false,
});
dis.dispatch({ action: 'close_settings' });
if (this.state.forwardingEvent) {
dis.dispatch({
action: 'forward_event',
@ -1406,13 +1403,6 @@ module.exports = React.createClass({
});*/
},
showSettings: function(show) {
// XXX: this is a bit naughty; we should be doing this via props
if (show) {
this.setState({editingRoomSettings: true});
}
},
/**
* called by the parent component when PageUp/Down/etc is pressed.
*

View file

@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import url from 'url';
import { _t } from '../../../languageHandler';
import WidgetUtils from "../../../WidgetUtils";
export default class AppPermission extends React.Component {
constructor(props) {
@ -19,7 +20,7 @@ export default class AppPermission extends React.Component {
const searchParams = new URLSearchParams(wurl.search);
if (this.isScalarWurl(wurl) && searchParams && searchParams.get('url')) {
if (WidgetUtils.isScalarUrl(wurl) && searchParams && searchParams.get('url')) {
curl = url.parse(searchParams.get('url'));
if (curl) {
curl.search = curl.query = "";
@ -33,19 +34,6 @@ export default class AppPermission extends React.Component {
return curlString;
}
isScalarWurl(wurl) {
if (wurl && wurl.hostname && (
wurl.hostname === 'scalar.vector.im' ||
wurl.hostname === 'scalar-staging.riot.im' ||
wurl.hostname === 'scalar-develop.riot.im' ||
wurl.hostname === 'demo.riot.im' ||
wurl.hostname === 'localhost'
)) {
return true;
}
return false;
}
render() {
let e2eWarningText;
if (this.props.isRoomEncrypted) {

View file

@ -25,7 +25,6 @@ import PlatformPeg from '../../../PlatformPeg';
import ScalarAuthClient from '../../../ScalarAuthClient';
import WidgetMessaging from '../../../WidgetMessaging';
import TintableSvgButton from './TintableSvgButton';
import SdkConfig from '../../../SdkConfig';
import Modal from '../../../Modal';
import { _t, _td } from '../../../languageHandler';
import sdk from '../../../index';
@ -121,39 +120,6 @@ export default class AppTile extends React.Component {
return u.format();
}
/**
* Returns true if specified url is a scalar URL, typically https://scalar.vector.im/api
* @param {[type]} testUrlString URL to check
* @return {Boolean} True if specified URL is a scalar URL
*/
isScalarUrl(testUrlString) {
if (!testUrlString) {
console.error('Scalar URL check failed. No URL specified');
return false;
}
const testUrl = url.parse(testUrlString);
let scalarUrls = SdkConfig.get().integrations_widgets_urls;
if (!scalarUrls || scalarUrls.length == 0) {
scalarUrls = [SdkConfig.get().integrations_rest_url];
}
for (let i = 0; i < scalarUrls.length; i++) {
const scalarUrl = url.parse(scalarUrls[i]);
if (testUrl && scalarUrl) {
if (
testUrl.protocol === scalarUrl.protocol &&
testUrl.host === scalarUrl.host &&
testUrl.pathname.startsWith(scalarUrl.pathname)
) {
return true;
}
}
}
return false;
}
isMixedContent() {
const parentContentProtocol = window.location.protocol;
const u = url.parse(this.props.url);
@ -209,7 +175,7 @@ export default class AppTile extends React.Component {
setScalarToken() {
this.setState({initialising: true});
if (!this.isScalarUrl(this.props.url)) {
if (!WidgetUtils.isScalarUrl(this.props.url)) {
console.warn('Non-scalar widget, not setting scalar token!', url);
this.setState({
error: null,

View file

@ -17,6 +17,7 @@ limitations under the License.
import TagTile from './TagTile';
import React from 'react';
import { Draggable } from 'react-beautiful-dnd';
export default function DNDTagTile(props) {

View file

@ -39,6 +39,19 @@ module.exports = React.createClass({
componentDidMount: function() {
this._updatePinnedMessages();
MatrixClientPeg.get().on("RoomState.events", this._onStateEvent);
},
componentWillUnmount: function() {
if (MatrixClientPeg.get()) {
MatrixClientPeg.get().removeListener("RoomState.events", this._onStateEvent);
}
},
_onStateEvent: function(ev) {
if (ev.getRoomId() === this.props.room.roomId && ev.getType() === "m.room.pinned_events") {
this._updatePinnedMessages();
}
},
_updatePinnedMessages: function() {

View file

@ -395,7 +395,17 @@ module.exports = React.createClass({
powerLevels["events"] = Object.assign({}, this.state.powerLevels["events"] || {});
powerLevels["events"][powerLevelKey.slice(eventsLevelPrefix.length)] = value;
} else {
powerLevels[powerLevelKey] = value;
const keyPath = powerLevelKey.split('.');
let parentObj;
let currentObj = powerLevels;
for (const key of keyPath) {
if (!currentObj[key]) {
currentObj[key] = {};
}
parentObj = currentObj;
currentObj = currentObj[key];
}
parentObj[keyPath[keyPath.length - 1]] = value;
}
this.setState({
powerLevels,
@ -664,6 +674,10 @@ module.exports = React.createClass({
desc: _t('To remove other users\' messages, you must be a'),
defaultValue: 50,
},
"notifications.room": {
desc: _t('To notify everyone in the room, you must be a'),
defaultValue: 50,
},
};
const banLevel = parseIntWithDefault(powerLevels.ban, powerLevelDescriptors.ban.defaultValue);
@ -865,7 +879,16 @@ module.exports = React.createClass({
const powerSelectors = Object.keys(powerLevelDescriptors).map((key, index) => {
const descriptor = powerLevelDescriptors[key];
const value = parseIntWithDefault(powerLevels[key], descriptor.defaultValue);
const keyPath = key.split('.');
let currentObj = powerLevels;
for (const prop of keyPath) {
if (currentObj === undefined) {
break;
}
currentObj = currentObj[prop];
}
const value = parseIntWithDefault(currentObj, descriptor.defaultValue);
return <div key={index} className="mx_RoomSettings_powerLevel">
<span className="mx_RoomSettings_powerLevelKey">
{ descriptor.desc }