Merge remote-tracking branch 'origin/develop' into travis/skinning/pt3-easy-comps

This commit is contained in:
Travis Ralston 2021-03-09 09:33:19 -07:00
commit 5b3367d44e
24 changed files with 73 additions and 65 deletions

View file

@ -22,9 +22,18 @@ limitations under the License.
float: right; float: right;
} }
.mx_ViewSource_label_bottom { .mx_ViewSource_separator {
clear: both; clear: both;
border-bottom: 1px solid #e5e5e5; border-bottom: 1px solid #e5e5e5;
padding-top: 0.7em;
padding-bottom: 0.7em;
}
.mx_ViewSource_heading {
font-size: $font-17px;
font-weight: 400;
color: $primary-fg-color;
margin-top: 0.7em;
} }
.mx_ViewSource pre { .mx_ViewSource pre {
@ -34,3 +43,7 @@ limitations under the License.
word-wrap: break-word; word-wrap: break-word;
white-space: pre-wrap; white-space: pre-wrap;
} }
.mx_ViewSource_details {
margin-top: 0.8em;
}

View file

@ -21,7 +21,7 @@ $left-gutter: 64px;
.mx_EventTile { .mx_EventTile {
> .mx_SenderProfile { > .mx_SenderProfile {
line-height: $font-20px; line-height: $font-20px;
padding-left: $left-gutter; margin-left: $left-gutter;
} }
> .mx_EventTile_line { > .mx_EventTile_line {

View file

@ -630,7 +630,7 @@ export default class CallHandler {
logger.debug("Mapped real room " + roomId + " to room ID " + mappedRoomId); logger.debug("Mapped real room " + roomId + " to room ID " + mappedRoomId);
const timeUntilTurnCresExpire = MatrixClientPeg.get().getTurnServersExpiry() - Date.now(); const timeUntilTurnCresExpire = MatrixClientPeg.get().getTurnServersExpiry() - Date.now();
console.log("Current turn creds expire in " + timeUntilTurnCresExpire + " seconds"); console.log("Current turn creds expire in " + timeUntilTurnCresExpire + " ms");
const call = createNewMatrixCall(MatrixClientPeg.get(), mappedRoomId); const call = createNewMatrixCall(MatrixClientPeg.get(), mappedRoomId);
this.calls.set(roomId, call); this.calls.set(roomId, call);

View file

@ -23,7 +23,7 @@ class Skinner {
if (!name) throw new Error(`Invalid component name: ${name}`); if (!name) throw new Error(`Invalid component name: ${name}`);
if (this.components === null) { if (this.components === null) {
throw new Error( throw new Error(
"Attempted to get a component before a skin has been loaded."+ `Attempted to get a component (${name}) before a skin has been loaded.`+
" This is probably because either:"+ " This is probably because either:"+
" a) Your app has not called sdk.loadSkin(), or"+ " a) Your app has not called sdk.loadSkin(), or"+
" b) A component has called getComponent at the root level", " b) A component has called getComponent at the root level",

View file

@ -441,15 +441,14 @@ export const Commands = [
}), }),
new Command({ new Command({
command: 'invite', command: 'invite',
args: '<user-id>', args: '<user-id> [<reason>]',
description: _td('Invites user with given id to current room'), description: _td('Invites user with given id to current room'),
runFn: function(roomId, args) { runFn: function(roomId, args) {
if (args) { if (args) {
const matches = args.match(/^(\S+)$/); const [address, reason] = args.split(/\s+(.+)/);
if (matches) { if (address) {
// We use a MultiInviter to re-use the invite logic, even though // We use a MultiInviter to re-use the invite logic, even though
// we're only inviting one user. // we're only inviting one user.
const address = matches[1];
// If we need an identity server but don't have one, things // If we need an identity server but don't have one, things
// get a bit more complex here, but we try to show something // get a bit more complex here, but we try to show something
// meaningful. // meaningful.
@ -490,7 +489,7 @@ export const Commands = [
} }
const inviter = new MultiInviter(roomId); const inviter = new MultiInviter(roomId);
return success(prom.then(() => { return success(prom.then(() => {
return inviter.invite([address]); return inviter.invite([address], reason);
}).then(() => { }).then(() => {
if (inviter.getCompletionState(address) !== "invited") { if (inviter.getCompletionState(address) !== "invited") {
throw new Error(inviter.getErrorText(address)); throw new Error(inviter.getErrorText(address));

View file

@ -16,8 +16,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
'use strict';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import request from 'browser-request'; import request from 'browser-request';

View file

@ -31,20 +31,49 @@ export default class ViewSource extends React.Component {
onFinished: PropTypes.func.isRequired, onFinished: PropTypes.func.isRequired,
roomId: PropTypes.string.isRequired, roomId: PropTypes.string.isRequired,
eventId: PropTypes.string.isRequired, eventId: PropTypes.string.isRequired,
isEncrypted: PropTypes.bool.isRequired,
decryptedContent: PropTypes.object,
}; };
render() { render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
return (
<BaseDialog className="mx_ViewSource" onFinished={this.props.onFinished} title={_t('View Source')}>
<div className="mx_ViewSource_label_left">Room ID: { this.props.roomId }</div>
<div className="mx_ViewSource_label_right">Event ID: { this.props.eventId }</div>
<div className="mx_ViewSource_label_bottom" />
<div className="mx_Dialog_content"> let content;
if (this.props.isEncrypted) {
content = <>
<details open className="mx_ViewSource_details">
<summary>
<span className="mx_ViewSource_heading">{_t("Decrypted event source")}</span>
</summary>
<SyntaxHighlight className="json">
{ JSON.stringify(this.props.decryptedContent, null, 2) }
</SyntaxHighlight>
</details>
<details className="mx_ViewSource_details">
<summary>
<span className="mx_ViewSource_heading">{_t("Original event source")}</span>
</summary>
<SyntaxHighlight className="json"> <SyntaxHighlight className="json">
{ JSON.stringify(this.props.content, null, 2) } { JSON.stringify(this.props.content, null, 2) }
</SyntaxHighlight> </SyntaxHighlight>
</details>
</>;
} else {
content = <>
<div className="mx_ViewSource_heading">{_t("Original event source")}</div>
<SyntaxHighlight className="json">
{ JSON.stringify(this.props.content, null, 2) }
</SyntaxHighlight>
</>;
}
return (
<BaseDialog className="mx_ViewSource" onFinished={this.props.onFinished} title={_t('View Source')}>
<div className="mx_Dialog_content">
<div className="mx_ViewSource_label_left">Room ID: { this.props.roomId }</div>
<div className="mx_ViewSource_label_left">Event ID: { this.props.eventId }</div>
<div className="mx_ViewSource_separator" />
{ content }
</div> </div>
</BaseDialog> </BaseDialog>
); );

View file

@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
'use strict';
import React from 'react'; import React from 'react';
import {replaceableComponent} from "../../../utils/replaceableComponent"; import {replaceableComponent} from "../../../utils/replaceableComponent";

View file

@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
'use strict';
import React from 'react'; import React from 'react';
import {replaceableComponent} from "../../../utils/replaceableComponent"; import {replaceableComponent} from "../../../utils/replaceableComponent";

View file

@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
'use strict';
import React from 'react'; import React from 'react';
import {replaceableComponent} from "../../../utils/replaceableComponent"; import {replaceableComponent} from "../../../utils/replaceableComponent";

View file

@ -132,18 +132,9 @@ export default class MessageContextMenu extends React.Component {
roomId: ev.getRoomId(), roomId: ev.getRoomId(),
eventId: ev.getId(), eventId: ev.getId(),
content: ev.event, content: ev.event,
}, 'mx_Dialog_viewsource'); isEncrypted: ev.isEncrypted(),
this.closeMenu();
};
onViewClearSourceClick = () => {
const ev = this.props.mxEvent.replacingEvent() || this.props.mxEvent;
const ViewSource = sdk.getComponent('structures.ViewSource');
Modal.createTrackedDialog('View Clear Event Source', '', ViewSource, {
roomId: ev.getRoomId(),
eventId: ev.getId(),
// FIXME: _clearEvent is private // FIXME: _clearEvent is private
content: ev._clearEvent, decryptedContent: ev._clearEvent,
}, 'mx_Dialog_viewsource'); }, 'mx_Dialog_viewsource');
this.closeMenu(); this.closeMenu();
}; };
@ -311,7 +302,6 @@ export default class MessageContextMenu extends React.Component {
let cancelButton; let cancelButton;
let forwardButton; let forwardButton;
let pinButton; let pinButton;
let viewClearSourceButton;
let unhidePreviewButton; let unhidePreviewButton;
let externalURLButton; let externalURLButton;
let quoteButton; let quoteButton;
@ -391,14 +381,6 @@ export default class MessageContextMenu extends React.Component {
</MenuItem> </MenuItem>
); );
if (mxEvent.getType() !== mxEvent.getWireType()) {
viewClearSourceButton = (
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onViewClearSourceClick}>
{ _t('View Decrypted Source') }
</MenuItem>
);
}
if (this.props.eventTileOps) { if (this.props.eventTileOps) {
if (this.props.eventTileOps.isWidgetHidden()) { if (this.props.eventTileOps.isWidgetHidden()) {
unhidePreviewButton = ( unhidePreviewButton = (
@ -483,7 +465,6 @@ export default class MessageContextMenu extends React.Component {
{ forwardButton } { forwardButton }
{ pinButton } { pinButton }
{ viewSourceButton } { viewSourceButton }
{ viewClearSourceButton }
{ unhidePreviewButton } { unhidePreviewButton }
{ permalinkButton } { permalinkButton }
{ quoteButton } { quoteButton }

View file

@ -118,7 +118,7 @@ export default class RoomSettingsDialog extends React.Component {
return ( return (
<BaseDialog className='mx_RoomSettingsDialog' hasCancel={true} <BaseDialog className='mx_RoomSettingsDialog' hasCancel={true}
onFinished={this.props.onFinished} title={_t("Room Settings - %(roomName)s", {roomName})}> onFinished={this.props.onFinished} title={_t("Room Settings - %(roomName)s", {roomName})}>
<div className='ms_SettingsDialog_content'> <div className='mx_SettingsDialog_content'>
<TabbedView tabs={this._getTabs()} /> <TabbedView tabs={this._getTabs()} />
</div> </div>
</BaseDialog> </BaseDialog>

View file

@ -157,7 +157,7 @@ export default class UserSettingsDialog extends React.Component {
return ( return (
<BaseDialog className='mx_UserSettingsDialog' hasCancel={true} <BaseDialog className='mx_UserSettingsDialog' hasCancel={true}
onFinished={this.props.onFinished} title={_t("Settings")}> onFinished={this.props.onFinished} title={_t("Settings")}>
<div className='ms_SettingsDialog_content'> <div className='mx_SettingsDialog_content'>
<TabbedView tabs={this._getTabs()} initialTabId={this.props.initialTabId} /> <TabbedView tabs={this._getTabs()} initialTabId={this.props.initialTabId} />
</div> </div>
</BaseDialog> </BaseDialog>

View file

@ -14,8 +14,6 @@
limitations under the License. limitations under the License.
*/ */
'use strict';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import FlairStore from '../../../stores/FlairStore'; import FlairStore from '../../../stores/FlairStore';

View file

@ -79,6 +79,9 @@ export default class EditHistoryMessage extends React.PureComponent {
roomId: this.props.mxEvent.getRoomId(), roomId: this.props.mxEvent.getRoomId(),
eventId: this.props.mxEvent.getId(), eventId: this.props.mxEvent.getId(),
content: this.props.mxEvent.event, content: this.props.mxEvent.event,
isEncrypted: this.props.mxEvent.isEncrypted(),
// FIXME: _clearEvent is private
decryptedContent: this.props.mxEvent._clearEvent,
}, 'mx_Dialog_viewsource'); }, 'mx_Dialog_viewsource');
}; };

View file

@ -14,8 +14,6 @@
limitations under the License. limitations under the License.
*/ */
'use strict';
import React from 'react'; import React from 'react';
import MFileBody from './MFileBody'; import MFileBody from './MFileBody';

View file

@ -2395,7 +2395,6 @@
"Cancel Sending": "Cancel Sending", "Cancel Sending": "Cancel Sending",
"Forward Message": "Forward Message", "Forward Message": "Forward Message",
"Pin Message": "Pin Message", "Pin Message": "Pin Message",
"View Decrypted Source": "View Decrypted Source",
"Unhide Preview": "Unhide Preview", "Unhide Preview": "Unhide Preview",
"Share Permalink": "Share Permalink", "Share Permalink": "Share Permalink",
"Share Message": "Share Message", "Share Message": "Share Message",
@ -2656,6 +2655,8 @@
"User menu": "User menu", "User menu": "User menu",
"Community and user menu": "Community and user menu", "Community and user menu": "Community and user menu",
"Could not load user profile": "Could not load user profile", "Could not load user profile": "Could not load user profile",
"Decrypted event source": "Decrypted event source",
"Original event source": "Original event source",
"Verify this login": "Verify this login", "Verify this login": "Verify this login",
"Session verified": "Session verified", "Session verified": "Session verified",
"Failed to send email": "Failed to send email", "Failed to send email": "Failed to send email",

View file

@ -15,8 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
'use strict';
import { _td } from '../languageHandler'; import { _td } from '../languageHandler';
import {StandardActions} from "./StandardActions"; import {StandardActions} from "./StandardActions";
import {PushRuleVectorState} from "./PushRuleVectorState"; import {PushRuleVectorState} from "./PushRuleVectorState";

View file

@ -15,8 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
'use strict';
export * from "./NotificationUtils"; export * from "./NotificationUtils";
export * from "./PushRuleVectorState"; export * from "./PushRuleVectorState";
export * from "./VectorPushRulesDefinitions"; export * from "./VectorPushRulesDefinitions";

View file

@ -15,8 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
"use strict";
// polyfill textencoder if necessary // polyfill textencoder if necessary
import * as TextEncodingUtf8 from 'text-encoding-utf-8'; import * as TextEncodingUtf8 from 'text-encoding-utf-8';
let TextEncoder = window.TextEncoder; let TextEncoder = window.TextEncoder;

View file

@ -53,13 +53,15 @@ export default class MultiInviter {
* instance of the class. * instance of the class.
* *
* @param {array} addrs Array of addresses to invite * @param {array} addrs Array of addresses to invite
* @param {string} reason Reason for inviting (optional)
* @returns {Promise} Resolved when all invitations in the queue are complete * @returns {Promise} Resolved when all invitations in the queue are complete
*/ */
invite(addrs) { invite(addrs, reason) {
if (this.addrs.length > 0) { if (this.addrs.length > 0) {
throw new Error("Already inviting/invited"); throw new Error("Already inviting/invited");
} }
this.addrs.push(...addrs); this.addrs.push(...addrs);
this.reason = reason;
for (const addr of this.addrs) { for (const addr of this.addrs) {
if (getAddressType(addr) === null) { if (getAddressType(addr) === null) {
@ -123,7 +125,7 @@ export default class MultiInviter {
} }
} }
return MatrixClientPeg.get().invite(roomId, addr); return MatrixClientPeg.get().invite(roomId, addr, undefined, this.reason);
} else { } else {
throw new Error('Unsupported address'); throw new Error('Unsupported address');
} }

View file

@ -30,9 +30,11 @@ import * as sdk from '../index';
* @param {string} name The dot-path name of the component being replaced. * @param {string} name The dot-path name of the component being replaced.
* @param {React.Component} origComponent The component that can be replaced * @param {React.Component} origComponent The component that can be replaced
* with a skinned version. If no skinned version is available, this component * with a skinned version. If no skinned version is available, this component
* will be used. * will be used. Note that this is automatically provided to the function and
* thus is optional for purposes of types.
* @returns {ClassDecorator} The decorator.
*/ */
export function replaceableComponent(name: string, origComponent: React.Component) { export function replaceableComponent(name: string, origComponent?: React.Component): ClassDecorator {
// Decorators return a function to override the class (origComponent). This // Decorators return a function to override the class (origComponent). This
// ultimately assumes that `getComponent()` won't throw an error and instead // ultimately assumes that `getComponent()` won't throw an error and instead
// return a falsey value like `null` when the skin doesn't have a component. // return a falsey value like `null` when the skin doesn't have a component.

View file

@ -1,5 +1,3 @@
"use strict";
import React from 'react'; import React from 'react';
import {MatrixClientPeg as peg} from '../src/MatrixClientPeg'; import {MatrixClientPeg as peg} from '../src/MatrixClientPeg';
import dis from '../src/dispatcher/dispatcher'; import dis from '../src/dispatcher/dispatcher';

View file

@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
"use strict";
import {TextEncoder} from "util"; import {TextEncoder} from "util";
import nodeCrypto from "crypto"; import nodeCrypto from "crypto";
import { Crypto } from "@peculiar/webcrypto"; import { Crypto } from "@peculiar/webcrypto";