diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d9a01e6684..988a85fd433 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +Changes in [1.1.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.1.1) (2019-05-14) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.1.0...v1.1.1) + + * Fix registration with email + [\#2970](https://github.com/matrix-org/matrix-react-sdk/pull/2970) + * Fix bug where email was not required where it shouldn't have been + [\#2969](https://github.com/matrix-org/matrix-react-sdk/pull/2969) + Changes in [1.1.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.1.0) (2019-05-07) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.1.0-rc.1...v1.1.0) diff --git a/package.json b/package.json index 991080cb7ee..bcbf6ea29f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "1.1.0", + "version": "1.1.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { diff --git a/res/css/views/messages/_MessageActionBar.scss b/res/css/views/messages/_MessageActionBar.scss index 419542036ed..e66c99e95b4 100644 --- a/res/css/views/messages/_MessageActionBar.scss +++ b/res/css/views/messages/_MessageActionBar.scss @@ -23,7 +23,7 @@ limitations under the License. line-height: 24px; border-radius: 4px; background: $message-action-bar-bg-color; - top: -13px; + top: -18px; right: 8px; user-select: none; diff --git a/src/Lifecycle.js b/src/Lifecycle.js index 527394da4db..0e2389fd1c1 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -126,6 +126,15 @@ export function getStoredSessionOwner() { return hsUrl && userId && accessToken ? userId : null; } +/** + * @returns {bool} True if the stored session is for a guest user or false if it is + * for a real user. If there is no stored session, return null. + */ +export function getStoredSessionIsGuest() { + const sessVars = _getLocalStorageSessionVars(); + return sessVars.hsUrl && sessVars.userId && sessVars.accessToken ? sessVars.isGuest : null; +} + /** * @param {Object} queryParams string->string map of the * query-parameters extracted from the real query-string of the starting @@ -235,7 +244,15 @@ function _getLocalStorageSessionVars() { const userId = localStorage.getItem("mx_user_id"); const deviceId = localStorage.getItem("mx_device_id"); - return {hsUrl, isUrl, accessToken, userId, deviceId}; + let isGuest; + if (localStorage.getItem("mx_is_guest") !== null) { + isGuest = localStorage.getItem("mx_is_guest") === "true"; + } else { + // legacy key name + isGuest = localStorage.getItem("matrix-is-guest") === "true"; + } + + return {hsUrl, isUrl, accessToken, userId, deviceId, isGuest}; } // returns a promise which resolves to true if a session is found in @@ -253,15 +270,7 @@ async function _restoreFromLocalStorage() { return false; } - const {hsUrl, isUrl, accessToken, userId, deviceId} = _getLocalStorageSessionVars(); - - let isGuest; - if (localStorage.getItem("mx_is_guest") !== null) { - isGuest = localStorage.getItem("mx_is_guest") === "true"; - } else { - // legacy key name - isGuest = localStorage.getItem("matrix-is-guest") === "true"; - } + const {hsUrl, isUrl, accessToken, userId, deviceId, isGuest} = _getLocalStorageSessionVars(); if (accessToken && userId && hsUrl) { console.log(`Restoring session for ${userId}`); diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 545f8477182..4198980a17d 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1642,14 +1642,15 @@ export default React.createClass({ // returns a promise which resolves to the new MatrixClient onRegistered: function(credentials) { - // XXX: This should be in state or ideally store(s) because we risk not - // rendering the most up-to-date view of state otherwise. - this._is_registered = true; if (this.state.register_session_id) { // The user came in through an email validation link. To avoid overwriting - // their session, check to make sure the session isn't someone else. + // their session, check to make sure the session isn't someone else, and + // isn't a guest user since we'll usually have set a guest user session before + // starting the registration process. This isn't perfect since it's possible + // the user had a separate guest session they didn't actually mean to replace. const sessionOwner = Lifecycle.getStoredSessionOwner(); - if (sessionOwner && sessionOwner !== credentials.userId) { + const sessionIsGuest = Lifecycle.getStoredSessionIsGuest(); + if (sessionOwner && !sessionIsGuest && sessionOwner !== credentials.userId) { console.log( `Found a session for ${sessionOwner} but ${credentials.userId} is trying to verify their ` + `email address. Restoring the session for ${sessionOwner} with warning.`, @@ -1680,6 +1681,9 @@ export default React.createClass({ return MatrixClientPeg.get(); } } + // XXX: This should be in state or ideally store(s) because we risk not + // rendering the most up-to-date view of state otherwise. + this._is_registered = true; return Lifecycle.setLoggedIn(credentials); }, diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js index 9fd42fb31d7..2f120221401 100644 --- a/src/components/views/messages/MImageBody.js +++ b/src/components/views/messages/MImageBody.js @@ -197,12 +197,18 @@ export default class MImageBody extends React.Component { // synapse only supports 800x600 thumbnails for now though, // so we'll need to download the original image for this to work // well for now. First, let's try a few cases that let us avoid - // downloading the original: - if (pixelRatio === 1.0 || - (!content.info || !content.info.w || - !content.info.h || !content.info.size)) { - // always thumbnail. it may look a bit worse, but it'll save bandwidth. - // which is probably desirable on a lo-dpi device anyway. + // downloading the original, including: + // - When displaying a GIF, we always want to thumbnail so that we can + // properly respect the user's GIF autoplay setting (which relies on + // thumbnailing to produce the static preview image) + // - On a low DPI device, always thumbnail to save bandwidth + // - If there's no sizing info in the event, default to thumbnail + const info = content.info; + if ( + this._isGif() || + pixelRatio === 1.0 || + (!info || !info.w || !info.h || !info.size) + ) { return this.context.matrixClient.mxcUrlToHttp(content.url, thumbWidth, thumbHeight); } else { // we should only request thumbnails if the image is bigger than 800x600 @@ -215,10 +221,10 @@ export default class MImageBody extends React.Component { // timeline (e.g. >1MB). const isLargerThanThumbnail = ( - content.info.w > thumbWidth || - content.info.h > thumbHeight + info.w > thumbWidth || + info.h > thumbHeight ); - const isLargeFileSize = content.info.size > 1*1024*1024; + const isLargeFileSize = info.size > 1*1024*1024; if (isLargeFileSize && isLargerThanThumbnail) { // image is too large physically and bytewise to clutter our timeline so diff --git a/src/components/views/messages/RoomCreate.js b/src/components/views/messages/RoomCreate.js index f9dc3df2dca..95254323fab 100644 --- a/src/components/views/messages/RoomCreate.js +++ b/src/components/views/messages/RoomCreate.js @@ -49,7 +49,7 @@ module.exports = React.createClass({ return
; // We should never have been instaniated in this case } const prevRoom = MatrixClientPeg.get().getRoom(predecessor['room_id']); - const permalinkCreator = new RoomPermalinkCreator(prevRoom); + const permalinkCreator = new RoomPermalinkCreator(prevRoom, predecessor['room_id']); permalinkCreator.load(); const predecessorPermalink = permalinkCreator.forEvent(predecessor['event_id']); return
diff --git a/src/matrix-to.js b/src/matrix-to.js index a198bb422ee..14467cb4c5e 100644 --- a/src/matrix-to.js +++ b/src/matrix-to.js @@ -70,8 +70,12 @@ const MAX_SERVER_CANDIDATES = 3; // the list and magically have the link work. export class RoomPermalinkCreator { - constructor(room) { + // We support being given a roomId as a fallback in the event the `room` object + // doesn't exist or is not healthy for us to rely on. For example, loading a + // permalink to a room which the MatrixClient doesn't know about. + constructor(room, roomId=null) { this._room = room; + this._roomId = room ? room.roomId : roomId; this._highestPlUserId = null; this._populationMap = null; this._bannedHostsRegexps = null; @@ -79,6 +83,10 @@ export class RoomPermalinkCreator { this._serverCandidates = null; this._started = false; + if (!this._roomId) { + throw new Error("Failed to resolve a roomId for the permalink creator to use"); + } + this.onMembership = this.onMembership.bind(this); this.onRoomState = this.onRoomState.bind(this); } @@ -116,13 +124,13 @@ export class RoomPermalinkCreator { } forEvent(eventId) { - const roomId = this._room.roomId; + const roomId = this._roomId; const permalinkBase = `${baseUrl}/#/${roomId}/${eventId}`; return `${permalinkBase}${encodeServerCandidates(this._serverCandidates)}`; } forRoom() { - const roomId = this._room.roomId; + const roomId = this._roomId; const permalinkBase = `${baseUrl}/#/${roomId}`; return `${permalinkBase}${encodeServerCandidates(this._serverCandidates)}`; } @@ -246,7 +254,6 @@ export class RoomPermalinkCreator { } } - export function makeUserPermalink(userId) { return `${baseUrl}/#/${userId}`; } diff --git a/test/matrix-to-test.js b/test/matrix-to-test.js index 45b5f74c5e3..33947703ef0 100644 --- a/test/matrix-to-test.js +++ b/test/matrix-to-test.js @@ -74,7 +74,7 @@ describe('matrix-to', function() { }); it('should pick no candidate servers when the room has no members', function() { - const room = mockRoom(null, []); + const room = mockRoom("!fake:example.org", []); const creator = new RoomPermalinkCreator(room); creator.load(); expect(creator._serverCandidates).toBeTruthy(); @@ -82,7 +82,7 @@ describe('matrix-to', function() { }); it('should pick a candidate server for the highest power level user in the room', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:pl_50", powerLevel: 50, @@ -109,7 +109,7 @@ describe('matrix-to', function() { userId: "@alice:pl_95", powerLevel: 95, }; - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:pl_50", powerLevel: 50, @@ -132,7 +132,7 @@ describe('matrix-to', function() { }); it('should pick candidate servers based on user population', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:first", powerLevel: 0, @@ -168,7 +168,7 @@ describe('matrix-to', function() { }); it('should pick prefer candidate servers with higher power levels', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:first", powerLevel: 100, @@ -195,7 +195,7 @@ describe('matrix-to', function() { }); it('should pick a maximum of 3 candidate servers', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:alpha", powerLevel: 100, @@ -224,7 +224,7 @@ describe('matrix-to', function() { }); it('should not consider IPv4 hosts', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:127.0.0.1", powerLevel: 100, @@ -237,7 +237,7 @@ describe('matrix-to', function() { }); it('should not consider IPv6 hosts', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:[::1]", powerLevel: 100, @@ -250,7 +250,7 @@ describe('matrix-to', function() { }); it('should not consider IPv4 hostnames with ports', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:127.0.0.1:8448", powerLevel: 100, @@ -263,7 +263,7 @@ describe('matrix-to', function() { }); it('should not consider IPv6 hostnames with ports', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:[::1]:8448", powerLevel: 100, @@ -276,7 +276,7 @@ describe('matrix-to', function() { }); it('should work with hostnames with ports', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:example.org:8448", powerLevel: 100, @@ -291,7 +291,7 @@ describe('matrix-to', function() { }); it('should not consider servers explicitly denied by ACLs', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:evilcorp.com", powerLevel: 100, @@ -311,7 +311,7 @@ describe('matrix-to', function() { }); it('should not consider servers not allowed by ACLs', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:evilcorp.com", powerLevel: 100, @@ -331,7 +331,7 @@ describe('matrix-to', function() { }); it('should consider servers not explicitly banned by ACLs', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:evilcorp.com", powerLevel: 100, @@ -352,7 +352,7 @@ describe('matrix-to', function() { }); it('should consider servers not disallowed by ACLs', function() { - const room = mockRoom(null, [ + const room = mockRoom("!fake:example.org", [ { userId: "@alice:evilcorp.com", powerLevel: 100,