diff --git a/res/css/_components.scss b/res/css/_components.scss
index 173939e143..62cdb4533e 100644
--- a/res/css/_components.scss
+++ b/res/css/_components.scss
@@ -39,6 +39,7 @@
@import "./views/dialogs/_EncryptedEventDialog.scss";
@import "./views/dialogs/_GroupAddressPicker.scss";
@import "./views/dialogs/_QuestionDialog.scss";
+@import "./views/dialogs/_RoomUpgradeDialog.scss";
@import "./views/dialogs/_SetEmailDialog.scss";
@import "./views/dialogs/_SetMxIdDialog.scss";
@import "./views/dialogs/_SetPasswordDialog.scss";
@@ -99,6 +100,7 @@
@import "./views/rooms/_RoomSettings.scss";
@import "./views/rooms/_RoomTile.scss";
@import "./views/rooms/_RoomTooltip.scss";
+@import "./views/rooms/_RoomUpgradeWarningBar.scss";
@import "./views/rooms/_SearchBar.scss";
@import "./views/rooms/_SearchableEntityList.scss";
@import "./views/rooms/_Stickers.scss";
diff --git a/res/css/views/dialogs/_RoomUpgradeDialog.scss b/res/css/views/dialogs/_RoomUpgradeDialog.scss
new file mode 100644
index 0000000000..2e3ac5fdea
--- /dev/null
+++ b/res/css/views/dialogs/_RoomUpgradeDialog.scss
@@ -0,0 +1,19 @@
+/*
+Copyright 2018 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_RoomUpgradeDialog {
+ padding-right: 70px;
+}
diff --git a/res/css/views/rooms/_RoomSettings.scss b/res/css/views/rooms/_RoomSettings.scss
index 4013af4c7c..f04042ea77 100644
--- a/res/css/views/rooms/_RoomSettings.scss
+++ b/res/css/views/rooms/_RoomSettings.scss
@@ -20,6 +20,7 @@ limitations under the License.
margin-bottom: 20px;
}
+.mx_RoomSettings_upgradeButton,
.mx_RoomSettings_leaveButton,
.mx_RoomSettings_unbanButton {
@mixin mx_DialogButton;
@@ -27,11 +28,16 @@ limitations under the License.
margin-right: 8px;
}
+.mx_RoomSettings_upgradeButton,
.mx_RoomSettings_leaveButton:hover,
.mx_RoomSettings_unbanButton:hover {
@mixin mx_DialogButton_hover;
}
+.mx_RoomSettings_upgradeButton.danger {
+ @mixin mx_DialogButton_danger;
+}
+
.mx_RoomSettings_integrationsButton_error {
position: relative;
cursor: not-allowed;
diff --git a/res/css/views/rooms/_RoomUpgradeWarningBar.scss b/res/css/views/rooms/_RoomUpgradeWarningBar.scss
new file mode 100644
index 0000000000..82785b82d2
--- /dev/null
+++ b/res/css/views/rooms/_RoomUpgradeWarningBar.scss
@@ -0,0 +1,48 @@
+/*
+Copyright 2018 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_RoomUpgradeWarningBar {
+ text-align: center;
+ height: 176px;
+ background-color: $event-selected-color;
+ align-items: center;
+ flex-direction: column;
+ justify-content: center;
+ display: flex;
+ background-color: $preview-bar-bg-color;
+ -webkit-align-items: center;
+ padding-left: 20px;
+ padding-right: 20px;
+}
+
+.mx_RoomUpgradeWarningBar_header {
+ color: $warning-color;
+ font-weight: bold;
+}
+
+.mx_RoomUpgradeWarningBar_body {
+ color: $warning-color;
+}
+
+.mx_RoomUpgradeWarningBar_upgradelink {
+ color: $warning-color;
+ text-decoration: underline;
+}
+
+.mx_RoomUpgradeWarningBar_small {
+ color: $greyed-fg-color;
+ font-size: 70%;
+}
diff --git a/res/themes/light/css/_base.scss b/res/themes/light/css/_base.scss
index 7d004bd831..c7fd38259c 100644
--- a/res/themes/light/css/_base.scss
+++ b/res/themes/light/css/_base.scss
@@ -171,6 +171,10 @@ $progressbar-color: #000;
outline: none;
}
+@define-mixin mx_DialogButton_danger {
+ background-color: $warning-color;
+}
+
@define-mixin mx_DialogButton_hover {
}
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index 855090873f..5243cd15fa 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -1461,6 +1461,7 @@ module.exports = React.createClass({
const RoomPreviewBar = sdk.getComponent("rooms.RoomPreviewBar");
const Loader = sdk.getComponent("elements.Spinner");
const TimelinePanel = sdk.getComponent("structures.TimelinePanel");
+ const RoomUpgradeWarningBar = sdk.getComponent("rooms.RoomUpgradeWarningBar");
if (!this.state.room) {
if (this.state.roomLoading || this.state.peekLoading) {
@@ -1586,6 +1587,11 @@ module.exports = React.createClass({
/>;
}
+ const showRoomUpgradeBar = (
+ this.state.room.shouldUpgradeToVersion() &&
+ this.state.room.userMayUpgradeRoom(MatrixClientPeg.get().credentials.userId)
+ );
+
let aux = null;
let hideCancel = false;
if (this.state.editingRoomSettings) {
@@ -1597,6 +1603,9 @@ module.exports = React.createClass({
} else if (this.state.searching) {
hideCancel = true; // has own cancel
aux = ;
+ } else if (showRoomUpgradeBar) {
+ aux = ;
+ hideCancel = true;
} else if (this.state.showingPinned) {
hideCancel = true; // has own cancel
aux = ;
diff --git a/src/components/views/dialogs/RoomUpgradeDialog.js b/src/components/views/dialogs/RoomUpgradeDialog.js
new file mode 100644
index 0000000000..936ff745d1
--- /dev/null
+++ b/src/components/views/dialogs/RoomUpgradeDialog.js
@@ -0,0 +1,106 @@
+/*
+Copyright 2018 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from 'react';
+import PropTypes from 'prop-types';
+import sdk from '../../../index';
+import MatrixClientPeg from '../../../MatrixClientPeg';
+import Modal from '../../../Modal';
+import { _t } from '../../../languageHandler';
+
+export default React.createClass({
+ displayName: 'RoomUpgradeDialog',
+
+ propTypes: {
+ room: PropTypes.object.isRequired,
+ onFinished: PropTypes.func.isRequired,
+ },
+
+ componentWillMount: function() {
+ this._targetVersion = this.props.room.shouldUpgradeToVersion();
+ },
+
+ getInitialState: function() {
+ return {
+ busy: false,
+ };
+ },
+
+ _onCancelClick: function() {
+ this.props.onFinished(false);
+ },
+
+ _onUpgradeClick: function() {
+ this.setState({busy: true});
+ MatrixClientPeg.get().upgradeRoom(this.props.room.roomId, this._targetVersion).catch((err) => {
+ const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
+ Modal.createTrackedDialog('Failed to upgrade room', '', ErrorDialog, {
+ title: _t("Failed to upgrade room"),
+ description: ((err && err.message) ? err.message : _t("The room upgrade could not be completed")),
+ });
+ }).finally(() => {
+ this.setState({busy: false});
+ });
+ },
+
+ render: function() {
+ const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
+ const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
+ const Spinner = sdk.getComponent('views.elements.Spinner');
+
+ let buttons;
+ if (this.state.busy) {
+ buttons = ;
+ } else {
+ buttons = ;
+ }
+
+ return (
+
+
+ {_t(
+ "Upgrading this room requires closing down the current " +
+ "instance of the room and creating a new room it its place. " +
+ "To give room members the best possible experience, we will:",
+ )}
+
+
+ - {_t("Create a new room with the same name, description and avatar")}
+ - {_t("Update any local room aliases to point to the new room")}
+ - {_t("Stop users from speaking in the old version of the room, and post a message advising users to move to the new room")}
+ - {_t("Put a link back to the old room at the start of the new room so people can see old messages")}
+
+ {buttons}
+
+ );
+ },
+});
diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js
index 7a78d205b9..aeb55be075 100644
--- a/src/components/views/rooms/RoomSettings.js
+++ b/src/components/views/rooms/RoomSettings.js
@@ -572,6 +572,11 @@ module.exports = React.createClass({
});
},
+ _onRoomUpgradeClick: function() {
+ const RoomUpgradeDialog = sdk.getComponent('dialogs.RoomUpgradeDialog');
+ Modal.createTrackedDialog('Upgrade Room Version', '', RoomUpgradeDialog, {room: this.props.room});
+ },
+
_onRoomMemberMembership: function() {
// Update, since our banned user list may have changed
this.forceUpdate();
@@ -930,6 +935,13 @@ module.exports = React.createClass({
);
});
+ let roomUpgradeButton = null;
+ if (this.props.room.shouldUpgradeToVersion() && this.props.room.userMayUpgradeRoom(myUserId)) {
+ roomUpgradeButton =
+ { _t("Upgrade room to version %(ver)s", {ver: this.props.room.shouldUpgradeToVersion()}) }
+ ;
+ }
+
return (
@@ -1041,7 +1053,8 @@ module.exports = React.createClass({
{ _t('Advanced') }
{ _t('Internal room ID: ') } { this.props.room.roomId }
- { _t('Room version number: ') } { this.props.room.getVersion() }
+ { _t('Room version number: ') } { this.props.room.getVersion() }
+ { roomUpgradeButton }
);
diff --git a/src/components/views/rooms/RoomUpgradeWarningBar.js b/src/components/views/rooms/RoomUpgradeWarningBar.js
new file mode 100644
index 0000000000..a464d95140
--- /dev/null
+++ b/src/components/views/rooms/RoomUpgradeWarningBar.js
@@ -0,0 +1,57 @@
+/*
+Copyright 2018 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from 'react';
+import PropTypes from 'prop-types';
+import sdk from '../../../index';
+import Modal from '../../../Modal';
+
+import { _t } from '../../../languageHandler';
+
+module.exports = React.createClass({
+ displayName: 'RoomUpgardeWarningBar',
+
+ propTypes: {
+ room: PropTypes.object.isRequired,
+ },
+
+ onUpgradeClick: function() {
+ const RoomUpgradeDialog = sdk.getComponent('dialogs.RoomUpgradeDialog');
+ Modal.createTrackedDialog('Upgrade Room Version', '', RoomUpgradeDialog, {room: this.props.room});
+ },
+
+ render: function() {
+ const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
+ return (
+
+
+ {_t("There is a known vulnerability affecting this room.")}
+
+
+ {_t("This room version is vulnerable to malicious modification of room state.")}
+
+
+
+ {_t("Click here to upgrade to the latest room version and ensure room integrity is protected.")}
+
+
+
+ {_t("Only room administrators will see this warning")}
+
+
+ );
+ },
+});
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index fcc9bcc8be..043b90518d 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -205,6 +205,7 @@
"Authentication check failed: incorrect password?": "Authentication check failed: incorrect password?",
"Failed to join room": "Failed to join room",
"Message Pinning": "Message Pinning",
+ "Increase performance by only loading room members on first view": "Increase performance by only loading room members on first view",
"Disable Emoji suggestions while typing": "Disable Emoji suggestions while typing",
"Use compact timeline layout": "Use compact timeline layout",
"Hide removed messages": "Hide removed messages",
@@ -528,6 +529,7 @@
"Guests cannot join this room even if explicitly invited.": "Guests cannot join this room even if explicitly invited.",
"Click here to fix": "Click here to fix",
"To send events of type , you must be a": "To send events of type , you must be a",
+ "Upgrade room to version %(ver)s": "Upgrade room to version %(ver)s",
"Who can access this room?": "Who can access this room?",
"Only people who have been invited": "Only people who have been invited",
"Anyone who knows the room's link, apart from guests": "Anyone who knows the room's link, apart from guests",
@@ -865,6 +867,9 @@
"Ignore request": "Ignore request",
"Loading device info...": "Loading device info...",
"Encryption key request": "Encryption key request",
+ "Failed to upgrade room": "Failed to upgrade room",
+ "The room upgrade could not be completed": "The room upgrade could not be completed",
+ "Upgrade this room to version %(version)s": "Upgrade this room to version %(version)s",
"Upgrade Room Version": "Upgrade Room Version",
"Upgrading this room requires closing down the current instance of the room and creating a new room it its place. To give room members the best possible experience, we will:": "Upgrading this room requires closing down the current instance of the room and creating a new room it its place. To give room members the best possible experience, we will:",
"Create a new room with the same name, description and avatar": "Create a new room with the same name, description and avatar",
@@ -1121,6 +1126,8 @@
"Labs": "Labs",
"These are experimental features that may break in unexpected ways": "These are experimental features that may break in unexpected ways",
"Use with caution": "Use with caution",
+ "Lazy loading members not supported": "Lazy loading members not supported",
+ "Lazy loading is not supported by your current homeserver.": "Lazy loading is not supported by your current homeserver.",
"Deactivate my account": "Deactivate my account",
"Clear Cache": "Clear Cache",
"Clear Cache and Reload": "Clear Cache and Reload",
@@ -1231,8 +1238,5 @@
"Import": "Import",
"Failed to set direct chat tag": "Failed to set direct chat tag",
"Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room",
- "Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room",
- "Increase performance by only loading room members on first view": "Increase performance by only loading room members on first view",
- "Lazy loading members not supported": "Lazy load members not supported",
- "Lazy loading is not supported by your current homeserver.": "Lazy loading is not supported by your current homeserver."
+ "Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room"
}