Revert merge up from develop

This commit is contained in:
wmwragg 2016-07-27 14:16:17 +01:00
parent 6d141d1a7b
commit 3df746ef14
7 changed files with 130 additions and 143 deletions

View file

@ -13,7 +13,7 @@
"reskindex": "./reskindex.js" "reskindex": "./reskindex.js"
}, },
"scripts": { "scripts": {
"reskindex": "reskindex -h header", "reskindex": "./reskindex.js -h header",
"build": "babel src -d lib --source-maps --stage 1", "build": "babel src -d lib --source-maps --stage 1",
"start": "babel src -w -d lib --source-maps --stage 1", "start": "babel src -w -d lib --source-maps --stage 1",
"lint": "eslint src/", "lint": "eslint src/",
@ -42,10 +42,10 @@
"matrix-js-sdk": "matrix-org/matrix-js-sdk#develop", "matrix-js-sdk": "matrix-org/matrix-js-sdk#develop",
"optimist": "^0.6.1", "optimist": "^0.6.1",
"q": "^1.4.1", "q": "^1.4.1",
"react": "^15.0.1", "react": "^15.2.1",
"react-addons-css-transition-group": "^15.1.0", "react-addons-css-transition-group": "^15.2.1",
"react-dom": "^15.0.1", "react-dom": "^15.2.1",
"react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#c3d942e", "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#dbf0abf",
"sanitize-html": "^1.11.1", "sanitize-html": "^1.11.1",
"velocity-vector": "vector-im/velocity#059e3b2", "velocity-vector": "vector-im/velocity#059e3b2",
"whatwg-fetch": "^1.0.0" "whatwg-fetch": "^1.0.0"

View file

@ -1,51 +0,0 @@
/*
Copyright 2015 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const IS_GUEST_KEY = "matrix-is-guest";
class GuestAccess {
constructor(localStorage) {
this.localStorage = localStorage;
try {
this._isGuest = localStorage.getItem(IS_GUEST_KEY) === "true";
}
catch (e) {} // don't care
}
setPeekedRoom(roomId) {
// we purposefully do not persist this to local storage as peeking is
// entirely transient.
this._peekedRoomId = roomId;
}
getPeekedRoom() {
return this._peekedRoomId;
}
isGuest() {
return this._isGuest;
}
markAsGuest(isGuest) {
try {
this.localStorage.setItem(IS_GUEST_KEY, JSON.stringify(isGuest));
} catch (e) {} // ignore. If they don't do LS, they'll just get a new account.
this._isGuest = isGuest;
this._peekedRoomId = null;
}
}
module.exports = GuestAccess;

View file

@ -16,13 +16,9 @@ limitations under the License.
'use strict'; 'use strict';
// A thing that holds your Matrix Client import Matrix from 'matrix-js-sdk';
var Matrix = require("matrix-js-sdk");
var GuestAccess = require("./GuestAccess");
let matrixClient: MatrixClient = null; const localStorage = window.localStorage;
var localStorage = window.localStorage;
function deviceId() { function deviceId() {
// XXX: is Math.random()'s deterministicity a problem here? // XXX: is Math.random()'s deterministicity a problem here?
@ -35,7 +31,106 @@ function deviceId() {
return id; return id;
} }
function createClientForPeg(hs_url, is_url, user_id, access_token, guestAccess) { /**
* Wrapper object for handling the js-sdk Matrix Client object in the react-sdk
* Handles the creation/initialisation of client objects.
* This module provides a singleton instance of this class so the 'current'
* Matrix Client object is available easily.
*/
class MatrixClientPeg {
constructor() {
this.matrixClient = null;
}
get(): MatrixClient {
return this.matrixClient;
}
unset() {
this.matrixClient = null;
}
/**
* Replace this MatrixClientPeg's client with a client instance that has
* Home Server / Identity Server URLs but no credentials
*/
replaceUsingUrls(hs_url, is_url) {
this._replaceClient(hs_url, is_url);
}
/**
* Replace this MatrixClientPeg's client with a client instance that has
* Home Server / Identity Server URLs and active credentials
*/
replaceUsingAccessToken(hs_url, is_url, user_id, access_token, isGuest) {
this._replaceClient(hs_url, is_url, user_id, access_token, isGuest);
}
_replaceClient(hs_url, is_url, user_id, access_token, isGuest) {
if (localStorage) {
try {
localStorage.clear();
} catch (e) {
console.warn("Error clearing local storage", e);
}
}
this._createClient(hs_url, is_url, user_id, access_token, isGuest);
if (localStorage) {
try {
localStorage.setItem("mx_hs_url", hs_url);
localStorage.setItem("mx_is_url", is_url);
if (user_id !== undefined && access_token !== undefined) {
localStorage.setItem("mx_user_id", user_id);
localStorage.setItem("mx_access_token", access_token);
localStorage.setItem("mx_is_guest", JSON.stringify(isGuest));
console.log("Session persisted for %s", user_id);
}
} catch (e) {
console.warn("Error using local storage: can't persist session!", e);
}
} else {
console.warn("No local storage available: can't persist session!");
}
}
getCredentials() {
return [
this.matrixClient.baseUrl,
this.matrixClient.idBaseUrl,
this.matrixClient.credentials.userId,
this.matrixClient.getAccessToken(),
this.matrixClient.isGuest(),
];
}
tryRestore() {
if (localStorage) {
const hs_url = localStorage.getItem("mx_hs_url");
const is_url = localStorage.getItem("mx_is_url") || 'https://matrix.org';
const access_token = localStorage.getItem("mx_access_token");
const user_id = localStorage.getItem("mx_user_id");
let is_guest;
if (localStorage.getItem("mx_is_guest") !== null) {
is_guest = localStorage.getItem("mx_is_guest") === "true";
} else {
// legacy key name
is_guest = localStorage.getItem("matrix-is-guest") === "true";
}
if (access_token && user_id && hs_url) {
console.log("Restoring session for %s", user_id);
this._createClient(hs_url, is_url, user_id, access_token);
this.matrixClient.setGuest(is_guest);
} else {
console.log("Session not found.");
}
}
}
_createClient(hs_url, is_url, user_id, access_token, isGuest) {
var opts = { var opts = {
baseUrl: hs_url, baseUrl: hs_url,
idBaseUrl: is_url, idBaseUrl: is_url,
@ -49,94 +144,18 @@ function createClientForPeg(hs_url, is_url, user_id, access_token, guestAccess)
opts.deviceId = deviceId(); opts.deviceId = deviceId();
} }
matrixClient = Matrix.createClient(opts); this.matrixClient = Matrix.createClient(opts);
// we're going to add eventlisteners for each matrix event tile, so the // we're going to add eventlisteners for each matrix event tile, so the
// potential number of event listeners is quite high. // potential number of event listeners is quite high.
matrixClient.setMaxListeners(500); this.matrixClient.setMaxListeners(500);
if (guestAccess) { this.matrixClient.setGuest(Boolean(isGuest));
console.log("Guest: %s", guestAccess.isGuest());
matrixClient.setGuest(guestAccess.isGuest());
var peekedRoomId = guestAccess.getPeekedRoom();
if (peekedRoomId) {
console.log("Peeking in room %s", peekedRoomId);
matrixClient.peekInRoom(peekedRoomId);
}
} }
} }
if (localStorage) { if (!global.mxMatrixClientPeg) {
var hs_url = localStorage.getItem("mx_hs_url"); global.mxMatrixClientPeg = new MatrixClientPeg();
var is_url = localStorage.getItem("mx_is_url") || 'https://matrix.org'; global.mxMatrixClientPeg.tryRestore();
var access_token = localStorage.getItem("mx_access_token");
var user_id = localStorage.getItem("mx_user_id");
var guestAccess = new GuestAccess(localStorage);
if (access_token && user_id && hs_url) {
console.log("Restoring session for %s", user_id);
createClientForPeg(hs_url, is_url, user_id, access_token, guestAccess);
}
else {
console.log("Session not found.");
}
} }
module.exports = global.mxMatrixClientPeg;
class MatrixClient {
constructor(guestAccess) {
this.guestAccess = guestAccess;
}
get(): MatrixClient {
return matrixClient;
}
unset() {
matrixClient = null;
}
// FIXME, XXX: this all seems very convoluted :(
//
// Why do we have this peg wrapper rather than just MatrixClient.get()?
// Why do we name MatrixClient as MatrixClientPeg when we export it?
//
// -matthew
replaceUsingUrls(hs_url, is_url) {
this.replaceClient(hs_url, is_url);
}
replaceUsingAccessToken(hs_url, is_url, user_id, access_token, isGuest) {
this.replaceClient(hs_url, is_url, user_id, access_token, isGuest);
}
replaceClient(hs_url, is_url, user_id, access_token, isGuest) {
if (localStorage) {
try {
localStorage.clear();
} catch (e) {
console.warn("Error clearing local storage", e);
}
}
this.guestAccess.markAsGuest(Boolean(isGuest));
createClientForPeg(hs_url, is_url, user_id, access_token, this.guestAccess);
if (localStorage) {
try {
localStorage.setItem("mx_hs_url", hs_url);
localStorage.setItem("mx_is_url", is_url);
localStorage.setItem("mx_user_id", user_id);
localStorage.setItem("mx_access_token", access_token);
console.log("Session persisted for %s", user_id);
} catch (e) {
console.warn("Error using local storage: can't persist session!", e);
}
} else {
console.warn("No local storage available: can't persist session!");
}
}
}
if (!global.mxMatrixClient) {
global.mxMatrixClient = new MatrixClient(new GuestAccess(localStorage));
}
module.exports = global.mxMatrixClient;

View file

@ -341,7 +341,12 @@ class TabComplete {
} }
if (a.kind == 'member') { if (a.kind == 'member') {
return this.memberTabOrder[b.member.userId] - this.memberTabOrder[a.member.userId]; let orderA = this.memberTabOrder[a.member.userId];
let orderB = this.memberTabOrder[b.member.userId];
if (orderA === undefined) orderA = -1;
if (orderB === undefined) orderB = -1;
return orderB - orderA;
} }
// anything else we have no ordering for // anything else we have no ordering for

