diff --git a/src/RoomAliasCache.js b/src/RoomAliasCache.js new file mode 100644 index 0000000000..bb511ba4d7 --- /dev/null +++ b/src/RoomAliasCache.js @@ -0,0 +1,35 @@ +/* +Copyright 2019 The Matrix.org Foundation C.I.C. + +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. +*/ + +/** + * This is meant to be a cache of room alias to room ID so that moving between + * rooms happens smoothly (for example using browser back / forward buttons). + * + * For the moment, it's in memory only and so only applies for the current + * session for simplicity, but could be extended further in the future. + * + * A similar thing could also be achieved via `pushState` with a state object, + * but keeping it separate like this seems easier in case we do want to extend. + */ +const aliasToIDMap = new Map(); + +export function storeRoomAliasInCache(alias, id) { + aliasToIDMap.set(alias, id); +} + +export function getCachedRoomIDForAlias(alias) { + return aliasToIDMap.get(alias); +} diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index da67416400..6cc86bf6d7 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -60,6 +60,7 @@ import AutoDiscoveryUtils from "../../utils/AutoDiscoveryUtils"; import DMRoomMap from '../../utils/DMRoomMap'; import { countRoomsWithNotif } from '../../RoomNotifs'; import { setTheme } from "../../theme"; +import { storeRoomAliasInCache } from '../../RoomAliasCache'; // Disable warnings for now: we use deprecated bluebird functions // and need to migrate, but they spam the console with warnings. @@ -866,7 +867,12 @@ export default createReactClass({ const room = MatrixClientPeg.get().getRoom(roomInfo.room_id); if (room) { const theAlias = Rooms.getDisplayAliasForRoom(room); - if (theAlias) presentedId = theAlias; + if (theAlias) { + presentedId = theAlias; + // Store display alias of the presented room in cache to speed future + // navigation. + storeRoomAliasInCache(theAlias, room.roomId); + } // Store this as the ID of the last room accessed. This is so that we can // persist which room is being stored across refreshes and browser quits. diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index 7e1b06c0bf..e860ed8b24 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -20,6 +20,7 @@ import MatrixClientPeg from '../MatrixClientPeg'; import sdk from '../index'; import Modal from '../Modal'; import { _t } from '../languageHandler'; +import { getCachedRoomIDForAlias, storeRoomAliasInCache } from '../RoomAliasCache'; const INITIAL_STATE = { // Whether we're joining the currently viewed room (see isJoining()) @@ -137,7 +138,7 @@ class RoomViewStore extends Store { } } - _viewRoom(payload) { + async _viewRoom(payload) { if (payload.room_id) { const newState = { roomId: payload.room_id, @@ -176,6 +177,22 @@ class RoomViewStore extends Store { this._joinRoom(payload); } } else if (payload.room_alias) { + // Try the room alias to room ID navigation cache first to avoid + // blocking room navigation on the homeserver. + const roomId = getCachedRoomIDForAlias(payload.room_alias); + if (roomId) { + dis.dispatch({ + action: 'view_room', + room_id: roomId, + event_id: payload.event_id, + highlighted: payload.highlighted, + room_alias: payload.room_alias, + auto_join: payload.auto_join, + oob_data: payload.oob_data, + }); + return; + } + // Room alias cache miss, so let's ask the homeserver. // Resolve the alias and then do a second dispatch with the room ID acquired this._setState({ roomId: null, @@ -186,8 +203,9 @@ class RoomViewStore extends Store { roomLoading: true, roomLoadError: null, }); - MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias).done( - (result) => { + try { + const result = await MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias); + storeRoomAliasInCache(payload.room_alias, result.room_id); dis.dispatch({ action: 'view_room', room_id: result.room_id, @@ -197,14 +215,14 @@ class RoomViewStore extends Store { auto_join: payload.auto_join, oob_data: payload.oob_data, }); - }, (err) => { + } catch (err) { dis.dispatch({ action: 'view_room_error', room_id: null, room_alias: payload.room_alias, - err: err, + err, }); - }); + } } }