mirror of
https://github.com/vector-im/element-web.git
synced 2024-09-09 22:55:12 +00:00
Merge remote-tracking branch 'origin/develop' into matthew/status
This commit is contained in:
commit
b9e2b59504
12 changed files with 291 additions and 232 deletions
|
@ -6,8 +6,8 @@
|
|||
"integrations_rest_url": "https://scalar.vector.im/api",
|
||||
"bug_report_endpoint_url": "https://riot.im/bugreports/submit",
|
||||
"features": {
|
||||
"feature_groups": "labs"
|
||||
"feature_pinning": "labs",
|
||||
"feature_groups": "labs",
|
||||
"feature_pinning": "labs"
|
||||
},
|
||||
"default_federate": true,
|
||||
"welcomePageUrl": "home.html",
|
||||
|
|
|
@ -19,6 +19,7 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import { DragDropContext } from 'react-dnd';
|
||||
import HTML5Backend from 'react-dnd-html5-backend';
|
||||
import classNames from 'classnames';
|
||||
import KeyCode from 'matrix-react-sdk/lib/KeyCode';
|
||||
import sdk from 'matrix-react-sdk';
|
||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||
|
@ -55,7 +56,7 @@ var LeftPanel = React.createClass({
|
|||
// We just need to update if any of these things change.
|
||||
if (
|
||||
this.props.collapsed !== nextProps.collapsed ||
|
||||
this.props.opacity !== nextProps.opacity
|
||||
this.props.disabled !== nextProps.disabled
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
@ -176,14 +177,16 @@ var LeftPanel = React.createClass({
|
|||
topBox = <SearchBox collapsed={ this.props.collapsed } onSearch={ this.onSearch } />;
|
||||
}
|
||||
|
||||
let classes = "mx_LeftPanel mx_fadable";
|
||||
if (this.props.collapsed) {
|
||||
classes += " collapsed";
|
||||
}
|
||||
let classes = classNames(
|
||||
"mx_LeftPanel", "mx_fadable",
|
||||
{
|
||||
"collapsed": this.props.collapsed,
|
||||
"mx_fadable_faded": this.props.disabled,
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<aside className={classes} style={{ opacity: this.props.opacity }}
|
||||
onKeyDown={ this._onKeyDown } onFocus={ this._onFocus } onBlur={ this._onBlur }>
|
||||
<aside className={classes} onKeyDown={ this._onKeyDown } onFocus={ this._onFocus } onBlur={ this._onBlur }>
|
||||
{ topBox }
|
||||
<CallPreview ConferenceHandler={VectorConferenceHandler} />
|
||||
<RoomList
|
||||
|
|
|
@ -18,14 +18,16 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import sdk from 'matrix-react-sdk';
|
||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||
import MatrixClient from 'matrix-js-sdk';
|
||||
import Analytics from 'matrix-react-sdk/lib/Analytics';
|
||||
import rate_limited_func from 'matrix-react-sdk/lib/ratelimitedfunc';
|
||||
import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton';
|
||||
import { showGroupInviteDialog, showGroupAddRoomDialog } from 'matrix-react-sdk/lib/GroupAddressPicker';
|
||||
import GroupStoreCache from 'matrix-react-sdk/lib/stores/GroupStoreCache';
|
||||
|
||||
class HeaderButton extends React.Component {
|
||||
constructor() {
|
||||
|
@ -80,6 +82,10 @@ module.exports = React.createClass({
|
|||
collapsed: React.PropTypes.bool, // currently unused property to request for a minimized view of the panel
|
||||
},
|
||||
|
||||
contextTypes: {
|
||||
matrixClient: PropTypes.instanceOf(MatrixClient),
|
||||
},
|
||||
|
||||
Phase: {
|
||||
RoomMemberList: 'RoomMemberList',
|
||||
GroupMemberList: 'GroupMemberList',
|
||||
|
@ -92,29 +98,52 @@ module.exports = React.createClass({
|
|||
|
||||
componentWillMount: function() {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
const cli = MatrixClientPeg.get();
|
||||
const cli = this.context.matrixClient;
|
||||
cli.on("RoomState.members", this.onRoomStateMember);
|
||||
this._initGroupStore(this.props.groupId);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
dis.unregister(this.dispatcherRef);
|
||||
if (MatrixClientPeg.get()) {
|
||||
MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember);
|
||||
if (this.context.matrixClient) {
|
||||
this.context.matrixClient.removeListener("RoomState.members", this.onRoomStateMember);
|
||||
}
|
||||
this._unregisterGroupStore();
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
if (this.props.groupId) {
|
||||
return {
|
||||
phase: this.Phase.GroupMemberList,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
phase: this.Phase.RoomMemberList,
|
||||
};
|
||||
return {
|
||||
phase: this.props.groupId ? this.Phase.GroupMemberList : this.Phase.RoomMemberList,
|
||||
isUserPrivilegedInGroup: null,
|
||||
}
|
||||
},
|
||||
|
||||
componentWillReceiveProps(newProps) {
|
||||
if (newProps.groupId !== this.props.groupId) {
|
||||
this._unregisterGroupStore();
|
||||
this._initGroupStore(newProps.groupId);
|
||||
}
|
||||
},
|
||||
|
||||
_initGroupStore(groupId) {
|
||||
this._groupStore = GroupStoreCache.getGroupStore(
|
||||
this.context.matrixClient, this.props.groupId,
|
||||
);
|
||||
this._groupStore.registerListener(this.onGroupStoreUpdated);
|
||||
},
|
||||
|
||||
_unregisterGroupStore() {
|
||||
if (this._groupStore) {
|
||||
this._groupStore.unregisterListener(this.onGroupStoreUpdated);
|
||||
}
|
||||
},
|
||||
|
||||
onGroupStoreUpdated: function(){
|
||||
this.setState({
|
||||
isUserPrivilegedInGroup: this._groupStore.isUserPrivileged(),
|
||||
});
|
||||
},
|
||||
|
||||
onCollapseClick: function() {
|
||||
dis.dispatch({
|
||||
action: 'hide_right_panel',
|
||||
|
@ -122,7 +151,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onInviteButtonClick: function() {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
if (this.context.matrixClient.isGuest()) {
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
return;
|
||||
}
|
||||
|
@ -222,13 +251,13 @@ module.exports = React.createClass({
|
|||
if ((this.state.phase == this.Phase.RoomMemberList || this.state.phase === this.Phase.RoomMemberInfo)
|
||||
&& this.props.roomId
|
||||
) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const cli = this.context.matrixClient;
|
||||
const room = cli.getRoom(this.props.roomId);
|
||||
let userIsInRoom;
|
||||
if (room) {
|
||||
membersBadge = room.getJoinedMembers().length;
|
||||
userIsInRoom = room.hasMembershipState(
|
||||
MatrixClientPeg.get().credentials.userId, 'join',
|
||||
this.context.matrixClient.credentials.userId, 'join',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -243,6 +272,11 @@ module.exports = React.createClass({
|
|||
}
|
||||
}
|
||||
|
||||
const isPhaseGroup = [
|
||||
this.Phase.GroupMemberInfo,
|
||||
this.Phase.GroupMemberList
|
||||
].includes(this.state.phase);
|
||||
|
||||
let headerButtons = [];
|
||||
if (this.props.roomId) {
|
||||
headerButtons = [
|
||||
|
@ -266,7 +300,7 @@ module.exports = React.createClass({
|
|||
} else if (this.props.groupId) {
|
||||
headerButtons = [
|
||||
<HeaderButton key="_groupMembersButton" title={_t('Members')} iconSrc="img/icons-people.svg"
|
||||
isHighlighted={this.state.phase === this.Phase.GroupMemberList}
|
||||
isHighlighted={isPhaseGroup}
|
||||
clickPhase={this.Phase.GroupMemberList}
|
||||
analytics={['Right Panel', 'Group Member List Button', 'click']}
|
||||
/>,
|
||||
|
@ -317,8 +351,8 @@ module.exports = React.createClass({
|
|||
panel = <div className="mx_RightPanel_blank"></div>;
|
||||
}
|
||||
|
||||
if (this.props.groupId) {
|
||||
inviteGroup = this.state.phase === this.Phase.GroupMemberList ? (
|
||||
if (this.props.groupId && this.state.isUserPrivilegedInGroup) {
|
||||
inviteGroup = isPhaseGroup ? (
|
||||
<AccessibleButton className="mx_RightPanel_invite" onClick={ this.onInviteButtonClick } >
|
||||
<div className="mx_RightPanel_icon" >
|
||||
<TintableSvg src="img/icon-invite-people.svg" width="35" height="35" />
|
||||
|
@ -335,13 +369,16 @@ module.exports = React.createClass({
|
|||
);
|
||||
}
|
||||
|
||||
let classes = "mx_RightPanel mx_fadable";
|
||||
if (this.props.collapsed) {
|
||||
classes += " collapsed";
|
||||
}
|
||||
let classes = classNames(
|
||||
"mx_RightPanel", "mx_fadable",
|
||||
{
|
||||
"collapsed": this.props.collapsed,
|
||||
"mx_fadable_faded": this.props.disabled,
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<aside className={classes} style={{ opacity: this.props.opacity }}>
|
||||
<aside className={classes}>
|
||||
<div className="mx_RightPanel_header">
|
||||
<div className="mx_RightPanel_headerButtonGroup">
|
||||
{headerButtons}
|
||||
|
|
|
@ -89,17 +89,17 @@ module.exports = React.createClass({
|
|||
});
|
||||
|
||||
// dis.dispatch({
|
||||
// action: 'ui_opacity',
|
||||
// sideOpacity: 0.3,
|
||||
// middleOpacity: 0.3,
|
||||
// action: 'panel_disable',
|
||||
// sideDisabled: true,
|
||||
// middleDisabled: true,
|
||||
// });
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
// dis.dispatch({
|
||||
// action: 'ui_opacity',
|
||||
// sideOpacity: 1.0,
|
||||
// middleOpacity: 1.0,
|
||||
// action: 'panel_disable',
|
||||
// sideDisabled: false,
|
||||
// middleDisabled: false,
|
||||
// });
|
||||
if (this.filterTimeout) {
|
||||
clearTimeout(this.filterTimeout);
|
||||
|
|
|
@ -57,7 +57,7 @@ class SendCustomEvent extends React.Component {
|
|||
_buttons() {
|
||||
return <div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onBack}>{ _t('Back') }</button>
|
||||
{!this.state.message && <button onClick={this._send}>{ _t('Send') }</button>}
|
||||
{ !this.state.message && <button onClick={this._send}>{ _t('Send') }</button> }
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ class SendCustomEvent extends React.Component {
|
|||
}
|
||||
|
||||
_additionalFields() {
|
||||
return <div/>;
|
||||
return <div />;
|
||||
}
|
||||
|
||||
_onChange(e) {
|
||||
|
@ -94,15 +94,15 @@ class SendCustomEvent extends React.Component {
|
|||
if (this.state.message) {
|
||||
return <div>
|
||||
<div className="mx_Dialog_content">
|
||||
{this.state.message}
|
||||
{ this.state.message }
|
||||
</div>
|
||||
{this._buttons()}
|
||||
{ this._buttons() }
|
||||
</div>;
|
||||
}
|
||||
|
||||
return <div>
|
||||
<div className="mx_Dialog_content">
|
||||
{this._additionalFields()}
|
||||
{ this._additionalFields() }
|
||||
<div className="mx_TextInputDialog_label">
|
||||
<label htmlFor="eventType"> { _t('Event Type') } </label>
|
||||
</div>
|
||||
|
@ -117,7 +117,7 @@ class SendCustomEvent extends React.Component {
|
|||
<textarea id="evContent" onChange={this._onChange} value={this.state.input_evContent} className="mx_TextInputDialog_input" cols="63" rows="5" />
|
||||
</div>
|
||||
</div>
|
||||
{this._buttons()}
|
||||
{ this._buttons() }
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ class RoomStateExplorer extends React.Component {
|
|||
if (this.state.event) {
|
||||
return <div className="mx_ViewSource">
|
||||
<div className="mx_Dialog_content">
|
||||
<pre>{JSON.stringify(this.state.event.event, null, 2)}</pre>
|
||||
<pre>{ JSON.stringify(this.state.event.event, null, 2) }</pre>
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onBack}>{ _t('Back') }</button>
|
||||
|
@ -237,7 +237,7 @@ class RoomStateExplorer extends React.Component {
|
|||
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;
|
||||
if (this.state.query && !evType.toLowerCase().includes(this.state.query.toLowerCase())) return;
|
||||
|
||||
const stateGroup = this.roomStateEvents[evType];
|
||||
const stateKeys = Object.keys(stateGroup);
|
||||
|
@ -258,7 +258,7 @@ class RoomStateExplorer extends React.Component {
|
|||
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;
|
||||
if (this.state.query && !stateKey.toLowerCase().includes(this.state.query.toLowerCase())) return;
|
||||
|
||||
const ev = stateGroup[stateKey];
|
||||
rows.push(<button className="mx_DevTools_RoomStateExplorer_button" key={stateKey}
|
||||
|
@ -271,7 +271,7 @@ class RoomStateExplorer extends React.Component {
|
|||
return <div>
|
||||
<div className="mx_Dialog_content">
|
||||
<input onChange={this.onQuery} placeholder={_t('Filter results')} size="64" className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query" value={this.state.query} />
|
||||
{rows}
|
||||
{ rows }
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onBack}>{ _t('Back') }</button>
|
||||
|
|
|
@ -14,16 +14,19 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
var React = require('react');
|
||||
import { _t, _tJsx } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import React from 'react';
|
||||
import Promise from 'bluebird';
|
||||
var sdk = require('matrix-react-sdk');
|
||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
var UserSettingsStore = require('matrix-react-sdk/lib/UserSettingsStore');
|
||||
var Modal = require('matrix-react-sdk/lib/Modal');
|
||||
|
||||
var notifications = require('../../../notifications');
|
||||
import sdk from 'matrix-react-sdk';
|
||||
import { _t, _tJsx } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||
import UserSettingsStore from 'matrix-react-sdk/lib/UserSettingsStore';
|
||||
import Modal from 'matrix-react-sdk/lib/Modal';
|
||||
import {
|
||||
NotificationUtils,
|
||||
VectorPushRulesDefinitions,
|
||||
PushRuleVectorState,
|
||||
ContentRules
|
||||
} from '../../../notifications';
|
||||
|
||||
// TODO: this "view" component still has far too much application logic in it,
|
||||
// which should be factored out to other files.
|
||||
|
@ -31,17 +34,13 @@ var notifications = require('../../../notifications');
|
|||
// TODO: this component also does a lot of direct poking into this.state, which
|
||||
// is VERY NAUGHTY.
|
||||
|
||||
var NotificationUtils = notifications.NotificationUtils;
|
||||
var VectorPushRulesDefinitions = notifications.VectorPushRulesDefinitions;
|
||||
var PushRuleVectorState = notifications.PushRuleVectorState;
|
||||
var ContentRules = notifications.ContentRules;
|
||||
|
||||
/**
|
||||
* Rules that Vector used to set in order to override the actions of default rules.
|
||||
* These are used to port peoples existing overrides to match the current API.
|
||||
* These can be removed and forgotten once everyone has moved to the new client.
|
||||
*/
|
||||
var LEGACY_RULES = {
|
||||
const LEGACY_RULES = {
|
||||
"im.vector.rule.contains_display_name": ".m.rule.contains_display_name",
|
||||
"im.vector.rule.room_one_to_one": ".m.rule.room_one_to_one",
|
||||
"im.vector.rule.room_message": ".m.rule.message",
|
||||
|
@ -51,7 +50,7 @@ var LEGACY_RULES = {
|
|||
};
|
||||
|
||||
function portLegacyActions(actions) {
|
||||
var decoded = NotificationUtils.decodeActions(actions);
|
||||
const decoded = NotificationUtils.decodeActions(actions);
|
||||
if (decoded !== null) {
|
||||
return NotificationUtils.encodeActions(decoded);
|
||||
} else {
|
||||
|
@ -62,7 +61,7 @@ function portLegacyActions(actions) {
|
|||
}
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'Notififications',
|
||||
displayName: 'Notifications',
|
||||
|
||||
phases: {
|
||||
LOADING: "LOADING", // The component is loading or sending data to the hs
|
||||
|
@ -102,7 +101,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onEnableNotificationsChange: function(event) {
|
||||
var self = this;
|
||||
const self = this;
|
||||
this.setState({
|
||||
phase: this.phases.LOADING
|
||||
});
|
||||
|
@ -122,20 +121,20 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onEnableEmailNotificationsChange: function(address, event) {
|
||||
var emailPusherPromise;
|
||||
let emailPusherPromise;
|
||||
if (event.target.checked) {
|
||||
var data = {}
|
||||
const data = {}
|
||||
data['brand'] = this.props.brand || 'Riot';
|
||||
emailPusherPromise = UserSettingsStore.addEmailPusher(address, data);
|
||||
} else {
|
||||
var emailPusher = UserSettingsStore.getEmailPusher(this.state.pushers, address);
|
||||
const emailPusher = UserSettingsStore.getEmailPusher(this.state.pushers, address);
|
||||
emailPusher.kind = null;
|
||||
emailPusherPromise = MatrixClientPeg.get().setPusher(emailPusher);
|
||||
}
|
||||
emailPusherPromise.done(() => {
|
||||
this._refreshFromServer();
|
||||
}, (error) => {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Error saving email notification preferences', '', ErrorDialog, {
|
||||
title: _t('Error saving email notification preferences'),
|
||||
description: _t('An error occurred whilst saving your email notification preferences.'),
|
||||
|
@ -145,14 +144,14 @@ module.exports = React.createClass({
|
|||
|
||||
onNotifStateButtonClicked: function(event) {
|
||||
// FIXME: use .bind() rather than className metadata here surely
|
||||
var vectorRuleId = event.target.className.split("-")[0];
|
||||
var newPushRuleVectorState = event.target.className.split("-")[1];
|
||||
const vectorRuleId = event.target.className.split("-")[0];
|
||||
const newPushRuleVectorState = event.target.className.split("-")[1];
|
||||
|
||||
if ("_keywords" === vectorRuleId) {
|
||||
this._setKeywordsPushRuleVectorState(newPushRuleVectorState)
|
||||
}
|
||||
else {
|
||||
var rule = this.getRule(vectorRuleId);
|
||||
const rule = this.getRule(vectorRuleId);
|
||||
if (rule) {
|
||||
this._setPushRuleVectorState(rule, newPushRuleVectorState);
|
||||
}
|
||||
|
@ -160,12 +159,12 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onKeywordsClicked: function(event) {
|
||||
var self = this;
|
||||
const self = this;
|
||||
|
||||
// Compute the keywords list to display
|
||||
var keywords = [];
|
||||
for (var i in this.state.vectorContentRules.rules) {
|
||||
var rule = this.state.vectorContentRules.rules[i];
|
||||
let keywords = [];
|
||||
for (let i in this.state.vectorContentRules.rules) {
|
||||
const rule = this.state.vectorContentRules.rules[i];
|
||||
keywords.push(rule.pattern);
|
||||
}
|
||||
if (keywords.length) {
|
||||
|
@ -179,7 +178,7 @@ module.exports = React.createClass({
|
|||
keywords = "";
|
||||
}
|
||||
|
||||
var TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
|
||||
const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
|
||||
Modal.createTrackedDialog('Keywords Dialog', '', TextInputDialog, {
|
||||
title: _t('Keywords'),
|
||||
description: _t('Enter keywords separated by a comma:'),
|
||||
|
@ -188,8 +187,8 @@ module.exports = React.createClass({
|
|||
onFinished: function onFinished(should_leave, newValue) {
|
||||
|
||||
if (should_leave && newValue !== keywords) {
|
||||
var newKeywords = newValue.split(',');
|
||||
for (var i in newKeywords) {
|
||||
let newKeywords = newValue.split(',');
|
||||
for (let i in newKeywords) {
|
||||
newKeywords[i] = newKeywords[i].trim();
|
||||
}
|
||||
|
||||
|
@ -208,8 +207,8 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
getRule: function(vectorRuleId) {
|
||||
for (var i in this.state.vectorPushRules) {
|
||||
var rule = this.state.vectorPushRules[i];
|
||||
for (let i in this.state.vectorPushRules) {
|
||||
const rule = this.state.vectorPushRules[i];
|
||||
if (rule.vectorRuleId === vectorRuleId) {
|
||||
return rule;
|
||||
}
|
||||
|
@ -223,13 +222,13 @@ module.exports = React.createClass({
|
|||
phase: this.phases.LOADING
|
||||
});
|
||||
|
||||
var self = this;
|
||||
var cli = MatrixClientPeg.get();
|
||||
var deferreds = [];
|
||||
var ruleDefinition = VectorPushRulesDefinitions[rule.vectorRuleId];
|
||||
const self = this;
|
||||
const cli = MatrixClientPeg.get();
|
||||
const deferreds = [];
|
||||
const ruleDefinition = VectorPushRulesDefinitions[rule.vectorRuleId];
|
||||
|
||||
if (rule.rule) {
|
||||
var actions = ruleDefinition.vectorStateToActions[newPushRuleVectorState];
|
||||
const actions = ruleDefinition.vectorStateToActions[newPushRuleVectorState];
|
||||
|
||||
if (!actions) {
|
||||
// The new state corresponds to disabling the rule.
|
||||
|
@ -244,7 +243,7 @@ module.exports = React.createClass({
|
|||
Promise.all(deferreds).done(function() {
|
||||
self._refreshFromServer();
|
||||
}, function(error) {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to change settings: " + error);
|
||||
Modal.createTrackedDialog('Failed to change settings', '', ErrorDialog, {
|
||||
title: _t('Failed to change settings'),
|
||||
|
@ -262,19 +261,19 @@ module.exports = React.createClass({
|
|||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var cli = MatrixClientPeg.get();
|
||||
const self = this;
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
this.setState({
|
||||
phase: this.phases.LOADING
|
||||
});
|
||||
|
||||
// Update all rules in self.state.vectorContentRules
|
||||
var deferreds = [];
|
||||
for (var i in this.state.vectorContentRules.rules) {
|
||||
var rule = this.state.vectorContentRules.rules[i];
|
||||
const deferreds = [];
|
||||
for (let i in this.state.vectorContentRules.rules) {
|
||||
const rule = this.state.vectorContentRules.rules[i];
|
||||
|
||||
var enabled, actions;
|
||||
let enabled, actions;
|
||||
switch (newPushRuleVectorState) {
|
||||
case PushRuleVectorState.ON:
|
||||
if (rule.actions.length !== 1) {
|
||||
|
@ -314,7 +313,7 @@ module.exports = React.createClass({
|
|||
Promise.all(deferreds).done(function(resps) {
|
||||
self._refreshFromServer();
|
||||
}, function(error) {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Can't update user notification settings: " + error);
|
||||
Modal.createTrackedDialog('Can\'t update user notifcation settings', '', ErrorDialog, {
|
||||
title: _t('Can\'t update user notification settings'),
|
||||
|
@ -329,14 +328,14 @@ module.exports = React.createClass({
|
|||
phase: this.phases.LOADING
|
||||
});
|
||||
|
||||
var self = this;
|
||||
var cli = MatrixClientPeg.get();
|
||||
var removeDeferreds = [];
|
||||
const self = this;
|
||||
const cli = MatrixClientPeg.get();
|
||||
const removeDeferreds = [];
|
||||
|
||||
// Remove per-word push rules of keywords that are no more in the list
|
||||
var vectorContentRulesPatterns = [];
|
||||
for (var i in self.state.vectorContentRules.rules) {
|
||||
var rule = self.state.vectorContentRules.rules[i];
|
||||
const vectorContentRulesPatterns = [];
|
||||
for (let i in self.state.vectorContentRules.rules) {
|
||||
const rule = self.state.vectorContentRules.rules[i];
|
||||
|
||||
vectorContentRulesPatterns.push(rule.pattern);
|
||||
|
||||
|
@ -347,16 +346,16 @@ module.exports = React.createClass({
|
|||
|
||||
// If the keyword is part of `externalContentRules`, remove the rule
|
||||
// before recreating it in the right Vector path
|
||||
for (var i in self.state.externalContentRules) {
|
||||
var rule = self.state.externalContentRules[i];
|
||||
for (let i in self.state.externalContentRules) {
|
||||
const rule = self.state.externalContentRules[i];
|
||||
|
||||
if (newKeywords.indexOf(rule.pattern) >= 0) {
|
||||
removeDeferreds.push(cli.deletePushRule('global', rule.kind, rule.rule_id));
|
||||
}
|
||||
}
|
||||
|
||||
var onError = function(error) {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const onError = function(error) {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to update keywords: " + error);
|
||||
Modal.createTrackedDialog('Failed to update keywords', '', ErrorDialog, {
|
||||
title: _t('Failed to update keywords'),
|
||||
|
@ -367,9 +366,9 @@ module.exports = React.createClass({
|
|||
|
||||
// Then, add the new ones
|
||||
Promise.all(removeDeferreds).done(function(resps) {
|
||||
var deferreds = [];
|
||||
const deferreds = [];
|
||||
|
||||
var pushRuleVectorStateKind = self.state.vectorContentRules.vectorState;
|
||||
let pushRuleVectorStateKind = self.state.vectorContentRules.vectorState;
|
||||
if (pushRuleVectorStateKind === PushRuleVectorState.OFF) {
|
||||
// When the current global keywords rule is OFF, we need to look at
|
||||
// the flavor of rules in 'vectorContentRules' to apply the same actions
|
||||
|
@ -384,8 +383,8 @@ module.exports = React.createClass({
|
|||
}
|
||||
}
|
||||
|
||||
for (var i in newKeywords) {
|
||||
var keyword = newKeywords[i];
|
||||
for (let i in newKeywords) {
|
||||
const keyword = newKeywords[i];
|
||||
|
||||
if (vectorContentRulesPatterns.indexOf(keyword) < 0) {
|
||||
if (self.state.vectorContentRules.vectorState !== PushRuleVectorState.OFF) {
|
||||
|
@ -412,31 +411,31 @@ module.exports = React.createClass({
|
|||
|
||||
// Create a push rule but disabled
|
||||
_addDisabledPushRule: function(scope, kind, ruleId, body) {
|
||||
var cli = MatrixClientPeg.get();
|
||||
return cli.addPushRule(scope, kind, ruleId, body).then(function() {
|
||||
return cli.setPushRuleEnabled(scope, kind, ruleId, false);
|
||||
});
|
||||
const cli = MatrixClientPeg.get();
|
||||
return cli.addPushRule(scope, kind, ruleId, body).then(() =>
|
||||
cli.setPushRuleEnabled(scope, kind, ruleId, false)
|
||||
);
|
||||
},
|
||||
|
||||
// Check if any legacy im.vector rules need to be ported to the new API
|
||||
// for overriding the actions of default rules.
|
||||
_portRulesToNewAPI: function(rulesets) {
|
||||
var self = this;
|
||||
var needsUpdate = [];
|
||||
var cli = MatrixClientPeg.get();
|
||||
const self = this;
|
||||
const needsUpdate = [];
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
for (var kind in rulesets.global) {
|
||||
var ruleset = rulesets.global[kind];
|
||||
for (var i = 0; i < ruleset.length; ++i) {
|
||||
var rule = ruleset[i];
|
||||
for (let kind in rulesets.global) {
|
||||
const ruleset = rulesets.global[kind];
|
||||
for (let i = 0; i < ruleset.length; ++i) {
|
||||
const rule = ruleset[i];
|
||||
if (rule.rule_id in LEGACY_RULES) {
|
||||
console.log("Porting legacy rule", rule);
|
||||
needsUpdate.push( function(kind, rule) {
|
||||
return cli.setPushRuleActions(
|
||||
'global', kind, LEGACY_RULES[rule.rule_id], portLegacyActions(rule.actions)
|
||||
).then( function() {
|
||||
return cli.deletePushRule('global', kind, rule.rule_id);
|
||||
}).catch( (e) => {
|
||||
).then(() =>
|
||||
cli.deletePushRule('global', kind, rule.rule_id)
|
||||
).catch( (e) => {
|
||||
console.warn(`Error when porting legacy rule: ${e}`);
|
||||
});
|
||||
}(kind, rule));
|
||||
|
@ -447,9 +446,9 @@ module.exports = React.createClass({
|
|||
if (needsUpdate.length > 0) {
|
||||
// If some of the rules need to be ported then wait for the porting
|
||||
// to happen and then fetch the rules again.
|
||||
return Promise.all(needsUpdate).then( function() {
|
||||
return cli.getPushRules();
|
||||
});
|
||||
return Promise.all(needsUpdate).then(() =>
|
||||
cli.getPushRules()
|
||||
);
|
||||
} else {
|
||||
// Otherwise return the rules that we already have.
|
||||
return rulesets;
|
||||
|
@ -457,15 +456,14 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_refreshFromServer: function() {
|
||||
var self = this;
|
||||
var pushRulesPromise = MatrixClientPeg.get().getPushRules().then(self._portRulesToNewAPI).then(function(rulesets) {
|
||||
//console.log("resolving pushRulesPromise");
|
||||
const self = this;
|
||||
const pushRulesPromise = MatrixClientPeg.get().getPushRules().then(self._portRulesToNewAPI).then(function(rulesets) {
|
||||
|
||||
/// XXX seriously? wtf is this?
|
||||
MatrixClientPeg.get().pushRules = rulesets;
|
||||
|
||||
// Get homeserver default rules and triage them by categories
|
||||
var rule_categories = {
|
||||
const rule_categories = {
|
||||
// The master rule (all notifications disabling)
|
||||
'.m.rule.master': 'master',
|
||||
|
||||
|
@ -483,12 +481,12 @@ module.exports = React.createClass({
|
|||
};
|
||||
|
||||
// HS default rules
|
||||
var defaultRules = {master: [], vector: {}, others: []};
|
||||
const defaultRules = {master: [], vector: {}, others: []};
|
||||
|
||||
for (var kind in rulesets.global) {
|
||||
for (var i = 0; i < Object.keys(rulesets.global[kind]).length; ++i) {
|
||||
var r = rulesets.global[kind][i];
|
||||
var cat = rule_categories[r.rule_id];
|
||||
for (let kind in rulesets.global) {
|
||||
for (let i = 0; i < Object.keys(rulesets.global[kind]).length; ++i) {
|
||||
const r = rulesets.global[kind][i];
|
||||
const cat = rule_categories[r.rule_id];
|
||||
r.kind = kind;
|
||||
|
||||
if (r.rule_id[0] === '.') {
|
||||
|
@ -511,7 +509,7 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
// parse the keyword rules into our state
|
||||
var contentRules = ContentRules.parseContentRules(rulesets);
|
||||
const contentRules = ContentRules.parseContentRules(rulesets);
|
||||
self.state.vectorContentRules = {
|
||||
vectorState: contentRules.vectorState,
|
||||
rules: contentRules.rules,
|
||||
|
@ -522,7 +520,7 @@ module.exports = React.createClass({
|
|||
self.state.vectorPushRules = [];
|
||||
self.state.externalPushRules = [];
|
||||
|
||||
var vectorRuleIds = [
|
||||
const vectorRuleIds = [
|
||||
'.m.rule.contains_display_name',
|
||||
'.m.rule.contains_user_name',
|
||||
'_keywords',
|
||||
|
@ -533,8 +531,8 @@ module.exports = React.createClass({
|
|||
'.m.rule.call',
|
||||
'.m.rule.suppress_notices'
|
||||
];
|
||||
for (var i in vectorRuleIds) {
|
||||
var vectorRuleId = vectorRuleIds[i];
|
||||
for (let i in vectorRuleIds) {
|
||||
const vectorRuleId = vectorRuleIds[i];
|
||||
|
||||
if (vectorRuleId === '_keywords') {
|
||||
// keywords needs a special handling
|
||||
|
@ -546,9 +544,8 @@ module.exports = React.createClass({
|
|||
<span>
|
||||
{ _tJsx('Messages containing <span>keywords</span>',
|
||||
/<span>(.*?)<\/span>/,
|
||||
(sub) => {
|
||||
return <span className="mx_UserNotifSettings_keywords" onClick={ self.onKeywordsClicked }>{sub}</span>;
|
||||
}
|
||||
(sub) =>
|
||||
<span className="mx_UserNotifSettings_keywords" onClick={ self.onKeywordsClicked }>{sub}</span>
|
||||
)}
|
||||
</span>
|
||||
),
|
||||
|
@ -556,10 +553,10 @@ module.exports = React.createClass({
|
|||
});
|
||||
}
|
||||
else {
|
||||
var ruleDefinition = VectorPushRulesDefinitions[vectorRuleId];
|
||||
var rule = defaultRules.vector[vectorRuleId];
|
||||
const ruleDefinition = VectorPushRulesDefinitions[vectorRuleId];
|
||||
const rule = defaultRules.vector[vectorRuleId];
|
||||
|
||||
var vectorState = ruleDefinition.ruleToVectorState(rule);
|
||||
const vectorState = ruleDefinition.ruleToVectorState(rule);
|
||||
|
||||
//console.log("Refreshing vectorPushRules for " + vectorRuleId +", "+ ruleDefinition.description +", " + rule +", " + vectorState);
|
||||
|
||||
|
@ -579,14 +576,14 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
// Build the rules not managed by Vector UI
|
||||
var otherRulesDescriptions = {
|
||||
const otherRulesDescriptions = {
|
||||
'.m.rule.message': _t('Notify for all other messages/rooms'),
|
||||
'.m.rule.fallback': _t('Notify me for anything else'),
|
||||
};
|
||||
|
||||
for (var i in defaultRules.others) {
|
||||
var rule = defaultRules.others[i];
|
||||
var ruleDescription = otherRulesDescriptions[rule.rule_id];
|
||||
for (let i in defaultRules.others) {
|
||||
const rule = defaultRules.others[i];
|
||||
const ruleDescription = otherRulesDescriptions[rule.rule_id];
|
||||
|
||||
// Show enabled default rules that was modified by the user
|
||||
if (ruleDescription && rule.enabled && !rule.default) {
|
||||
|
@ -596,8 +593,7 @@ module.exports = React.createClass({
|
|||
}
|
||||
});
|
||||
|
||||
var pushersPromise = MatrixClientPeg.get().getPushers().then(function(resp) {
|
||||
//console.log("resolving pushersPromise");
|
||||
const pushersPromise = MatrixClientPeg.get().getPushers().then(function(resp) {
|
||||
self.setState({pushers: resp.pushers});
|
||||
});
|
||||
|
||||
|
@ -623,7 +619,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_updatePushRuleActions: function(rule, actions, enabled) {
|
||||
var cli = MatrixClientPeg.get();
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
return cli.setPushRuleActions(
|
||||
'global', rule.kind, rule.rule_id, actions
|
||||
|
@ -669,9 +665,9 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
renderNotifRulesTableRows: function() {
|
||||
var rows = [];
|
||||
for (var i in this.state.vectorPushRules) {
|
||||
var rule = this.state.vectorPushRules[i];
|
||||
const rows = [];
|
||||
for (let i in this.state.vectorPushRules) {
|
||||
const rule = this.state.vectorPushRules[i];
|
||||
//console.log("rendering: " + rule.description + ", " + rule.vectorRuleId + ", " + rule.vectorState);
|
||||
rows.push(this.renderNotifRulesTableRow(rule.description, rule.vectorRuleId, rule.vectorState));
|
||||
}
|
||||
|
@ -697,30 +693,32 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
|
||||
var spinner;
|
||||
const self = this;
|
||||
|
||||
let spinner;
|
||||
if (this.state.phase === this.phases.LOADING) {
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
spinner = <Loader />;
|
||||
}
|
||||
|
||||
|
||||
let masterPushRuleDiv;
|
||||
if (this.state.masterPushRule) {
|
||||
var masterPushRuleDiv = (
|
||||
masterPushRuleDiv = (
|
||||
<div className="mx_UserNotifSettings_tableRow">
|
||||
<div className="mx_UserNotifSettings_inputCell">
|
||||
<input id="enableNotifications"
|
||||
ref="enableNotifications"
|
||||
type="checkbox"
|
||||
checked={ !this.state.masterPushRule.enabled }
|
||||
onChange={ this.onEnableNotificationsChange } />
|
||||
</div>
|
||||
<div className="mx_UserNotifSettings_labelCell">
|
||||
<label htmlFor="enableNotifications">
|
||||
{ _t('Enable notifications for this account') }
|
||||
</label>
|
||||
</div>
|
||||
<div className="mx_UserNotifSettings_inputCell">
|
||||
<input id="enableNotifications"
|
||||
ref="enableNotifications"
|
||||
type="checkbox"
|
||||
checked={ !this.state.masterPushRule.enabled }
|
||||
onChange={ this.onEnableNotificationsChange }
|
||||
/>
|
||||
</div>
|
||||
<div className="mx_UserNotifSettings_labelCell">
|
||||
<label htmlFor="enableNotifications">
|
||||
{ _t('Enable notifications for this account') }
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -748,29 +746,29 @@ module.exports = React.createClass({
|
|||
// This only supports the first email address in your profile for now
|
||||
emailNotificationsRow = this.emailNotificationsRow(
|
||||
emailThreepids[0].address,
|
||||
_t('Enable email notifications') + ' (' + emailThreepids[0].address + ')'
|
||||
`${_t('Enable email notifications')} (${emailThreepids[0].address})`
|
||||
);
|
||||
}
|
||||
|
||||
// Build external push rules
|
||||
var externalRules = [];
|
||||
for (var i in this.state.externalPushRules) {
|
||||
var rule = this.state.externalPushRules[i];
|
||||
const externalRules = [];
|
||||
for (let i in this.state.externalPushRules) {
|
||||
const rule = this.state.externalPushRules[i];
|
||||
externalRules.push(<li>{ _t(rule.description) }</li>);
|
||||
}
|
||||
|
||||
// Show keywords not displayed by the vector UI as a single external push rule
|
||||
var externalKeyWords = [];
|
||||
for (var i in this.state.externalContentRules) {
|
||||
var rule = this.state.externalContentRules[i];
|
||||
externalKeyWords.push(rule.pattern);
|
||||
let externalKeywords = [];
|
||||
for (let i in this.state.externalContentRules) {
|
||||
const rule = this.state.externalContentRules[i];
|
||||
externalKeywords.push(rule.pattern);
|
||||
}
|
||||
if (externalKeyWords.length) {
|
||||
externalKeyWords = externalKeyWords.join(", ");
|
||||
externalRules.push(<li>{ _t('Notifications on the following keywords follow rules which can’t be displayed here:') } { externalKeyWords }</li>);
|
||||
if (externalKeywords.length) {
|
||||
externalKeywords = externalKeywords.join(", ");
|
||||
externalRules.push(<li>{ _t('Notifications on the following keywords follow rules which can’t be displayed here:') } { externalKeywords }</li>);
|
||||
}
|
||||
|
||||
var devicesSection;
|
||||
let devicesSection;
|
||||
if (this.state.pushers === undefined) {
|
||||
devicesSection = <div className="error">{ _t('Unable to fetch notification target list') }</div>
|
||||
} else if (this.state.pushers.length == 0) {
|
||||
|
@ -778,8 +776,8 @@ module.exports = React.createClass({
|
|||
} else {
|
||||
// TODO: It would be great to be able to delete pushers from here too,
|
||||
// and this wouldn't be hard to add.
|
||||
var rows = [];
|
||||
for (var i = 0; i < this.state.pushers.length; ++i) {
|
||||
const rows = [];
|
||||
for (let i = 0; i < this.state.pushers.length; ++i) {
|
||||
rows.push(<tr key={ i }>
|
||||
<td>{this.state.pushers[i].app_display_name}</td>
|
||||
<td>{this.state.pushers[i].device_display_name}</td>
|
||||
|
@ -798,7 +796,7 @@ module.exports = React.createClass({
|
|||
</div>);
|
||||
}
|
||||
|
||||
var advancedSettings;
|
||||
let advancedSettings;
|
||||
if (externalRules.length) {
|
||||
advancedSettings = (
|
||||
<div>
|
||||
|
|
|
@ -82,6 +82,11 @@ textarea {
|
|||
transition: opacity 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.mx_fadable.mx_fadable_faded {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* XXX: critical hack to GeminiScrollbar to allow them to work in FF 42 and Chrome 48.
|
||||
Stop the scrollbar view from pushing out the container's overall sizing, which causes
|
||||
flexbox to adapt to the new size and cause the view to keep growing.
|
||||
|
|
|
@ -33,10 +33,12 @@ limitations under the License.
|
|||
min-height: 70px;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.mx_GroupView_header_view {
|
||||
border-bottom: 1px solid $primary-hairline-color;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.mx_GroupView_header_avatar, .mx_GroupView_header_info {
|
||||
|
@ -159,8 +161,12 @@ limitations under the License.
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
.mx_GroupView_rooms_header h3 {
|
||||
margin-bottom: 10px
|
||||
.mx_GroupView h3 {
|
||||
text-transform: uppercase;
|
||||
color: $h3-color;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.mx_GroupView_rooms_header .mx_AccessibleButton {
|
||||
|
@ -169,15 +175,24 @@ limitations under the License.
|
|||
height: 24px;
|
||||
}
|
||||
|
||||
.mx_GroupView_rooms_header_addButton {
|
||||
display: inline-block;
|
||||
.mx_GroupView_group {
|
||||
border-top: 1px solid $primary-hairline-color;
|
||||
}
|
||||
|
||||
.mx_GroupView_rooms_header_addButton object {
|
||||
.mx_GroupView_group_disabled {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.mx_GroupView_rooms_header_addButton_label {
|
||||
.mx_GroupView_rooms_header_addRow_button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.mx_GroupView_rooms_header_addRow_button object {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.mx_GroupView_rooms_header_addRow_label {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
line-height: 24px;
|
||||
|
@ -222,14 +237,6 @@ limitations under the License.
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
.mx_GroupView_memberSettings h3 {
|
||||
text-transform: uppercase;
|
||||
color: $h3-color;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.mx_GroupView_memberSettings input {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ limitations under the License.
|
|||
min-width: 0px;
|
||||
max-width: 960px;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
margin: 0px auto;
|
||||
|
||||
overflow: auto;
|
||||
border-bottom: 1px solid $primary-hairline-color;
|
||||
|
@ -80,17 +80,32 @@ limitations under the License.
|
|||
max-width: 1920px ! important;
|
||||
}
|
||||
|
||||
.mx_RoomView_topUnreadMessagesBar {
|
||||
|
||||
.mx_RoomView_body {
|
||||
order: 3;
|
||||
flex: 1 1 0;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.mx_RoomView_body .mx_RoomView_topUnreadMessagesBar {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.mx_RoomView_body .mx_RoomView_messagePanel {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.mx_RoomView_body .mx_RoomView_statusArea {
|
||||
order: 3;
|
||||
}
|
||||
|
||||
.mx_RoomView_messagePanel {
|
||||
.mx_RoomView_body .mx_MessageComposer {
|
||||
order: 4;
|
||||
}
|
||||
|
||||
flex: 1 1 0;
|
||||
|
||||
.mx_RoomView_messagePanel {
|
||||
width: 100%;
|
||||
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
@ -131,18 +146,6 @@ limitations under the License.
|
|||
clear: both;
|
||||
}
|
||||
|
||||
.mx_RoomView_invitePrompt {
|
||||
order: 2;
|
||||
|
||||
min-width: 0px;
|
||||
max-width: 960px;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
li.mx_RoomView_myReadMarker_container {
|
||||
height: 0px;
|
||||
margin: 0px;
|
||||
|
@ -160,8 +163,6 @@ hr.mx_RoomView_myReadMarker {
|
|||
}
|
||||
|
||||
.mx_RoomView_statusArea {
|
||||
order: 5;
|
||||
|
||||
width: 100%;
|
||||
flex: 0 0 auto;
|
||||
|
||||
|
@ -236,8 +237,6 @@ hr.mx_RoomView_myReadMarker {
|
|||
}
|
||||
|
||||
.mx_RoomView .mx_MessageComposer {
|
||||
order: 6;
|
||||
|
||||
width: 100%;
|
||||
flex: 0 0 auto;
|
||||
margin-right: 2px;
|
||||
|
|
|
@ -42,4 +42,8 @@ limitations under the License.
|
|||
.mx_VideoView_localVideoFeed video {
|
||||
width: auto;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_VideoView_localVideoFeed.mx_VideoView_localVideoFeed_flipped video {
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
|
|
|
@ -94,30 +94,26 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_RightPanel_footer .mx_RightPanel_invite {
|
||||
line-height: 35px;
|
||||
font-size: 14px;
|
||||
color: $primary-fg-color;
|
||||
padding-top: 13px;
|
||||
padding-left: 5px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.collapsed .mx_RightPanel_footer .mx_RightPanel_invite {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mx_RightPanel_invite .mx_RightPanel_icon {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.mx_RightPanel_invite .mx_RightPanel_icon object {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.mx_RightPanel_invite .mx_RightPanel_message {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
padding-left: 10px
|
||||
padding-left: 10px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.mx_MatrixChat_useCompactLayout {
|
||||
|
|
10
src/skins/vector/img/icon-delete-pink.svg
Normal file
10
src/skins/vector/img/icon-delete-pink.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#FF0064" d="M85.633,454.889c0,31.168,25.553,56.661,56.79,56.661h227.156c31.234,0,56.787-25.493,56.787-56.661
|
||||
V128.225H85.633V454.889z M468.958,43.042H362.479L326.828,0.45H185.173l-35.652,42.591H43.042v42.592h425.916V43.042z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 738 B |
Loading…
Reference in a new issue