diff --git a/CHANGELOG.md b/CHANGELOG.md index d4e0b41883..fa02dc1ae3 100644 --- a/CHANGELOG.md +++ b/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) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.1.0-rc.2...v2.1.0) diff --git a/package.json b/package.json index 793692d8b4..09393f052a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.1.0", + "version": "2.1.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { diff --git a/release.sh b/release.sh index c585708326..3c28084bb7 100755 --- a/release.sh +++ b/release.sh @@ -35,7 +35,7 @@ do fi done -exec ./node_modules/matrix-js-sdk/release.sh -z "$@" +./node_modules/matrix-js-sdk/release.sh -z "$@" release="${1#v}" prerelease=0 diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index 448c6d9e9b..98fcc85d60 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -32,7 +32,7 @@ import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientB import * as StorageManager from './utils/StorageManager'; import IdentityAuthClient from './IdentityAuthClient'; 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 { homeserverUrl: string, @@ -221,7 +221,6 @@ class _MatrixClientPeg { verificationMethods: [ verificationMethods.SAS, SHOW_QR_CODE_METHOD, - SCAN_QR_CODE_METHOD, // XXX: We don't actually support scanning yet! verificationMethods.RECIPROCATE_QR_CODE, ], unstableClientRelationAggregation: true, diff --git a/src/Notifier.js b/src/Notifier.js index b030f1b6f9..36a6f13bb6 100644 --- a/src/Notifier.js +++ b/src/Notifier.js @@ -153,10 +153,12 @@ const Notifier = { }, start: function() { - this.boundOnEvent = this.onEvent.bind(this); - this.boundOnSyncStateChange = this.onSyncStateChange.bind(this); - this.boundOnRoomReceipt = this.onRoomReceipt.bind(this); - this.boundOnEventDecrypted = this.onEventDecrypted.bind(this); + // do not re-bind in the case of repeated call + this.boundOnEvent = this.boundOnEvent || this.onEvent.bind(this); + this.boundOnSyncStateChange = this.boundOnSyncStateChange || this.onSyncStateChange.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('Room.receipt', this.boundOnRoomReceipt); MatrixClientPeg.get().on('Event.decrypted', this.boundOnEventDecrypted); @@ -166,7 +168,7 @@ const Notifier = { }, stop: function() { - if (MatrixClientPeg.get() && this.boundOnRoomTimeline) { + if (MatrixClientPeg.get()) { MatrixClientPeg.get().removeListener('Event', this.boundOnEvent); MatrixClientPeg.get().removeListener('Room.receipt', this.boundOnRoomReceipt); MatrixClientPeg.get().removeListener('Event.decrypted', this.boundOnEventDecrypted); diff --git a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.js b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.js index 5ae90b694e..f3ea3beb1c 100644 --- a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.js +++ b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.js @@ -46,9 +46,18 @@ export default class ManageEventIndexDialog extends React.Component { }; } - async updateCurrentRoom(room) { + updateCurrentRoom = async (room) => { 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; if (room) currentRoom = room.name; @@ -63,13 +72,13 @@ export default class ManageEventIndexDialog extends React.Component { roomCount: roomCount, currentRoom: currentRoom, }); - } + }; componentWillUnmount(): void { const eventIndex = EventIndexPeg.get(); 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(); 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(); - eventIndexSize = stats.size; crawlingRoomsCount = roomStats.crawlingRooms.size; roomCount = roomStats.totalRooms.size; - eventCount = stats.eventCount; const room = eventIndex.currentRoom(); if (room) currentRoom = room.name; diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js index 4c02f925fc..f8c03be864 100644 --- a/src/components/structures/FilePanel.js +++ b/src/components/structures/FilePanel.js @@ -95,8 +95,8 @@ const FilePanel = createReactClass({ // this could be made more general in the future or the filter logic // could be fixed. if (EventIndexPeg.get() !== null) { - client.on('Room.timeline', this.onRoomTimeline.bind(this)); - client.on('Event.decrypted', this.onEventDecrypted.bind(this)); + client.on('Room.timeline', this.onRoomTimeline); + client.on('Event.decrypted', this.onEventDecrypted); } }, @@ -107,8 +107,8 @@ const FilePanel = createReactClass({ if (!MatrixClientPeg.get().isRoomEncrypted(this.props.roomId)) return; if (EventIndexPeg.get() !== null) { - client.removeListener('Room.timeline', this.onRoomTimeline.bind(this)); - client.removeListener('Event.decrypted', this.onEventDecrypted.bind(this)); + client.removeListener('Room.timeline', this.onRoomTimeline); + client.removeListener('Event.decrypted', this.onEventDecrypted); } }, diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 3ccc4627e1..229c741310 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -65,6 +65,7 @@ import { ThemeWatcher } from "../../theme"; import { storeRoomAliasInCache } from '../../RoomAliasCache'; import { defer } from "../../utils/promise"; import ToastStore from "../../stores/ToastStore"; +import * as StorageManager from "../../utils/StorageManager"; /** constants for MatrixChat.state.view */ export const VIEWS = { @@ -1193,6 +1194,8 @@ export default createReactClass({ } else { this._showScreenAfterLogin(); } + + StorageManager.tryPersistStorage(); }, _showScreenAfterLogin: function() { diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index eddd26c857..20df323c10 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -92,6 +92,7 @@ export default class RightPanel extends React.Component { // not mounted in time to get the dispatch. // Until then, let this code serve as a warning from history. if ( + rps.roomPanelPhaseParams.member && userForPanel.userId === rps.roomPanelPhaseParams.member.userId && rps.roomPanelPhaseParams.verificationRequest ) { diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index 7215a45be2..ea5623fe48 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -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) const permalinkButton = ( - - - { mxEvent.isRedacted() || mxEvent.getType() !== 'm.room.message' - ? _t('Share Permalink') : _t('Share Message') } - + + { mxEvent.isRedacted() || mxEvent.getType() !== 'm.room.message' + ? _t('Share Permalink') : _t('Share Message') } ); @@ -436,16 +441,15 @@ export default createReactClass({ isUrlPermitted(mxEvent.event.content.external_url) ) { externalURLButton = ( - - - { _t('Source URL') } - + + { _t('Source URL') } ); } diff --git a/src/components/views/dialogs/DeviceVerifyDialog.js b/src/components/views/dialogs/DeviceVerifyDialog.js index 835b7daf02..f7826b9c27 100644 --- a/src/components/views/dialogs/DeviceVerifyDialog.js +++ b/src/components/views/dialogs/DeviceVerifyDialog.js @@ -27,7 +27,7 @@ import {verificationMethods} from 'matrix-js-sdk/src/crypto'; import {ensureDMExists} from "../../../createRoom"; import dis from "../../../dispatcher"; 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"; const MODE_LEGACY = 'legacy'; @@ -135,7 +135,6 @@ export default class DeviceVerifyDialog extends React.Component { this._request = await client.requestVerification(this.props.userId, [ verificationMethods.SAS, SHOW_QR_CODE_METHOD, - SCAN_QR_CODE_METHOD, verificationMethods.RECIPROCATE_QR_CODE, ]); diff --git a/src/components/views/dialogs/VerificationRequestDialog.js b/src/components/views/dialogs/VerificationRequestDialog.js index 8080fa09f3..abcf925f96 100644 --- a/src/components/views/dialogs/VerificationRequestDialog.js +++ b/src/components/views/dialogs/VerificationRequestDialog.js @@ -26,10 +26,15 @@ export default class VerificationRequestDialog extends React.Component { onFinished: PropTypes.func.isRequired, }; + constructor(...args) { + super(...args); + this.onFinished = this.onFinished.bind(this); + } + render() { const BaseDialog = sdk.getComponent("views.dialogs.BaseDialog"); const EncryptionPanel = sdk.getComponent("views.right_panel.EncryptionPanel"); - return ; } + + onFinished() { + this.props.verificationRequest.cancel(); + this.props.onFinished(); + } } diff --git a/src/components/views/elements/Pill.js b/src/components/views/elements/Pill.js index 59c0bde177..cd7277cdeb 100644 --- a/src/components/views/elements/Pill.js +++ b/src/components/views/elements/Pill.js @@ -128,7 +128,8 @@ const Pill = createReactClass({ case Pill.TYPE_ROOM_MENTION: { const localRoom = resourceId[0] === '#' ? MatrixClientPeg.get().getRooms().find((r) => { - return r.getAliases().includes(resourceId); + return r.getCanonicalAlias() === resourceId || + r.getAliases().includes(resourceId); }) : MatrixClientPeg.get().getRoom(resourceId); room = localRoom; if (!localRoom) { diff --git a/src/components/views/room_settings/AliasSettings.js b/src/components/views/room_settings/AliasSettings.js index d7befa488d..a52fa09c87 100644 --- a/src/components/views/room_settings/AliasSettings.js +++ b/src/components/views/room_settings/AliasSettings.js @@ -91,6 +91,7 @@ export default class AliasSettings extends React.Component { remoteDomains: [], // [ domain.com, foobar.com ] canonicalAlias: null, // #canonical:domain.com updatingCanonicalAlias: false, + localAliasesLoading: true, }; if (props.canonicalAliasEvent) { @@ -102,28 +103,32 @@ export default class AliasSettings extends React.Component { async componentWillMount() { const cli = MatrixClientPeg.get(); - if (await cli.doesServerSupportUnstableFeature("org.matrix.msc2432")) { - const response = await cli.unstableGetLocalAliases(this.props.roomId); - const localAliases = response.aliases; - 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()), - {[localDomain]: localAliases || []}, - ); - const remoteDomains = Object.keys(domainToAliases).filter((domain) => { - return domain !== localDomain && domainToAliases[domain].length > 0; - }); - this.setState({ domainToAliases, remoteDomains }); - } else { - const state = {}; - const localDomain = cli.getDomain(); - state.domainToAliases = this.aliasEventsToDictionary(this.props.aliasEvents || []); - state.remoteDomains = Object.keys(state.domainToAliases).filter((domain) => { - return domain !== localDomain && state.domainToAliases[domain].length > 0; - }); - this.setState(state); + try { + if (await cli.doesServerSupportUnstableFeature("org.matrix.msc2432")) { + const response = await cli.unstableGetLocalAliases(this.props.roomId); + const localAliases = response.aliases; + 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()), + {[localDomain]: localAliases || []}, + ); + const remoteDomains = Object.keys(domainToAliases).filter((domain) => { + return domain !== localDomain && domainToAliases[domain].length > 0; + }); + this.setState({ domainToAliases, remoteDomains }); + } else { + const state = {}; + const localDomain = cli.getDomain(); + state.domainToAliases = this.aliasEventsToDictionary(this.props.aliasEvents || []); + state.remoteDomains = Object.keys(state.domainToAliases).filter((domain) => { + return domain !== localDomain && state.domainToAliases[domain].length > 0; + }); + 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 = ; + } else { + localAliasesList = ; + } + return (
{canonicalAliasSection} - + {localAliasesList} {remoteAliasesSection}
); diff --git a/src/components/views/settings/EventIndexPanel.js b/src/components/views/settings/EventIndexPanel.js index 68faa53e53..80d93c4562 100644 --- a/src/components/views/settings/EventIndexPanel.js +++ b/src/components/views/settings/EventIndexPanel.js @@ -37,21 +37,29 @@ export default class EventIndexPanel extends React.Component { }; } - async updateCurrentRoom(room) { + updateCurrentRoom = async (room) => { 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({ eventIndexSize: stats.size, roomCount: stats.roomCount, }); - } + }; componentWillUnmount(): void { const eventIndex = EventIndexPeg.get(); 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; if (eventIndex !== null) { - eventIndex.on("changedCheckpoint", this.updateCurrentRoom.bind(this)); + eventIndex.on("changedCheckpoint", this.updateCurrentRoom); - const stats = await eventIndex.getStats(); - eventIndexSize = stats.size; - roomCount = stats.roomCount; + try { + const stats = await eventIndex.getStats(); + 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({ diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js index 42947d1fb2..a3a9cb78c5 100644 --- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js +++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js @@ -107,20 +107,20 @@ export default class RolesRoomSettingsTab extends React.Component { }; componentDidMount(): void { - MatrixClientPeg.get().on("RoomState.members", this._onRoomMembership.bind(this)); + MatrixClientPeg.get().on("RoomState.members", this._onRoomMembership); } componentWillUnmount(): void { const client = MatrixClientPeg.get(); 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; this.forceUpdate(); - } + }; _populateDefaultPlEvents(eventsSection, stateLevel, eventsLevel) { for (const desiredEvent of Object.keys(plEventsToShow)) { diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index 5769080511..c8a9a4c1fa 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -240,6 +240,33 @@ export default class EventIndex extends EventEmitter { 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. * @@ -248,10 +275,7 @@ export default class EventIndex extends EventEmitter { async addLiveEventToIndex(ev) { const indexManager = PlatformPeg.get().getEventIndexingManager(); - if (["m.room.message", "m.room.name", "m.room.topic"] - .indexOf(ev.getType()) == -1) { - return; - } + if (!this.isValidEvent(ev)) return; const jsonEvent = ev.toJSON(); 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. 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 // decryption keys, do we want to retry this checkpoint at a later // stage? - const filteredEvents = matrixEvents.filter(isValidEvent); + const filteredEvents = matrixEvents.filter(this.isValidEvent); // Let us convert the events back into a format that EventIndex can // consume. diff --git a/src/integrations/IntegrationManagers.js b/src/integrations/IntegrationManagers.js index c933e5c433..3ba1aab135 100644 --- a/src/integrations/IntegrationManagers.js +++ b/src/integrations/IntegrationManagers.js @@ -54,14 +54,14 @@ export class IntegrationManagers { startWatching(): void { this.stopWatching(); this._client = MatrixClientPeg.get(); - this._client.on("accountData", this._onAccountData.bind(this)); + this._client.on("accountData", this._onAccountData); this._compileManagers(); setInterval(() => this._setupHomeserverManagers(), HS_MANAGERS_REFRESH_INTERVAL); } stopWatching(): void { 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); } @@ -136,11 +136,11 @@ export class IntegrationManagers { this._primaryManager = null; // reset primary } - _onAccountData(ev: MatrixEvent): void { + _onAccountData = (ev: MatrixEvent): void => { if (ev.getType() === 'm.widgets') { this._compileManagers(); } - } + }; hasManager(): boolean { return this._managers.length > 0; diff --git a/src/mjolnir/Mjolnir.js b/src/mjolnir/Mjolnir.js index 4970d8e8af..0c99306278 100644 --- a/src/mjolnir/Mjolnir.js +++ b/src/mjolnir/Mjolnir.js @@ -61,7 +61,7 @@ export class Mjolnir { setup() { if (!MatrixClientPeg.get()) return; this._updateLists(SettingsStore.getValue("mjolnirRooms")); - MatrixClientPeg.get().on("RoomState.events", this._onEvent.bind(this)); + MatrixClientPeg.get().on("RoomState.events", this._onEvent); } stop() { @@ -76,7 +76,7 @@ export class Mjolnir { } if (!MatrixClientPeg.get()) return; - MatrixClientPeg.get().removeListener("RoomState.events", this._onEvent.bind(this)); + MatrixClientPeg.get().removeListener("RoomState.events", this._onEvent); } async getOrCreatePersonalList(): Promise { @@ -130,13 +130,13 @@ export class Mjolnir { this._lists = this._lists.filter(b => b.roomId !== roomId); } - _onEvent(event) { + _onEvent = (event) => { if (!MatrixClientPeg.get()) return; if (!this._roomIds.includes(event.getRoomId())) return; if (!ALL_RULE_TYPES.includes(event.getType())) return; this._updateLists(this._roomIds); - } + }; _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 diff --git a/src/rageshake/submit-rageshake.js b/src/rageshake/submit-rageshake.js index 091f64bf93..b17dc62168 100644 --- a/src/rageshake/submit-rageshake.js +++ b/src/rageshake/submit-rageshake.js @@ -106,6 +106,25 @@ export default async function sendBugReport(bugReportEndpoint, opts) { 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) { progressCallback(_t("Collecting logs")); const logs = await rageshake.getLogsForReport(); diff --git a/src/utils/StorageManager.js b/src/utils/StorageManager.js index c5a9f7aeed..4ed118da8a 100644 --- a/src/utils/StorageManager.js +++ b/src/utils/StorageManager.js @@ -43,6 +43,16 @@ function track(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() { log("Checking storage consistency"); log(`Local storage supported? ${!!localStorage}`); diff --git a/yarn.lock b/yarn.lock index 1ed39459d0..17b0b97ac9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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" integrity sha512-pWB896KPGSGkp1XtyzRBftpTzwSOL0Gfk0wLvxt4f2mgzjY19o0LxJ3U25vNWTzsh7da+KTbuXQoQ3lOJZ8WHw== -matrix-js-sdk@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.0.0.tgz#dcbab35f1afdb35ef0364eb232e78e0fb7dc2a5b" - integrity sha512-A/aeE2Zn2OHq1n/9wIHCszrQZ7oXfThUHWi5Kz7illVCPUJ3JrZ31XVvx02k6vBasDcUtjAfZblHdTVN62cWLw== +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": + version "5.0.1" + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/a998006842ae558f02819ca84fbaad43685cc10b" dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0"