View file

@ -493,6 +493,17 @@ module.exports = React.createClass({
return; return;
} }
if (this.props.ConferenceHandler &&
member.userId === this.props.ConferenceHandler.getConferenceUserIdForRoom(member.roomId)) {
this._updateConfCallNotification();
}
this._updateRoomMembers();
},
// rate limited because a power level change will emit an event for every
// member in the room.
_updateRoomMembers: new rate_limited_func(function() {
// a member state changed in this room, refresh the tab complete list // a member state changed in this room, refresh the tab complete list
this.tabComplete.loadEntries(this.state.room); this.tabComplete.loadEntries(this.state.room);
this._updateAutoComplete(); this._updateAutoComplete();
@ -506,12 +517,7 @@ module.exports = React.createClass({
joining: false joining: false
}); });
} }
}, 500),
if (this.props.ConferenceHandler &&
member.userId === this.props.ConferenceHandler.getConferenceUserIdForRoom(member.roomId)) {
this._updateConfCallNotification();
}
},
_hasUnsentMessages: function(room) { _hasUnsentMessages: function(room) {
return this._getUnsentMessages(room).length > 0; return this._getUnsentMessages(room).length > 0;

View file

@ -406,14 +406,14 @@ module.exports = React.createClass({
this.props.onFinished(); this.props.onFinished();
} }
else { else {
self.setState({ updating: self.state.updating + 1 }); this.setState({ updating: this.state.updating + 1 });
createRoom({ createRoom({
createOpts: { createOpts: {
invite: [this.props.member.userId], invite: [this.props.member.userId],
}, },
}).finally(function() { }).finally(() => {
self.props.onFinished(); this.props.onFinished();
self.setState({ updating: self.state.updating - 1 }); this.setState({ updating: this.state.updating - 1 });
}).done(); }).done();
} }
}, },

View file

@ -14,6 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
/**
* 'debounces' a function to only execute every n milliseconds.
* Useful when react-sdk gets many, many events but only wants
* to update the interface once for all of them.
*
* Note that the function must not take arguments, since the args
* could be different for each invocarion of the function.
*/
module.exports = function(f, minIntervalMs) { module.exports = function(f, minIntervalMs) {
this.lastCall = 0; this.lastCall = 0;
this.scheduledCall = undefined; this.scheduledCall = undefined;