Merge branches 'develop' and 't3chguy/alpha_room_list' of github.com:matrix-org/matrix-react-sdk into t3chguy/alpha_room_list
This commit is contained in:
commit
e6d8c4a576
22 changed files with 256 additions and 119 deletions
34
CHANGELOG.md
34
CHANGELOG.md
|
@ -1,3 +1,37 @@
|
||||||
|
Changes in [2.1.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.1.1) (2020-02-19)
|
||||||
|
===================================================================================================
|
||||||
|
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.1.0...v2.1.1)
|
||||||
|
|
||||||
|
* show spinner while loading local aliases
|
||||||
|
[\#4090](https://github.com/matrix-org/matrix-react-sdk/pull/4090)
|
||||||
|
* Don't index key verification events.
|
||||||
|
[\#4083](https://github.com/matrix-org/matrix-react-sdk/pull/4083)
|
||||||
|
* Get rid of dependence on usercontent.riot.im
|
||||||
|
[\#4046](https://github.com/matrix-org/matrix-react-sdk/pull/4046)
|
||||||
|
* also detect aliases using new /aliases endpoint for room access settings
|
||||||
|
[\#4089](https://github.com/matrix-org/matrix-react-sdk/pull/4089)
|
||||||
|
* get local aliases from /aliases in room settings
|
||||||
|
[\#4086](https://github.com/matrix-org/matrix-react-sdk/pull/4086)
|
||||||
|
* Start verification sessions in an E2E DM where possible
|
||||||
|
[\#4080](https://github.com/matrix-org/matrix-react-sdk/pull/4080)
|
||||||
|
* Only show supported verification methods
|
||||||
|
[\#4077](https://github.com/matrix-org/matrix-react-sdk/pull/4077)
|
||||||
|
* Use local echo in VerificationRequest for accepting/declining a verification
|
||||||
|
request
|
||||||
|
[\#4072](https://github.com/matrix-org/matrix-react-sdk/pull/4072)
|
||||||
|
* Report installed PWA, touch input status in rageshakes, analytics
|
||||||
|
[\#4078](https://github.com/matrix-org/matrix-react-sdk/pull/4078)
|
||||||
|
* refactor event grouping into separate helper classes
|
||||||
|
[\#4059](https://github.com/matrix-org/matrix-react-sdk/pull/4059)
|
||||||
|
* Find existing requests when starting a new verification request
|
||||||
|
[\#4070](https://github.com/matrix-org/matrix-react-sdk/pull/4070)
|
||||||
|
* Always speak the full text of the typing indicator when it updates.
|
||||||
|
[\#4074](https://github.com/matrix-org/matrix-react-sdk/pull/4074)
|
||||||
|
* Fix escaped markdown passing backslashes through
|
||||||
|
[\#4008](https://github.com/matrix-org/matrix-react-sdk/pull/4008)
|
||||||
|
* Move the sidebar to below the sidebar tab buttons for screen readers.
|
||||||
|
[\#4071](https://github.com/matrix-org/matrix-react-sdk/pull/4071)
|
||||||
|
|
||||||
Changes in [2.1.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.1.0) (2020-02-17)
|
Changes in [2.1.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.1.0) (2020-02-17)
|
||||||
===================================================================================================
|
===================================================================================================
|
||||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.1.0-rc.2...v2.1.0)
|
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.1.0-rc.2...v2.1.0)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "matrix-react-sdk",
|
"name": "matrix-react-sdk",
|
||||||
"version": "2.1.0",
|
"version": "2.1.1",
|
||||||
"description": "SDK for matrix.org using React",
|
"description": "SDK for matrix.org using React",
|
||||||
"author": "matrix.org",
|
"author": "matrix.org",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
@ -35,7 +35,7 @@ do
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
exec ./node_modules/matrix-js-sdk/release.sh -z "$@"
|
./node_modules/matrix-js-sdk/release.sh -z "$@"
|
||||||
|
|
||||||
release="${1#v}"
|
release="${1#v}"
|
||||||
prerelease=0
|
prerelease=0
|
||||||
|
|
|
@ -32,7 +32,7 @@ import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientB
|
||||||
import * as StorageManager from './utils/StorageManager';
|
import * as StorageManager from './utils/StorageManager';
|
||||||
import IdentityAuthClient from './IdentityAuthClient';
|
import IdentityAuthClient from './IdentityAuthClient';
|
||||||
import { crossSigningCallbacks } from './CrossSigningManager';
|
import { crossSigningCallbacks } from './CrossSigningManager';
|
||||||
import {SCAN_QR_CODE_METHOD, SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode";
|
import {SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode";
|
||||||
|
|
||||||
interface MatrixClientCreds {
|
interface MatrixClientCreds {
|
||||||
homeserverUrl: string,
|
homeserverUrl: string,
|
||||||
|
@ -221,7 +221,6 @@ class _MatrixClientPeg {
|
||||||
verificationMethods: [
|
verificationMethods: [
|
||||||
verificationMethods.SAS,
|
verificationMethods.SAS,
|
||||||
SHOW_QR_CODE_METHOD,
|
SHOW_QR_CODE_METHOD,
|
||||||
SCAN_QR_CODE_METHOD, // XXX: We don't actually support scanning yet!
|
|
||||||
verificationMethods.RECIPROCATE_QR_CODE,
|
verificationMethods.RECIPROCATE_QR_CODE,
|
||||||
],
|
],
|
||||||
unstableClientRelationAggregation: true,
|
unstableClientRelationAggregation: true,
|
||||||
|
|
|
@ -153,10 +153,12 @@ const Notifier = {
|
||||||
},
|
},
|
||||||
|
|
||||||
start: function() {
|
start: function() {
|
||||||
this.boundOnEvent = this.onEvent.bind(this);
|
// do not re-bind in the case of repeated call
|
||||||
this.boundOnSyncStateChange = this.onSyncStateChange.bind(this);
|
this.boundOnEvent = this.boundOnEvent || this.onEvent.bind(this);
|
||||||
this.boundOnRoomReceipt = this.onRoomReceipt.bind(this);
|
this.boundOnSyncStateChange = this.boundOnSyncStateChange || this.onSyncStateChange.bind(this);
|
||||||
this.boundOnEventDecrypted = this.onEventDecrypted.bind(this);
|
this.boundOnRoomReceipt = this.boundOnRoomReceipt || this.onRoomReceipt.bind(this);
|
||||||
|
this.boundOnEventDecrypted = this.boundOnEventDecrypted || this.onEventDecrypted.bind(this);
|
||||||
|
|
||||||
MatrixClientPeg.get().on('event', this.boundOnEvent);
|
MatrixClientPeg.get().on('event', this.boundOnEvent);
|
||||||
MatrixClientPeg.get().on('Room.receipt', this.boundOnRoomReceipt);
|
MatrixClientPeg.get().on('Room.receipt', this.boundOnRoomReceipt);
|
||||||
MatrixClientPeg.get().on('Event.decrypted', this.boundOnEventDecrypted);
|
MatrixClientPeg.get().on('Event.decrypted', this.boundOnEventDecrypted);
|
||||||
|
@ -166,7 +168,7 @@ const Notifier = {
|
||||||
},
|
},
|
||||||
|
|
||||||
stop: function() {
|
stop: function() {
|
||||||
if (MatrixClientPeg.get() && this.boundOnRoomTimeline) {
|
if (MatrixClientPeg.get()) {
|
||||||
MatrixClientPeg.get().removeListener('Event', this.boundOnEvent);
|
MatrixClientPeg.get().removeListener('Event', this.boundOnEvent);
|
||||||
MatrixClientPeg.get().removeListener('Room.receipt', this.boundOnRoomReceipt);
|
MatrixClientPeg.get().removeListener('Room.receipt', this.boundOnRoomReceipt);
|
||||||
MatrixClientPeg.get().removeListener('Event.decrypted', this.boundOnEventDecrypted);
|
MatrixClientPeg.get().removeListener('Event.decrypted', this.boundOnEventDecrypted);
|
||||||
|
|
|
@ -46,9 +46,18 @@ export default class ManageEventIndexDialog extends React.Component {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateCurrentRoom(room) {
|
updateCurrentRoom = async (room) => {
|
||||||
const eventIndex = EventIndexPeg.get();
|
const eventIndex = EventIndexPeg.get();
|
||||||
const stats = await eventIndex.getStats();
|
let stats;
|
||||||
|
|
||||||
|
try {
|
||||||
|
stats = await eventIndex.getStats();
|
||||||
|
} catch {
|
||||||
|
// This call may fail if sporadically, not a huge issue as we will
|
||||||
|
// try later again and probably succeed.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let currentRoom = null;
|
let currentRoom = null;
|
||||||
|
|
||||||
if (room) currentRoom = room.name;
|
if (room) currentRoom = room.name;
|
||||||
|
@ -63,13 +72,13 @@ export default class ManageEventIndexDialog extends React.Component {
|
||||||
roomCount: roomCount,
|
roomCount: roomCount,
|
||||||
currentRoom: currentRoom,
|
currentRoom: currentRoom,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
componentWillUnmount(): void {
|
componentWillUnmount(): void {
|
||||||
const eventIndex = EventIndexPeg.get();
|
const eventIndex = EventIndexPeg.get();
|
||||||
|
|
||||||
if (eventIndex !== null) {
|
if (eventIndex !== null) {
|
||||||
eventIndex.removeListener("changedCheckpoint", this.updateCurrentRoom.bind(this));
|
eventIndex.removeListener("changedCheckpoint", this.updateCurrentRoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,14 +92,21 @@ export default class ManageEventIndexDialog extends React.Component {
|
||||||
const eventIndex = EventIndexPeg.get();
|
const eventIndex = EventIndexPeg.get();
|
||||||
|
|
||||||
if (eventIndex !== null) {
|
if (eventIndex !== null) {
|
||||||
eventIndex.on("changedCheckpoint", this.updateCurrentRoom.bind(this));
|
eventIndex.on("changedCheckpoint", this.updateCurrentRoom);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const stats = await eventIndex.getStats();
|
||||||
|
eventIndexSize = stats.size;
|
||||||
|
eventCount = stats.eventCount;
|
||||||
|
} catch {
|
||||||
|
// This call may fail if sporadically, not a huge issue as we
|
||||||
|
// will try later again in the updateCurrentRoom call and
|
||||||
|
// probably succeed.
|
||||||
|
}
|
||||||
|
|
||||||
const stats = await eventIndex.getStats();
|
|
||||||
const roomStats = eventIndex.crawlingRooms();
|
const roomStats = eventIndex.crawlingRooms();
|
||||||
eventIndexSize = stats.size;
|
|
||||||
crawlingRoomsCount = roomStats.crawlingRooms.size;
|
crawlingRoomsCount = roomStats.crawlingRooms.size;
|
||||||
roomCount = roomStats.totalRooms.size;
|
roomCount = roomStats.totalRooms.size;
|
||||||
eventCount = stats.eventCount;
|
|
||||||
|
|
||||||
const room = eventIndex.currentRoom();
|
const room = eventIndex.currentRoom();
|
||||||
if (room) currentRoom = room.name;
|
if (room) currentRoom = room.name;
|
||||||
|
|
|
@ -95,8 +95,8 @@ const FilePanel = createReactClass({
|
||||||
// this could be made more general in the future or the filter logic
|
// this could be made more general in the future or the filter logic
|
||||||
// could be fixed.
|
// could be fixed.
|
||||||
if (EventIndexPeg.get() !== null) {
|
if (EventIndexPeg.get() !== null) {
|
||||||
client.on('Room.timeline', this.onRoomTimeline.bind(this));
|
client.on('Room.timeline', this.onRoomTimeline);
|
||||||
client.on('Event.decrypted', this.onEventDecrypted.bind(this));
|
client.on('Event.decrypted', this.onEventDecrypted);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -107,8 +107,8 @@ const FilePanel = createReactClass({
|
||||||
if (!MatrixClientPeg.get().isRoomEncrypted(this.props.roomId)) return;
|
if (!MatrixClientPeg.get().isRoomEncrypted(this.props.roomId)) return;
|
||||||
|
|
||||||
if (EventIndexPeg.get() !== null) {
|
if (EventIndexPeg.get() !== null) {
|
||||||
client.removeListener('Room.timeline', this.onRoomTimeline.bind(this));
|
client.removeListener('Room.timeline', this.onRoomTimeline);
|
||||||
client.removeListener('Event.decrypted', this.onEventDecrypted.bind(this));
|
client.removeListener('Event.decrypted', this.onEventDecrypted);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ import { ThemeWatcher } from "../../theme";
|
||||||
import { storeRoomAliasInCache } from '../../RoomAliasCache';
|
import { storeRoomAliasInCache } from '../../RoomAliasCache';
|
||||||
import { defer } from "../../utils/promise";
|
import { defer } from "../../utils/promise";
|
||||||
import ToastStore from "../../stores/ToastStore";
|
import ToastStore from "../../stores/ToastStore";
|
||||||
|
import * as StorageManager from "../../utils/StorageManager";
|
||||||
|
|
||||||
/** constants for MatrixChat.state.view */
|
/** constants for MatrixChat.state.view */
|
||||||
export const VIEWS = {
|
export const VIEWS = {
|
||||||
|
@ -1193,6 +1194,8 @@ export default createReactClass({
|
||||||
} else {
|
} else {
|
||||||
this._showScreenAfterLogin();
|
this._showScreenAfterLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StorageManager.tryPersistStorage();
|
||||||
},
|
},
|
||||||
|
|
||||||
_showScreenAfterLogin: function() {
|
_showScreenAfterLogin: function() {
|
||||||
|
|
|
@ -92,6 +92,7 @@ export default class RightPanel extends React.Component {
|
||||||
// not mounted in time to get the dispatch.
|
// not mounted in time to get the dispatch.
|
||||||
// Until then, let this code serve as a warning from history.
|
// Until then, let this code serve as a warning from history.
|
||||||
if (
|
if (
|
||||||
|
rps.roomPanelPhaseParams.member &&
|
||||||
userForPanel.userId === rps.roomPanelPhaseParams.member.userId &&
|
userForPanel.userId === rps.roomPanelPhaseParams.member.userId &&
|
||||||
rps.roomPanelPhaseParams.verificationRequest
|
rps.roomPanelPhaseParams.verificationRequest
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -414,11 +414,16 @@ export default createReactClass({
|
||||||
}
|
}
|
||||||
// XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID)
|
// XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID)
|
||||||
const permalinkButton = (
|
const permalinkButton = (
|
||||||
<MenuItem className="mx_MessageContextMenu_field">
|
<MenuItem
|
||||||
<a href={permalink} target="_blank" rel="noopener" onClick={this.onPermalinkClick} tabIndex={-1}>
|
element="a"
|
||||||
{ mxEvent.isRedacted() || mxEvent.getType() !== 'm.room.message'
|
className="mx_MessageContextMenu_field"
|
||||||
? _t('Share Permalink') : _t('Share Message') }
|
onClick={this.onPermalinkClick}
|
||||||
</a>
|
href={permalink}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
>
|
||||||
|
{ mxEvent.isRedacted() || mxEvent.getType() !== 'm.room.message'
|
||||||
|
? _t('Share Permalink') : _t('Share Message') }
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -436,16 +441,15 @@ export default createReactClass({
|
||||||
isUrlPermitted(mxEvent.event.content.external_url)
|
isUrlPermitted(mxEvent.event.content.external_url)
|
||||||
) {
|
) {
|
||||||
externalURLButton = (
|
externalURLButton = (
|
||||||
<MenuItem className="mx_MessageContextMenu_field">
|
<MenuItem
|
||||||
<a
|
element="a"
|
||||||
href={mxEvent.event.content.external_url}
|
className="mx_MessageContextMenu_field"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
onClick={this.closeMenu}
|
onClick={this.closeMenu}
|
||||||
tabIndex={-1}
|
href={mxEvent.event.content.external_url}
|
||||||
>
|
>
|
||||||
{ _t('Source URL') }
|
{ _t('Source URL') }
|
||||||
</a>
|
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {verificationMethods} from 'matrix-js-sdk/src/crypto';
|
||||||
import {ensureDMExists} from "../../../createRoom";
|
import {ensureDMExists} from "../../../createRoom";
|
||||||
import dis from "../../../dispatcher";
|
import dis from "../../../dispatcher";
|
||||||
import SettingsStore from '../../../settings/SettingsStore';
|
import SettingsStore from '../../../settings/SettingsStore';
|
||||||
import {SCAN_QR_CODE_METHOD, SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode";
|
import {SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode";
|
||||||
import VerificationQREmojiOptions from "../verification/VerificationQREmojiOptions";
|
import VerificationQREmojiOptions from "../verification/VerificationQREmojiOptions";
|
||||||
|
|
||||||
const MODE_LEGACY = 'legacy';
|
const MODE_LEGACY = 'legacy';
|
||||||
|
@ -135,7 +135,6 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||||
this._request = await client.requestVerification(this.props.userId, [
|
this._request = await client.requestVerification(this.props.userId, [
|
||||||
verificationMethods.SAS,
|
verificationMethods.SAS,
|
||||||
SHOW_QR_CODE_METHOD,
|
SHOW_QR_CODE_METHOD,
|
||||||
SCAN_QR_CODE_METHOD,
|
|
||||||
verificationMethods.RECIPROCATE_QR_CODE,
|
verificationMethods.RECIPROCATE_QR_CODE,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,15 @@ export default class VerificationRequestDialog extends React.Component {
|
||||||
onFinished: PropTypes.func.isRequired,
|
onFinished: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
this.onFinished = this.onFinished.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const BaseDialog = sdk.getComponent("views.dialogs.BaseDialog");
|
const BaseDialog = sdk.getComponent("views.dialogs.BaseDialog");
|
||||||
const EncryptionPanel = sdk.getComponent("views.right_panel.EncryptionPanel");
|
const EncryptionPanel = sdk.getComponent("views.right_panel.EncryptionPanel");
|
||||||
return <BaseDialog className="mx_InfoDialog" onFinished={this.props.onFinished}
|
return <BaseDialog className="mx_InfoDialog" onFinished={this.onFinished}
|
||||||
contentId="mx_Dialog_content"
|
contentId="mx_Dialog_content"
|
||||||
title={_t("Verification Request")}
|
title={_t("Verification Request")}
|
||||||
hasCancel={true}
|
hasCancel={true}
|
||||||
|
@ -42,4 +47,9 @@ export default class VerificationRequestDialog extends React.Component {
|
||||||
/>
|
/>
|
||||||
</BaseDialog>;
|
</BaseDialog>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onFinished() {
|
||||||
|
this.props.verificationRequest.cancel();
|
||||||
|
this.props.onFinished();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,8 @@ const Pill = createReactClass({
|
||||||
case Pill.TYPE_ROOM_MENTION: {
|
case Pill.TYPE_ROOM_MENTION: {
|
||||||
const localRoom = resourceId[0] === '#' ?
|
const localRoom = resourceId[0] === '#' ?
|
||||||
MatrixClientPeg.get().getRooms().find((r) => {
|
MatrixClientPeg.get().getRooms().find((r) => {
|
||||||
return r.getAliases().includes(resourceId);
|
return r.getCanonicalAlias() === resourceId ||
|
||||||
|
r.getAliases().includes(resourceId);
|
||||||
}) : MatrixClientPeg.get().getRoom(resourceId);
|
}) : MatrixClientPeg.get().getRoom(resourceId);
|
||||||
room = localRoom;
|
room = localRoom;
|
||||||
if (!localRoom) {
|
if (!localRoom) {
|
||||||
|
|
|
@ -91,6 +91,7 @@ export default class AliasSettings extends React.Component {
|
||||||
remoteDomains: [], // [ domain.com, foobar.com ]
|
remoteDomains: [], // [ domain.com, foobar.com ]
|
||||||
canonicalAlias: null, // #canonical:domain.com
|
canonicalAlias: null, // #canonical:domain.com
|
||||||
updatingCanonicalAlias: false,
|
updatingCanonicalAlias: false,
|
||||||
|
localAliasesLoading: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (props.canonicalAliasEvent) {
|
if (props.canonicalAliasEvent) {
|
||||||
|
@ -102,28 +103,32 @@ export default class AliasSettings extends React.Component {
|
||||||
|
|
||||||
async componentWillMount() {
|
async componentWillMount() {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
if (await cli.doesServerSupportUnstableFeature("org.matrix.msc2432")) {
|
try {
|
||||||
const response = await cli.unstableGetLocalAliases(this.props.roomId);
|
if (await cli.doesServerSupportUnstableFeature("org.matrix.msc2432")) {
|
||||||
const localAliases = response.aliases;
|
const response = await cli.unstableGetLocalAliases(this.props.roomId);
|
||||||
const localDomain = cli.getDomain();
|
const localAliases = response.aliases;
|
||||||
const domainToAliases = Object.assign(
|
const localDomain = cli.getDomain();
|
||||||
{},
|
const domainToAliases = Object.assign(
|
||||||
// FIXME, any localhost alt_aliases will be ignored as they are overwritten by localAliases
|
{},
|
||||||
this.aliasesToDictionary(this._getAltAliases()),
|
// FIXME, any localhost alt_aliases will be ignored as they are overwritten by localAliases
|
||||||
{[localDomain]: localAliases || []},
|
this.aliasesToDictionary(this._getAltAliases()),
|
||||||
);
|
{[localDomain]: localAliases || []},
|
||||||
const remoteDomains = Object.keys(domainToAliases).filter((domain) => {
|
);
|
||||||
return domain !== localDomain && domainToAliases[domain].length > 0;
|
const remoteDomains = Object.keys(domainToAliases).filter((domain) => {
|
||||||
});
|
return domain !== localDomain && domainToAliases[domain].length > 0;
|
||||||
this.setState({ domainToAliases, remoteDomains });
|
});
|
||||||
} else {
|
this.setState({ domainToAliases, remoteDomains });
|
||||||
const state = {};
|
} else {
|
||||||
const localDomain = cli.getDomain();
|
const state = {};
|
||||||
state.domainToAliases = this.aliasEventsToDictionary(this.props.aliasEvents || []);
|
const localDomain = cli.getDomain();
|
||||||
state.remoteDomains = Object.keys(state.domainToAliases).filter((domain) => {
|
state.domainToAliases = this.aliasEventsToDictionary(this.props.aliasEvents || []);
|
||||||
return domain !== localDomain && state.domainToAliases[domain].length > 0;
|
state.remoteDomains = Object.keys(state.domainToAliases).filter((domain) => {
|
||||||
});
|
return domain !== localDomain && state.domainToAliases[domain].length > 0;
|
||||||
this.setState(state);
|
});
|
||||||
|
this.setState(state);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.setState({localAliasesLoading: false});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,26 +307,34 @@ export default class AliasSettings extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let localAliasesList;
|
||||||
|
if (this.state.localAliasesLoading) {
|
||||||
|
const Spinner = sdk.getComponent("elements.Spinner");
|
||||||
|
localAliasesList = <Spinner />;
|
||||||
|
} else {
|
||||||
|
localAliasesList = <EditableAliasesList
|
||||||
|
id="roomAliases"
|
||||||
|
className={"mx_RoomSettings_localAliases"}
|
||||||
|
items={this.state.domainToAliases[localDomain] || []}
|
||||||
|
newItem={this.state.newAlias}
|
||||||
|
onNewItemChanged={this.onNewAliasChanged}
|
||||||
|
canRemove={this.props.canSetAliases}
|
||||||
|
canEdit={this.props.canSetAliases}
|
||||||
|
onItemAdded={this.onLocalAliasAdded}
|
||||||
|
onItemRemoved={this.onLocalAliasDeleted}
|
||||||
|
itemsLabel={_t('Local addresses for this room:')}
|
||||||
|
noItemsLabel={_t('This room has no local addresses')}
|
||||||
|
placeholder={_t(
|
||||||
|
'New address (e.g. #foo:%(localDomain)s)', {localDomain: localDomain},
|
||||||
|
)}
|
||||||
|
domain={localDomain}
|
||||||
|
/>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mx_AliasSettings'>
|
<div className='mx_AliasSettings'>
|
||||||
{canonicalAliasSection}
|
{canonicalAliasSection}
|
||||||
<EditableAliasesList
|
{localAliasesList}
|
||||||
id="roomAliases"
|
|
||||||
className={"mx_RoomSettings_localAliases"}
|
|
||||||
items={this.state.domainToAliases[localDomain] || []}
|
|
||||||
newItem={this.state.newAlias}
|
|
||||||
onNewItemChanged={this.onNewAliasChanged}
|
|
||||||
canRemove={this.props.canSetAliases}
|
|
||||||
canEdit={this.props.canSetAliases}
|
|
||||||
onItemAdded={this.onLocalAliasAdded}
|
|
||||||
onItemRemoved={this.onLocalAliasDeleted}
|
|
||||||
itemsLabel={_t('Local addresses for this room:')}
|
|
||||||
noItemsLabel={_t('This room has no local addresses')}
|
|
||||||
placeholder={_t(
|
|
||||||
'New address (e.g. #foo:%(localDomain)s)', {localDomain: localDomain},
|
|
||||||
)}
|
|
||||||
domain={localDomain}
|
|
||||||
/>
|
|
||||||
{remoteAliasesSection}
|
{remoteAliasesSection}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -37,21 +37,29 @@ export default class EventIndexPanel extends React.Component {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateCurrentRoom(room) {
|
updateCurrentRoom = async (room) => {
|
||||||
const eventIndex = EventIndexPeg.get();
|
const eventIndex = EventIndexPeg.get();
|
||||||
const stats = await eventIndex.getStats();
|
let stats;
|
||||||
|
|
||||||
|
try {
|
||||||
|
stats = await eventIndex.getStats();
|
||||||
|
} catch {
|
||||||
|
// This call may fail if sporadically, not a huge issue as we will
|
||||||
|
// try later again and probably succeed.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
eventIndexSize: stats.size,
|
eventIndexSize: stats.size,
|
||||||
roomCount: stats.roomCount,
|
roomCount: stats.roomCount,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
componentWillUnmount(): void {
|
componentWillUnmount(): void {
|
||||||
const eventIndex = EventIndexPeg.get();
|
const eventIndex = EventIndexPeg.get();
|
||||||
|
|
||||||
if (eventIndex !== null) {
|
if (eventIndex !== null) {
|
||||||
eventIndex.removeListener("changedCheckpoint", this.updateCurrentRoom.bind(this));
|
eventIndex.removeListener("changedCheckpoint", this.updateCurrentRoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,11 +76,17 @@ export default class EventIndexPanel extends React.Component {
|
||||||
let roomCount = 0;
|
let roomCount = 0;
|
||||||
|
|
||||||
if (eventIndex !== null) {
|
if (eventIndex !== null) {
|
||||||
eventIndex.on("changedCheckpoint", this.updateCurrentRoom.bind(this));
|
eventIndex.on("changedCheckpoint", this.updateCurrentRoom);
|
||||||
|
|
||||||
const stats = await eventIndex.getStats();
|
try {
|
||||||
eventIndexSize = stats.size;
|
const stats = await eventIndex.getStats();
|
||||||
roomCount = stats.roomCount;
|
eventIndexSize = stats.size;
|
||||||
|
roomCount = stats.roomCount;
|
||||||
|
} catch {
|
||||||
|
// This call may fail if sporadically, not a huge issue as we
|
||||||
|
// will try later again in the updateCurrentRoom call and
|
||||||
|
// probably succeed.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
|
|
@ -107,20 +107,20 @@ export default class RolesRoomSettingsTab extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
MatrixClientPeg.get().on("RoomState.members", this._onRoomMembership.bind(this));
|
MatrixClientPeg.get().on("RoomState.members", this._onRoomMembership);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount(): void {
|
componentWillUnmount(): void {
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
if (client) {
|
if (client) {
|
||||||
client.removeListener("RoomState.members", this._onRoomMembership.bind(this));
|
client.removeListener("RoomState.members", this._onRoomMembership);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRoomMembership(event, state, member) {
|
_onRoomMembership = (event, state, member) => {
|
||||||
if (state.roomId !== this.props.roomId) return;
|
if (state.roomId !== this.props.roomId) return;
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
};
|
||||||
|
|
||||||
_populateDefaultPlEvents(eventsSection, stateLevel, eventsLevel) {
|
_populateDefaultPlEvents(eventsSection, stateLevel, eventsLevel) {
|
||||||
for (const desiredEvent of Object.keys(plEventsToShow)) {
|
for (const desiredEvent of Object.keys(plEventsToShow)) {
|
||||||
|
|
|
@ -240,6 +240,33 @@ export default class EventIndex extends EventEmitter {
|
||||||
this.crawlerCheckpoints.push(backwardsCheckpoint);
|
this.crawlerCheckpoints.push(backwardsCheckpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an event should be added to the event index.
|
||||||
|
*
|
||||||
|
* Most notably we filter events for which decryption failed, are redacted
|
||||||
|
* or aren't of a type that we know how to index.
|
||||||
|
*
|
||||||
|
* @param {MatrixEvent} ev The event that should checked.
|
||||||
|
* @returns {bool} Returns true if the event can be indexed, false
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
isValidEvent(ev) {
|
||||||
|
const isUsefulType = ["m.room.message", "m.room.name", "m.room.topic"].includes(ev.getType());
|
||||||
|
const validEventType = isUsefulType && !ev.isRedacted() && !ev.isDecryptionFailure();
|
||||||
|
|
||||||
|
let validMsgType = true;
|
||||||
|
|
||||||
|
if (ev.getType() === "m.room.message" && !ev.isRedacted()) {
|
||||||
|
// Expand this if there are more invalid msgtypes.
|
||||||
|
const msgtype = ev.getContent().msgtype;
|
||||||
|
|
||||||
|
if (!msgtype) validMsgType = false;
|
||||||
|
else validMsgType = !msgtype.startsWith("m.key.verification");
|
||||||
|
}
|
||||||
|
|
||||||
|
return validEventType && validMsgType;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue up live events to be added to the event index.
|
* Queue up live events to be added to the event index.
|
||||||
*
|
*
|
||||||
|
@ -248,10 +275,7 @@ export default class EventIndex extends EventEmitter {
|
||||||
async addLiveEventToIndex(ev) {
|
async addLiveEventToIndex(ev) {
|
||||||
const indexManager = PlatformPeg.get().getEventIndexingManager();
|
const indexManager = PlatformPeg.get().getEventIndexingManager();
|
||||||
|
|
||||||
if (["m.room.message", "m.room.name", "m.room.topic"]
|
if (!this.isValidEvent(ev)) return;
|
||||||
.indexOf(ev.getType()) == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const jsonEvent = ev.toJSON();
|
const jsonEvent = ev.toJSON();
|
||||||
const e = ev.isEncrypted() ? jsonEvent.decrypted : jsonEvent;
|
const e = ev.isEncrypted() ? jsonEvent.decrypted : jsonEvent;
|
||||||
|
@ -407,22 +431,11 @@ export default class EventIndex extends EventEmitter {
|
||||||
// Let us wait for all the events to get decrypted.
|
// Let us wait for all the events to get decrypted.
|
||||||
await Promise.all(decryptionPromises);
|
await Promise.all(decryptionPromises);
|
||||||
|
|
||||||
// We filter out events for which decryption failed, are redacted
|
|
||||||
// or aren't of a type that we know how to index.
|
|
||||||
const isValidEvent = (value) => {
|
|
||||||
return ([
|
|
||||||
"m.room.message",
|
|
||||||
"m.room.name",
|
|
||||||
"m.room.topic",
|
|
||||||
].indexOf(value.getType()) >= 0
|
|
||||||
&& !value.isRedacted() && !value.isDecryptionFailure()
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO if there are no events at this point we're missing a lot
|
// TODO if there are no events at this point we're missing a lot
|
||||||
// decryption keys, do we want to retry this checkpoint at a later
|
// decryption keys, do we want to retry this checkpoint at a later
|
||||||
// stage?
|
// stage?
|
||||||
const filteredEvents = matrixEvents.filter(isValidEvent);
|
const filteredEvents = matrixEvents.filter(this.isValidEvent);
|
||||||
|
|
||||||
// Let us convert the events back into a format that EventIndex can
|
// Let us convert the events back into a format that EventIndex can
|
||||||
// consume.
|
// consume.
|
||||||
|
|
|
@ -54,14 +54,14 @@ export class IntegrationManagers {
|
||||||
startWatching(): void {
|
startWatching(): void {
|
||||||
this.stopWatching();
|
this.stopWatching();
|
||||||
this._client = MatrixClientPeg.get();
|
this._client = MatrixClientPeg.get();
|
||||||
this._client.on("accountData", this._onAccountData.bind(this));
|
this._client.on("accountData", this._onAccountData);
|
||||||
this._compileManagers();
|
this._compileManagers();
|
||||||
setInterval(() => this._setupHomeserverManagers(), HS_MANAGERS_REFRESH_INTERVAL);
|
setInterval(() => this._setupHomeserverManagers(), HS_MANAGERS_REFRESH_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
stopWatching(): void {
|
stopWatching(): void {
|
||||||
if (!this._client) return;
|
if (!this._client) return;
|
||||||
this._client.removeListener("accountData", this._onAccountData.bind(this));
|
this._client.removeListener("accountData", this._onAccountData);
|
||||||
if (this._wellknownRefreshTimerId !== null) clearInterval(this._wellknownRefreshTimerId);
|
if (this._wellknownRefreshTimerId !== null) clearInterval(this._wellknownRefreshTimerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,11 +136,11 @@ export class IntegrationManagers {
|
||||||
this._primaryManager = null; // reset primary
|
this._primaryManager = null; // reset primary
|
||||||
}
|
}
|
||||||
|
|
||||||
_onAccountData(ev: MatrixEvent): void {
|
_onAccountData = (ev: MatrixEvent): void => {
|
||||||
if (ev.getType() === 'm.widgets') {
|
if (ev.getType() === 'm.widgets') {
|
||||||
this._compileManagers();
|
this._compileManagers();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
hasManager(): boolean {
|
hasManager(): boolean {
|
||||||
return this._managers.length > 0;
|
return this._managers.length > 0;
|
||||||
|
|
|
@ -61,7 +61,7 @@ export class Mjolnir {
|
||||||
setup() {
|
setup() {
|
||||||
if (!MatrixClientPeg.get()) return;
|
if (!MatrixClientPeg.get()) return;
|
||||||
this._updateLists(SettingsStore.getValue("mjolnirRooms"));
|
this._updateLists(SettingsStore.getValue("mjolnirRooms"));
|
||||||
MatrixClientPeg.get().on("RoomState.events", this._onEvent.bind(this));
|
MatrixClientPeg.get().on("RoomState.events", this._onEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
|
@ -76,7 +76,7 @@ export class Mjolnir {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MatrixClientPeg.get()) return;
|
if (!MatrixClientPeg.get()) return;
|
||||||
MatrixClientPeg.get().removeListener("RoomState.events", this._onEvent.bind(this));
|
MatrixClientPeg.get().removeListener("RoomState.events", this._onEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOrCreatePersonalList(): Promise<BanList> {
|
async getOrCreatePersonalList(): Promise<BanList> {
|
||||||
|
@ -130,13 +130,13 @@ export class Mjolnir {
|
||||||
this._lists = this._lists.filter(b => b.roomId !== roomId);
|
this._lists = this._lists.filter(b => b.roomId !== roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onEvent(event) {
|
_onEvent = (event) => {
|
||||||
if (!MatrixClientPeg.get()) return;
|
if (!MatrixClientPeg.get()) return;
|
||||||
if (!this._roomIds.includes(event.getRoomId())) return;
|
if (!this._roomIds.includes(event.getRoomId())) return;
|
||||||
if (!ALL_RULE_TYPES.includes(event.getType())) return;
|
if (!ALL_RULE_TYPES.includes(event.getType())) return;
|
||||||
|
|
||||||
this._updateLists(this._roomIds);
|
this._updateLists(this._roomIds);
|
||||||
}
|
};
|
||||||
|
|
||||||
_onListsChanged(settingName, roomId, atLevel, newValue) {
|
_onListsChanged(settingName, roomId, atLevel, newValue) {
|
||||||
// We know that ban lists are only recorded at one level so we don't need to re-eval them
|
// We know that ban lists are only recorded at one level so we don't need to re-eval them
|
||||||
|
|
|
@ -106,6 +106,25 @@ export default async function sendBugReport(bugReportEndpoint, opts) {
|
||||||
body.append('enabled_labs', enabledLabs.join(', '));
|
body.append('enabled_labs', enabledLabs.join(', '));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add storage persistence/quota information
|
||||||
|
if (navigator.storage && navigator.storage.persisted) {
|
||||||
|
try {
|
||||||
|
body.append("storageManager_persisted", await navigator.storage.persisted());
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
if (navigator.storage && navigator.storage.estimate) {
|
||||||
|
try {
|
||||||
|
const estimate = await navigator.storage.estimate();
|
||||||
|
body.append("storageManager_quota", estimate.quota);
|
||||||
|
body.append("storageManager_usage", estimate.usage);
|
||||||
|
if (estimate.usageDetails) {
|
||||||
|
Object.keys(estimate.usageDetails).forEach(k => {
|
||||||
|
body.append(`storageManager_usage_${k}`, estimate.usageDetails[k]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
if (opts.sendLogs) {
|
if (opts.sendLogs) {
|
||||||
progressCallback(_t("Collecting logs"));
|
progressCallback(_t("Collecting logs"));
|
||||||
const logs = await rageshake.getLogsForReport();
|
const logs = await rageshake.getLogsForReport();
|
||||||
|
|
|
@ -43,6 +43,16 @@ function track(action) {
|
||||||
Analytics.trackEvent("StorageManager", action);
|
Analytics.trackEvent("StorageManager", action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function tryPersistStorage() {
|
||||||
|
if (navigator.storage && navigator.storage.persist) {
|
||||||
|
navigator.storage.persist().then(persistent => {
|
||||||
|
console.log("StorageManager: Persistent?", persistent);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("StorageManager: Persistence unsupported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function checkConsistency() {
|
export async function checkConsistency() {
|
||||||
log("Checking storage consistency");
|
log("Checking storage consistency");
|
||||||
log(`Local storage supported? ${!!localStorage}`);
|
log(`Local storage supported? ${!!localStorage}`);
|
||||||
|
|
|
@ -5760,10 +5760,9 @@ mathml-tag-names@^2.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.1.tgz#6dff66c99d55ecf739ca53c492e626f1d12a33cc"
|
resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.1.tgz#6dff66c99d55ecf739ca53c492e626f1d12a33cc"
|
||||||
integrity sha512-pWB896KPGSGkp1XtyzRBftpTzwSOL0Gfk0wLvxt4f2mgzjY19o0LxJ3U25vNWTzsh7da+KTbuXQoQ3lOJZ8WHw==
|
integrity sha512-pWB896KPGSGkp1XtyzRBftpTzwSOL0Gfk0wLvxt4f2mgzjY19o0LxJ3U25vNWTzsh7da+KTbuXQoQ3lOJZ8WHw==
|
||||||
|
|
||||||
matrix-js-sdk@5.0.0:
|
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
|
||||||
version "5.0.0"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.0.0.tgz#dcbab35f1afdb35ef0364eb232e78e0fb7dc2a5b"
|
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/a998006842ae558f02819ca84fbaad43685cc10b"
|
||||||
integrity sha512-A/aeE2Zn2OHq1n/9wIHCszrQZ7oXfThUHWi5Kz7illVCPUJ3JrZ31XVvx02k6vBasDcUtjAfZblHdTVN62cWLw==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.8.3"
|
"@babel/runtime" "^7.8.3"
|
||||||
another-json "^0.2.0"
|
another-json "^0.2.0"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue