diff --git a/src/Lifecycle.js b/src/Lifecycle.js index e891ab5984..295ffe44f4 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -412,6 +412,7 @@ export function stopMatrixClient() { if (cli) { cli.stopClient(); cli.removeAllListeners(); + cli.store.deleteAllData(); MatrixClientPeg.unset(); } } diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index 9c0daf4726..3759aa72c1 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -16,6 +16,7 @@ limitations under the License. 'use strict'; +import q from "q"; import Matrix from 'matrix-js-sdk'; import utils from 'matrix-js-sdk/lib/utils'; import EventTimeline from 'matrix-js-sdk/lib/models/event-timeline'; @@ -71,7 +72,16 @@ class MatrixClientPeg { const opts = utils.deepCopy(this.opts); // the react sdk doesn't work without this, so don't allow opts.pendingEventOrdering = "detached"; - this.get().startClient(opts); + + let promise = this.matrixClient.store.startup(); + // log any errors when starting up the database (if one exists) + promise.catch((err) => { console.error(err); }); + + // regardless of errors, start the client. If we did error out, we'll + // just end up doing a full initial /sync. + promise.finally(() => { + this.get().startClient(opts); + }); } getCredentials(): MatrixClientCreds { @@ -111,6 +121,14 @@ class MatrixClientPeg { if (localStorage) { opts.sessionStore = new Matrix.WebStorageSessionStore(localStorage); } + if (window.indexedDB && localStorage) { + opts.store = new Matrix.IndexedDBStore( + new Matrix.IndexedDBStoreBackend(window.indexedDB), + new Matrix.SyncAccumulator(), { + localStorage: localStorage, + } + ); + } this.matrixClient = Matrix.createClient(opts); diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 961277a4a1..aa9470f126 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -175,6 +175,7 @@ export default React.createClass({ collapsedRhs={this.props.collapse_rhs} enableLabs={this.props.config.enableLabs} referralBaseUrl={this.props.config.referralBaseUrl} + teamToken={this.props.teamToken} />; if (!this.props.collapse_rhs) right_panel = ; break; diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 72680a3eac..3265249105 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -464,6 +464,10 @@ module.exports = React.createClass({ this.notifyNewScreen('directory'); break; case 'view_home_page': + if (!this._teamToken) { + dis.dispatch({action: 'view_room_directory'}); + return; + } this._setPage(PageTypes.HomePage); this.notifyNewScreen('home'); break; diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index fdade60dfd..f8240e247b 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -109,6 +109,10 @@ module.exports = React.createClass({ // true if RightPanel is collapsed collapsedRhs: React.PropTypes.bool, + + // Team token for the referral link. If falsy, the referral section will + // not appear + teamToken: React.PropTypes.string, }, getDefaultProps: function() { @@ -462,7 +466,7 @@ module.exports = React.createClass({ }, _renderReferral: function() { - const teamToken = window.localStorage.getItem('mx_team_token'); + const teamToken = this.props.teamToken; if (!teamToken) { return null; } diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js index 4d1285678b..3247f5a90b 100644 --- a/src/components/views/rooms/RoomSettings.js +++ b/src/components/views/rooms/RoomSettings.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -35,6 +36,47 @@ function parseIntWithDefault(val, def) { return isNaN(res) ? def : res; } +const BannedUser = React.createClass({ + propTypes: { + member: React.PropTypes.object.isRequired, // js-sdk RoomMember + }, + + _onUnbanClick: function() { + const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog"); + Modal.createDialog(ConfirmUserActionDialog, { + member: this.props.member, + action: 'Unban', + danger: false, + onFinished: (proceed) => { + if (!proceed) return; + + MatrixClientPeg.get().unban( + this.props.member.roomId, this.props.member.userId, + ).catch((err) => { + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + Modal.createDialog(ErrorDialog, { + title: "Failed to unban", + description: err.message, + }); + }).done(); + }, + }); + }, + + render: function() { + return ( +
  • + + Unban + + {this.props.member.userId} +
  • + ); + } +}); + module.exports = React.createClass({ displayName: 'RoomSettings', @@ -74,6 +116,9 @@ module.exports = React.createClass({ componentWillMount: function() { ScalarMessaging.startListening(); + + MatrixClientPeg.get().on("RoomMember.membership", this._onRoomMemberMembership); + MatrixClientPeg.get().getRoomDirectoryVisibility( this.props.room.roomId ).done((result) => { @@ -102,6 +147,11 @@ module.exports = React.createClass({ componentWillUnmount: function() { ScalarMessaging.stopListening(); + const cli = MatrixClientPeg.get(); + if (cli) { + cli.removeListener("RoomMember.membership", this._onRoomMemberMembership); + } + dis.dispatch({ action: 'ui_opacity', sideOpacity: 1.0, @@ -501,6 +551,11 @@ module.exports = React.createClass({ }); }, + _onRoomMemberMembership: function() { + // Update, since our banned user list may have changed + this.forceUpdate(); + }, + _renderEncryptionSection: function() { var cli = MatrixClientPeg.get(); var roomState = this.props.room.currentState; @@ -611,11 +666,9 @@ module.exports = React.createClass({

    Banned users