diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js
index 9e10c012..73e2aeba 100644
--- a/src/components/structures/RoomSubList.js
+++ b/src/components/structures/RoomSubList.js
@@ -88,6 +88,7 @@ var RoomSubList = React.createClass({
searchFilter: React.PropTypes.string,
emptyContent: React.PropTypes.node, // content shown if the list is empty
headerItems: React.PropTypes.node, // content shown in the sublist header
+ extraTiles: React.PropTypes.arrayOf(React.PropTypes.node), // extra elements added beneath tiles
},
getInitialState: function() {
@@ -102,6 +103,7 @@ var RoomSubList = React.createClass({
return {
onHeaderClick: function() {}, // NOP
onShowMoreRooms: function() {}, // NOP
+ extraTiles: [],
isInvite: false,
};
},
@@ -534,13 +536,14 @@ var RoomSubList = React.createClass({
var label = this.props.collapsed ? null : this.props.label;
let content;
- if (this.state.sortedList.length == 0 && !this.props.searchFilter) {
+ if (this.state.sortedList.length == 0 && !this.props.searchFilter && !this.props.extraTiles) {
content = this.props.emptyContent;
} else {
content = this.makeRoomTiles();
+ content.push(...this.props.extraTiles);
}
- if (this.state.sortedList.length > 0 || this.props.editable) {
+ if (this.state.sortedList.length > 0 || this.props.extraTiles.length > 0 || this.props.editable) {
var subList;
var classes = "mx_RoomSubList";
diff --git a/src/components/views/dialogs/DevtoolsDialog.js b/src/components/views/dialogs/DevtoolsDialog.js
new file mode 100644
index 00000000..9c5948b4
--- /dev/null
+++ b/src/components/views/dialogs/DevtoolsDialog.js
@@ -0,0 +1,350 @@
+/*
+Copyright 2017 Michael Telatynski <7t3chguy@gmail.com>
+
+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 sdk from 'matrix-react-sdk';
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
+import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
+
+class SendCustomEvent extends React.Component {
+ static propTypes = {
+ roomId: React.PropTypes.string.isRequired,
+ onBack: React.PropTypes.func.isRequired,
+
+ eventType: React.PropTypes.string.isRequired,
+ evContent: React.PropTypes.string.isRequired,
+ };
+
+ static defaultProps = {
+ eventType: '',
+ evContent: '{\n\n}',
+ };
+
+ constructor(props, context) {
+ super(props, context);
+ this._send = this._send.bind(this);
+ this.onBack = this.onBack.bind(this);
+ this._onChange = this._onChange.bind(this);
+
+ this.state = {
+ message: null,
+ input_eventType: this.props.eventType,
+ input_evContent: this.props.evContent,
+ };
+ }
+
+ onBack() {
+ if (this.state.message) {
+ this.setState({ message: null });
+ } else {
+ this.props.onBack();
+ }
+ }
+
+ _buttons() {
+ return
+ { _t('Back') }
+ {!this.state.message && { _t('Send') } }
+
;
+ }
+
+ send(content) {
+ return MatrixClientPeg.get().sendEvent(this.props.roomId, this.state.input_eventType, content);
+ }
+
+ async _send() {
+ if (this.state.input_eventType === '') {
+ this.setState({ message: _t('You must specify an event type!') });
+ return;
+ }
+
+ let message;
+ try {
+ const content = JSON.parse(this.state.input_evContent);
+ await this.send(content);
+ message = _t('Event sent!');
+ } catch (e) {
+ message = _t('Failed to send custom event.') + ' (' + e.toString() + ')';
+ }
+ this.setState({ message });
+ }
+
+ _additionalFields() {
+ return
;
+ }
+
+ _onChange(e) {
+ this.setState({[`input_${e.target.id}`]: e.target.value});
+ }
+
+ render() {
+ if (this.state.message) {
+ return
+
+ {this.state.message}
+
+ {this._buttons()}
+
;
+ }
+
+ return
+
+ {this._additionalFields()}
+
+ { _t('Event Type') }
+
+
+
+
+
+
+ { _t('Event Content') }
+
+
+
+
+
+ {this._buttons()}
+
;
+ }
+}
+
+class SendCustomStateEvent extends SendCustomEvent {
+ static propTypes = {
+ roomId: React.PropTypes.string.isRequired,
+ onBack: React.PropTypes.func.isRequired,
+
+ eventType: React.PropTypes.string.isRequired,
+ evContent: React.PropTypes.string.isRequired,
+ stateKey: React.PropTypes.string.isRequired,
+ };
+
+ static defaultProps = {
+ eventType: '',
+ evContent: '{\n\n}',
+ stateKey: '',
+ };
+
+ constructor(props, context) {
+ super(props, context);
+ this.state['input_stateKey'] = this.props.stateKey;
+ }
+
+ send(content) {
+ const cli = MatrixClientPeg.get();
+ return cli.sendStateEvent(this.props.roomId, this.state.input_eventType, content, this.state.input_stateKey);
+ }
+
+ _additionalFields() {
+ return
+
+ { _t('State Key') }
+
+
+
+
+
;
+ }
+}
+
+class RoomStateExplorer extends React.Component {
+ static propTypes = {
+ setMode: React.PropTypes.func.isRequired,
+ roomId: React.PropTypes.string.isRequired,
+ onBack: React.PropTypes.func.isRequired,
+ };
+
+ constructor(props, context) {
+ super(props, context);
+
+ const room = MatrixClientPeg.get().getRoom(this.props.roomId);
+ this.roomStateEvents = room.currentState.events;
+
+ this.onBack = this.onBack.bind(this);
+ this.editEv = this.editEv.bind(this);
+ this.onQuery = this.onQuery.bind(this);
+ }
+
+ state = {
+ query: '',
+ eventType: null,
+ event: null,
+ };
+
+ browseEventType(eventType) {
+ return () => {
+ this.setState({ eventType });
+ };
+ }
+
+ onViewSourceClick(event) {
+ return () => {
+ this.setState({ event });
+ };
+ }
+
+ onBack() {
+ if (this.state.event) {
+ this.setState({ event: null });
+ } else if (this.state.eventType) {
+ this.setState({ eventType: null });
+ } else {
+ this.props.onBack();
+ }
+ }
+
+ editEv() {
+ const ev = this.state.event;
+ this.props.setMode(SendCustomStateEvent, {
+ eventType: ev.getType(),
+ evContent: JSON.stringify(ev.getContent(), null, '\t'),
+ stateKey: ev.getStateKey(),
+ });
+ }
+
+ onQuery(ev) {
+ this.setState({ query: ev.target.value });
+ }
+
+ render() {
+ if (this.state.event) {
+ return
+
+
{JSON.stringify(this.state.event.event, null, 2)}
+
+
+ { _t('Back') }
+ { _t('Edit') }
+
+
;
+ }
+
+ const rows = [];
+
+ if (this.state.eventType === null) {
+ Object.keys(this.roomStateEvents).forEach((evType) => {
+ // Skip this entry if does not contain search query
+ if (this.state.query && !evType.includes(this.state.query)) return;
+
+ const stateGroup = this.roomStateEvents[evType];
+ const stateKeys = Object.keys(stateGroup);
+
+ let onClickFn;
+ if (stateKeys.length > 1) {
+ onClickFn = this.browseEventType(evType);
+ } else if (stateKeys.length === 1) {
+ onClickFn = this.onViewSourceClick(stateGroup[stateKeys[0]]);
+ }
+
+ rows.push(
+ { evType }
+ );
+ });
+ } else {
+ const evType = this.state.eventType;
+ const stateGroup = this.roomStateEvents[evType];
+ Object.keys(stateGroup).forEach((stateKey) => {
+ // Skip this entry if does not contain search query
+ if (this.state.query && !stateKey.includes(this.state.query)) return;
+
+ const ev = stateGroup[stateKey];
+ rows.push(
+ { stateKey }
+ );
+ });
+ }
+
+ return
+
+
+ {rows}
+
+
+ { _t('Back') }
+
+
;
+ }
+}
+
+export default class DevtoolsDialog extends React.Component {
+ static propTypes = {
+ roomId: React.PropTypes.string.isRequired,
+ onFinished: React.PropTypes.func.isRequired,
+ };
+
+ state = {
+ mode: null,
+ modeArgs: {},
+ };
+
+ constructor(props, context) {
+ super(props, context);
+ this.onBack = this.onBack.bind(this);
+ this.setMode = this.setMode.bind(this);
+ this.onCancel = this.onCancel.bind(this);
+ }
+
+ componentWillUnmount() {
+ this._unmounted = true;
+ }
+
+ _setMode(mode) {
+ return () => {
+ this.setMode(mode);
+ };
+ }
+
+ setMode(mode, modeArgs={}) {
+ this.setState({ mode, modeArgs });
+ }
+
+ onBack() {
+ this.setState({ mode: null });
+ }
+
+ onCancel() {
+ this.props.onFinished(false);
+ }
+
+ render() {
+ let body;
+
+ if (this.state.mode) {
+ body =
+
;
+ } else {
+ body =
+
+ { _t('Send Custom Event') }
+ { _t('Send Custom State Event') }
+ { _t('Explore Room State') }
+
+
+ { _t('Cancel') }
+
+
;
+ }
+
+ const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
+ return (
+
+ Room ID: { this.props.roomId }
+ { body }
+
+ );
+ }
+}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 0dc93594..63a4c578 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -9,6 +9,7 @@
"All Rooms": "All Rooms",
"All notifications are currently disabled for all targets.": "All notifications are currently disabled for all targets.",
"An error occurred whilst saving your email notification preferences.": "An error occurred whilst saving your email notification preferences.",
+ "Back": "Back",
"Bug report sent": "Bug report sent",
"Call invitation": "Call invitation",
"Cancel": "Cancel",
@@ -26,6 +27,7 @@
"delete the alias.": "delete the alias.",
"Delete the room alias %(alias)s and remove %(name)s from the directory?": "Delete the room alias %(alias)s and remove %(name)s from the directory?",
"Describe your problem here.": "Describe your problem here.",
+ "Developer Tools": "Developer Tools",
"Direct Chat": "Direct Chat",
"Directory": "Directory",
"Dismiss": "Dismiss",
@@ -50,12 +52,14 @@
"Failed to get public room list": "Failed to get public room list",
"Failed to join the room": "Failed to join the room",
"Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room",
+ "Failed to send custom event.": "Failed to send custom event.",
"Failed to send report: ": "Failed to send report: ",
"Failed to set direct chat tag": "Failed to set direct chat tag",
"Failed to set Direct Message status of room": "Failed to set Direct Message status of room",
"Favourite": "Favourite",
"Fetching third party location failed": "Fetching third party location failed",
"Files": "Files",
+ "Filter results": "Filter results",
"Filter room names": "Filter room names",
"Forget": "Forget",
"Forward Message": "Forward Message",
@@ -117,6 +121,9 @@
"Search for a room": "Search for a room",
"Send": "Send",
"Send logs": "Send logs",
+ "Send Custom Event": "Send Custom Event",
+ "Send Custom State Event": "Send Custom State Event",
+ "Explore Room State": "Explore Room State",
"Settings": "Settings",
"Source URL": "Source URL",
"Sorry, your browser is
not able to run Riot.": "Sorry, your browser is
not able to run Riot.",
@@ -150,6 +157,7 @@
"You are not receiving desktop notifications": "You are not receiving desktop notifications",
"You are Rioting as a guest.
Register or
sign in to access more rooms and features!": "You are Rioting as a guest.
Register or
sign in to access more rooms and features!",
"You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply",
+ "You must specify an event type!": "You must specify an event type!",
"Thank you!": "Thank you!",
"Sunday": "Sunday",
"Monday": "Monday",
@@ -164,6 +172,10 @@
"Warning": "Warning",
"Checking for an update...": "Checking for an update...",
"Error encountered (%(errorDetail)s).": "Error encountered (%(errorDetail)s).",
+ "Event sent!": "Event sent!",
+ "Event Type": "Event Type",
+ "Event Content": "Event Content",
+ "State Key": "State Key",
"No update available.": "No update available.",
"Downloading update...": "Downloading update...",
"You need to be using HTTPS to place a screen-sharing call.": "You need to be using HTTPS to place a screen-sharing call.",
@@ -207,5 +219,6 @@
"Remember, you can always set an email address in user settings if you change your mind.": "Remember, you can always set an email address in user settings if you change your mind.",
"To return to your account in future you need to
set a password ": "To return to your account in future you need to
set a password ",
"Set Password": "Set Password",
- "Couldn't load home page": "Couldn't load home page"
+ "Couldn't load home page": "Couldn't load home page",
+ "Invite to this group": "Invite to this group"
}
diff --git a/src/skins/vector/css/_components.scss b/src/skins/vector/css/_components.scss
index 00c19b13..61bfa104 100644
--- a/src/skins/vector/css/_components.scss
+++ b/src/skins/vector/css/_components.scss
@@ -32,6 +32,7 @@
@import "./matrix-react-sdk/views/elements/_ProgressBar.scss";
@import "./matrix-react-sdk/views/elements/_RichText.scss";
@import "./matrix-react-sdk/views/elements/_RoleButton.scss";
+@import "./matrix-react-sdk/views/groups/_GroupInviteTile.scss";
@import "./matrix-react-sdk/views/login/_InteractiveAuthEntryComponents.scss";
@import "./matrix-react-sdk/views/login/_ServerConfig.scss";
@import "./matrix-react-sdk/views/messages/_MEmoteBody.scss";
@@ -74,6 +75,7 @@
@import "./vector-web/views/context_menus/_MessageContextMenu.scss";
@import "./vector-web/views/context_menus/_RoomTileContextMenu.scss";
@import "./vector-web/views/dialogs/_ChangelogDialog.scss";
+@import "./vector-web/views/dialogs/_DevtoolsDialog.scss";
@import "./vector-web/views/dialogs/_SetEmailDialog.scss";
@import "./vector-web/views/dialogs/_SetPasswordDialog.scss";
@import "./vector-web/views/directory/_NetworkDropdown.scss";
diff --git a/src/skins/vector/css/matrix-react-sdk/structures/_GroupView.scss b/src/skins/vector/css/matrix-react-sdk/structures/_GroupView.scss
index ae9f97b2..712a7508 100644
--- a/src/skins/vector/css/matrix-react-sdk/structures/_GroupView.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/_GroupView.scss
@@ -70,8 +70,12 @@ limitations under the License.
flex: 1;
}
-.mx_GroupView_saveButton, .mx_GroupView_cancelButton {
- display: table-cell;
+.mx_GroupView_header_rightCol {
+ display: flex;
+}
+
+.mx_GroupView_textButton {
+ display: inline-block;
}
.mx_GroupView_header_groupid {
@@ -126,6 +130,26 @@ limitations under the License.
top: 5px;
}
+.mx_GroupView_membershipSection {
+ margin-left: auto;
+ margin-right: auto;
+ margin-bottom: 11px;
+ justify-content: space-between;
+ display: flex;
+ color: $greyed-fg-color;
+}
+
+.mx_GroupView_membershipSection_description {
+ /* To match textButton */
+ line-height: 34px;
+}
+
+.mx_GroupView_membershipSection .mx_GroupView_textButton {
+ margin-right: 0px;
+ margin-top: 0px;
+ margin-left: 8px;
+}
+
.mx_GroupView_featuredThings {
margin-top: 20px;
}
@@ -142,9 +166,30 @@ limitations under the License.
margin-top: 10px;
}
+.mx_GroupView_featuredThings_container {
+ display: flex;
+}
+
+.mx_GroupView_featuredThings_addButton,
.mx_GroupView_featuredThing {
- cursor: pointer;
display: table-cell;
+ text-align: center;
+
+ width: 100px;
+ margin: 0px 20px;
+}
+
+.mx_GroupView_featuredThing .mx_BaseAvatar {
+ /* To prevent misalignment with mx_TintableSvg (in addButton) */
+ vertical-align: initial;
+}
+
+.mx_GroupView_featuredThings_addButton object {
+ pointer-events: none;
+}
+
+.mx_GroupView_featuredThing_name {
+ word-wrap: break-word;
}
.mx_GroupView_uploadInput {
diff --git a/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss b/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss
index 31686a7c..ec1cfd2e 100644
--- a/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss
@@ -80,6 +80,16 @@ limitations under the License.
cursor: pointer;
}
+.mx_UserSettings_button.mx_UserSettings_buttonSmall {
+ height: 36px;
+ padding: 4px;
+ padding-left: 7px;
+ padding-right: 7px;
+ font-size: 12px;
+ margin-right: 5px;
+ line-height: 12px;
+}
+
.mx_UserSettings_button.danger {
background-color: $warning-color;
}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/groups/_GroupInviteTile.scss b/src/skins/vector/css/matrix-react-sdk/views/groups/_GroupInviteTile.scss
new file mode 100644
index 00000000..6b4034b9
--- /dev/null
+++ b/src/skins/vector/css/matrix-react-sdk/views/groups/_GroupInviteTile.scss
@@ -0,0 +1,74 @@
+/*
+Copyright 2017 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_GroupInviteTile {
+ position: relative;
+ cursor: pointer;
+ font-size: 13px;
+ display: block;
+ height: 34px;
+}
+
+.mx_GroupInviteTile_nameContainer {
+ display: inline-block;
+ width: 180px;
+ height: 24px;
+}
+
+.mx_GroupInviteTile_avatarContainer {
+ display: inline-block;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-left: 16px;
+ padding-right: 6px;
+ width: 24px;
+ height: 24px;
+ vertical-align: middle;
+}
+
+.mx_GroupInviteTile_name {
+ display: inline-block;
+ position: relative;
+ width: 165px;
+ vertical-align: middle;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 2px;
+ padding-bottom: 3px;
+ color: $roomtile-name-color;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.mx_GroupInviteTile_badge {
+ display: inline-block;
+ min-width: 15px;
+ height: 15px;
+ position: absolute;
+ right: 8px; /*gutter */
+ top: 9px;
+ border-radius: 8px;
+ color: $accent-fg-color;
+ background-color: $group-alert-color;
+ font-weight: 600;
+ font-size: 10px;
+ text-align: center;
+ padding-top: 1px;
+ padding-left: 4px;
+ padding-right: 4px;
+}
+
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
index e9c62d3a..91e09601 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
@@ -45,7 +45,6 @@ limitations under the License.
.mx_EventTile .mx_SenderProfile {
color: $primary-fg-color;
- opacity: 0.5;
font-size: 14px;
display: block; /* anti-zalgo, with overflow hidden */
overflow-y: hidden;
@@ -57,6 +56,15 @@ limitations under the License.
line-height: 22px;
}
+.mx_EventTile .mx_SenderProfile .mx_SenderProfile_name,
+.mx_EventTile .mx_SenderProfile .mx_SenderProfile_aux {
+ opacity: 0.5;
+}
+
+.mx_EventTile .mx_SenderProfile .mx_Flair {
+ opacity: 0.7;
+}
+
.mx_EventTile .mx_MessageTimestamp {
display: block;
visibility: hidden;
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomSettings.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomSettings.scss
index 517ff94c..9e269ac2 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomSettings.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomSettings.scss
@@ -21,9 +21,7 @@ limitations under the License.
}
.mx_RoomSettings_leaveButton,
-.mx_RoomSettings_unbanButton,
-.mx_RoomSettings_integrationsButton,
-.mx_RoomSettings_integrationsButton_error {
+.mx_RoomSettings_unbanButton {
position: relative;
height: 36px;
background-color: $accent-color;
@@ -36,25 +34,37 @@ limitations under the License.
padding-left: 12px;
padding-right: 12px;
}
+.mx_RoomSettings_integrationsButton_error {
+ position: relative;
+ cursor: not-allowed;
+}
+.mx_RoomSettings_integrationsButton_error img {
+ position: absolute;
+ right: -5px;
+ top: -5px;
+}
.mx_RoomSettings_leaveButton,
-.mx_RoomSettings_integrationsButton,
.mx_RoomSettings_integrationsButton_error {
float: right;
}
-.mx_RoomSettings_integrationsButton_error {
- pointer: not-allowed;
+.mx_RoomSettings_integrationsButton_error .mx_RoomSettings_integrationsButton_errorPopup {
+ display: none;
+}
+.mx_RoomSettings_integrationsButton_error:hover .mx_RoomSettings_integrationsButton_errorPopup {
+ display: inline;
}
.mx_RoomSettings_integrationsButton_errorPopup {
position: absolute;
top: 110%;
- left: -26%;
- width: 150%;
+ left: -125%;
+ width: 348%;
padding: 2%;
font-size: 10pt;
line-height: 1.5em;
border-radius: 5px;
background-color: $accent-color;
color: $accent-fg-color;
+ text-align: center;
}
.mx_RoomSettings_unbanButton {
display: inline;
diff --git a/src/skins/vector/css/themes/_base.scss b/src/skins/vector/css/themes/_base.scss
index 6f613e38..a13c517b 100644
--- a/src/skins/vector/css/themes/_base.scss
+++ b/src/skins/vector/css/themes/_base.scss
@@ -22,6 +22,8 @@ $warning-color: #ff0064;
$mention-user-pill-bg-color: #ff0064;
$other-user-pill-bg-color: rgba(0, 0, 0, 0.1);
+$group-alert-color: #774f7e;
+
$preview-bar-bg-color: #f7f7f7;
// left-panel style muted accent color
diff --git a/src/skins/vector/css/vector-web/views/dialogs/_DevtoolsDialog.scss b/src/skins/vector/css/vector-web/views/dialogs/_DevtoolsDialog.scss
new file mode 100644
index 00000000..975ee8c1
--- /dev/null
+++ b/src/skins/vector/css/vector-web/views/dialogs/_DevtoolsDialog.scss
@@ -0,0 +1,19 @@
+/*
+Copyright 2017 Michael Telatynski <7t3chguy@gmail.com>
+
+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_DevTools_RoomStateExplorer_button, .mx_DevTools_RoomStateExplorer_query {
+ margin-bottom: 10px;
+}
diff --git a/test/app-tests/joining.js b/test/app-tests/joining.js
index 9e0a84c7..29da3413 100644
--- a/test/app-tests/joining.js
+++ b/test/app-tests/joining.js
@@ -176,8 +176,9 @@ describe('joining a room', function () {
return Promise.delay(1);
}).then(() => {
- // We've joined, expect this to false
- expect(roomView.state.joining).toBe(false);
+ // NB. we don't expect the 'joining' flag to reset at any point:
+ // it will stay set and we observe whether we have Room object for
+ // the room and whether our member event shows we're joined.
// now send the room down the /sync pipe
httpBackend.when('GET', '/sync').