From 8cacf1ff9743fd807b8169c8aa8c09a3c9da4b2e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 21 Jul 2020 10:14:12 +0100 Subject: [PATCH 1/7] Convert RoomViewStore and ActiveRoomObserver to typescript Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/@types/global.d.ts | 3 + ...eRoomObserver.js => ActiveRoomObserver.ts} | 52 ++++---- .../{RoomViewStore.js => RoomViewStore.tsx} | 122 ++++++++++-------- 3 files changed, 95 insertions(+), 82 deletions(-) rename src/{ActiveRoomObserver.js => ActiveRoomObserver.ts} (54%) rename src/stores/{RoomViewStore.js => RoomViewStore.tsx} (83%) diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index f556ff8b5c..4ab9e5c8b3 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -24,6 +24,7 @@ import { RoomListStoreClass } from "../stores/room-list/RoomListStore"; import { PlatformPeg } from "../PlatformPeg"; import RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore"; import {IntegrationManagers} from "../integrations/IntegrationManagers"; +import {ActiveRoomObserver} from "../ActiveRoomObserver"; declare global { interface Window { @@ -39,6 +40,8 @@ declare global { mx_RebrandListener: RebrandListener; mx_RoomListStore: RoomListStoreClass; mx_RoomListLayoutStore: RoomListLayoutStore; + mx_ActiveRoomObserver: ActiveRoomObserver; + mxPlatformPeg: PlatformPeg; mxIntegrationManagers: typeof IntegrationManagers; } diff --git a/src/ActiveRoomObserver.js b/src/ActiveRoomObserver.ts similarity index 54% rename from src/ActiveRoomObserver.js rename to src/ActiveRoomObserver.ts index b7695d401d..4ff4951915 100644 --- a/src/ActiveRoomObserver.js +++ b/src/ActiveRoomObserver.ts @@ -16,6 +16,8 @@ limitations under the License. import RoomViewStore from './stores/RoomViewStore'; +type Listener = (isActive: boolean) => void; + /** * Consumes changes from the RoomViewStore and notifies specific things * about when the active room changes. Unlike listening for RoomViewStore @@ -25,57 +27,57 @@ import RoomViewStore from './stores/RoomViewStore'; * TODO: If we introduce an observer for something else, factor out * the adding / removing of listeners & emitting into a common class. */ -class ActiveRoomObserver { - constructor() { - this._listeners = {}; // key=roomId, value=function(isActive:boolean) +export class ActiveRoomObserver { + private listeners: {[key: string]: Listener[]} = {}; + private _activeRoomId = RoomViewStore.getRoomId(); // TODO + private readonly roomStoreToken: string; - this._activeRoomId = RoomViewStore.getRoomId(); - // TODO: We could self-destruct when the last listener goes away, or at least - // stop listening. - this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate.bind(this)); + constructor() { + // TODO: We could self-destruct when the last listener goes away, or at least stop listening. + this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); } - get activeRoomId(): string { + public get activeRoomId(): string { return this._activeRoomId; } - addListener(roomId, listener) { - if (!this._listeners[roomId]) this._listeners[roomId] = []; - this._listeners[roomId].push(listener); + public addListener(roomId, listener) { + if (!this.listeners[roomId]) this.listeners[roomId] = []; + this.listeners[roomId].push(listener); } - removeListener(roomId, listener) { - if (this._listeners[roomId]) { - const i = this._listeners[roomId].indexOf(listener); + public removeListener(roomId, listener) { + if (this.listeners[roomId]) { + const i = this.listeners[roomId].indexOf(listener); if (i > -1) { - this._listeners[roomId].splice(i, 1); + this.listeners[roomId].splice(i, 1); } } else { console.warn("Unregistering unrecognised listener (roomId=" + roomId + ")"); } } - _emit(roomId, isActive: boolean) { - if (!this._listeners[roomId]) return; + private emit(roomId, isActive: boolean) { + if (!this.listeners[roomId]) return; - for (const l of this._listeners[roomId]) { + for (const l of this.listeners[roomId]) { l.call(null, isActive); } } - _onRoomViewStoreUpdate() { + private onRoomViewStoreUpdate = () => { // emit for the old room ID - if (this._activeRoomId) this._emit(this._activeRoomId, false); + if (this._activeRoomId) this.emit(this._activeRoomId, false); // update our cache this._activeRoomId = RoomViewStore.getRoomId(); // and emit for the new one - if (this._activeRoomId) this._emit(this._activeRoomId, true); - } + if (this._activeRoomId) this.emit(this._activeRoomId, true); + }; } -if (global.mx_ActiveRoomObserver === undefined) { - global.mx_ActiveRoomObserver = new ActiveRoomObserver(); +if (window.mx_ActiveRoomObserver === undefined) { + window.mx_ActiveRoomObserver = new ActiveRoomObserver(); } -export default global.mx_ActiveRoomObserver; +export default window.mx_ActiveRoomObserver; diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.tsx similarity index 83% rename from src/stores/RoomViewStore.js rename to src/stores/RoomViewStore.tsx index 6e5007895c..e634433933 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.tsx @@ -15,13 +15,17 @@ 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. */ -import dis from '../dispatcher/dispatcher'; + +import React from "react"; import {Store} from 'flux/utils'; + +import dis from '../dispatcher/dispatcher'; import {MatrixClientPeg} from '../MatrixClientPeg'; import * as sdk from '../index'; import Modal from '../Modal'; import { _t } from '../languageHandler'; import { getCachedRoomIDForAlias, storeRoomAliasInCache } from '../RoomAliasCache'; +import {ActionPayload} from "../dispatcher/payloads"; const INITIAL_STATE = { // Whether we're joining the currently viewed room (see isJoining()) @@ -33,6 +37,7 @@ const INITIAL_STATE = { // The event to scroll to when the room is first viewed initialEventId: null, + initialEventPixelOffset: null, // Whether to highlight the initial event isInitialEventHighlighted: false, @@ -46,6 +51,10 @@ const INITIAL_STATE = { forwardingEvent: null, quotingEvent: null, + + replyingToEvent: null, + + shouldPeek: false, }; /** @@ -53,21 +62,20 @@ const INITIAL_STATE = { * with a subset of the js-sdk. * ``` */ -class RoomViewStore extends Store { +class RoomViewStore extends Store { + private state = INITIAL_STATE; // initialize state + constructor() { super(dis); - - // Initialise state - this._state = INITIAL_STATE; } - _setState(newState) { + setState(newState: Partial) { // If values haven't changed, there's nothing to do. // This only tries a shallow comparison, so unchanged objects will slip // through, but that's probably okay for now. let stateChanged = false; for (const key of Object.keys(newState)) { - if (this._state[key] !== newState[key]) { + if (this.state[key] !== newState[key]) { stateChanged = true; break; } @@ -76,7 +84,7 @@ class RoomViewStore extends Store { return; } - this._state = Object.assign(this._state, newState); + this.state = Object.assign(this.state, newState); this.__emitChange(); } @@ -89,59 +97,59 @@ class RoomViewStore extends Store { // - event_offset: 100 // - highlighted: true case 'view_room': - this._viewRoom(payload); + this.viewRoom(payload); break; case 'view_my_groups': case 'view_group': - this._setState({ + this.setState({ roomId: null, roomAlias: null, }); break; case 'view_room_error': - this._viewRoomError(payload); + this.viewRoomError(payload); break; case 'will_join': - this._setState({ + this.setState({ joining: true, }); break; case 'cancel_join': - this._setState({ + this.setState({ joining: false, }); break; // join_room: // - opts: options for joinRoom case 'join_room': - this._joinRoom(payload); + this.joinRoom(payload); break; case 'join_room_error': - this._joinRoomError(payload); + this.joinRoomError(payload); break; case 'join_room_ready': - this._setState({ shouldPeek: false }); + this.setState({ shouldPeek: false }); break; case 'on_client_not_viable': case 'on_logged_out': this.reset(); break; case 'forward_event': - this._setState({ + this.setState({ forwardingEvent: payload.event, }); break; case 'reply_to_event': // If currently viewed room does not match the room in which we wish to reply then change rooms // this can happen when performing a search across all rooms - if (payload.event && payload.event.getRoomId() !== this._state.roomId) { + if (payload.event && payload.event.getRoomId() !== this.state.roomId) { dis.dispatch({ action: 'view_room', room_id: payload.event.getRoomId(), replyingToEvent: payload.event, }); } else { - this._setState({ + this.setState({ replyingToEvent: payload.event, }); } @@ -149,14 +157,14 @@ class RoomViewStore extends Store { case 'open_room_settings': { const RoomSettingsDialog = sdk.getComponent("dialogs.RoomSettingsDialog"); Modal.createTrackedDialog('Room settings', '', RoomSettingsDialog, { - roomId: payload.room_id || this._state.roomId, + roomId: payload.room_id || this.state.roomId, }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); break; } } } - async _viewRoom(payload) { + private async viewRoom(payload) { if (payload.room_id) { const newState = { roomId: payload.room_id, @@ -181,18 +189,18 @@ class RoomViewStore extends Store { newState.replyingToEvent = payload.replyingToEvent; } - if (this._state.forwardingEvent) { + if (this.state.forwardingEvent) { dis.dispatch({ action: 'send_event', room_id: newState.roomId, - event: this._state.forwardingEvent, + event: this.state.forwardingEvent, }); } - this._setState(newState); + this.setState(newState); if (payload.auto_join) { - this._joinRoom(payload); + this.joinRoom(payload); } } else if (payload.room_alias) { // Try the room alias to room ID navigation cache first to avoid @@ -201,7 +209,7 @@ class RoomViewStore extends Store { if (!roomId) { // 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({ + this.setState({ roomId: null, initialEventId: null, initialEventPixelOffset: null, @@ -238,8 +246,8 @@ class RoomViewStore extends Store { } } - _viewRoomError(payload) { - this._setState({ + private viewRoomError(payload) { + this.setState({ roomId: payload.room_id, roomAlias: payload.room_alias, roomLoading: false, @@ -247,12 +255,12 @@ class RoomViewStore extends Store { }); } - _joinRoom(payload) { - this._setState({ + private joinRoom(payload) { + this.setState({ joining: true, }); MatrixClientPeg.get().joinRoom( - this._state.roomAlias || this._state.roomId, payload.opts, + this.state.roomAlias || this.state.roomId, payload.opts, ).then(() => { // We do *not* clear the 'joining' flag because the Room object and/or our 'joined' member event may not // have come down the sync stream yet, and that's the point at which we'd consider the user joined to the @@ -282,45 +290,45 @@ class RoomViewStore extends Store { }); } - _joinRoomError(payload) { - this._setState({ + private joinRoomError(payload) { + this.setState({ joining: false, joinError: payload.err, }); } - reset() { - this._state = Object.assign({}, INITIAL_STATE); + public reset() { + this.state = Object.assign({}, INITIAL_STATE); } // The room ID of the room currently being viewed - getRoomId() { - return this._state.roomId; + public getRoomId() { + return this.state.roomId; } // The event to scroll to when the room is first viewed - getInitialEventId() { - return this._state.initialEventId; + public getInitialEventId() { + return this.state.initialEventId; } // Whether to highlight the initial event - isInitialEventHighlighted() { - return this._state.isInitialEventHighlighted; + public isInitialEventHighlighted() { + return this.state.isInitialEventHighlighted; } // The room alias of the room (or null if not originally specified in view_room) - getRoomAlias() { - return this._state.roomAlias; + public getRoomAlias() { + return this.state.roomAlias; } // Whether the current room is loading (true whilst resolving an alias) - isRoomLoading() { - return this._state.roomLoading; + public isRoomLoading() { + return this.state.roomLoading; } // Any error that has occurred during loading - getRoomLoadError() { - return this._state.roomLoadError; + public getRoomLoadError() { + return this.state.roomLoadError; } // True if we're expecting the user to be joined to the room currently being @@ -346,27 +354,27 @@ class RoomViewStore extends Store { // // show join prompt // } // } - isJoining() { - return this._state.joining; + public isJoining() { + return this.state.joining; } // Any error that has occurred during joining - getJoinError() { - return this._state.joinError; + public getJoinError() { + return this.state.joinError; } // The mxEvent if one is about to be forwarded - getForwardingEvent() { - return this._state.forwardingEvent; + public getForwardingEvent() { + return this.state.forwardingEvent; } // The mxEvent if one is currently being replied to/quoted - getQuotingEvent() { - return this._state.replyingToEvent; + public getQuotingEvent() { + return this.state.replyingToEvent; } - shouldPeek() { - return this._state.shouldPeek; + public shouldPeek() { + return this.state.shouldPeek; } } From 9aff56afcc958cfc7f14052617fe33ec3cd89845 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 21 Jul 2020 10:15:05 +0100 Subject: [PATCH 2/7] add more types Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/stores/RoomViewStore.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index e634433933..cb4ed39a1d 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -164,7 +164,7 @@ class RoomViewStore extends Store { } } - private async viewRoom(payload) { + private async viewRoom(payload: ActionPayload) { if (payload.room_id) { const newState = { roomId: payload.room_id, @@ -246,7 +246,7 @@ class RoomViewStore extends Store { } } - private viewRoomError(payload) { + private viewRoomError(payload: ActionPayload) { this.setState({ roomId: payload.room_id, roomAlias: payload.room_alias, @@ -255,7 +255,7 @@ class RoomViewStore extends Store { }); } - private joinRoom(payload) { + private joinRoom(payload: ActionPayload) { this.setState({ joining: true, }); @@ -290,7 +290,7 @@ class RoomViewStore extends Store { }); } - private joinRoomError(payload) { + private joinRoomError(payload: ActionPayload) { this.setState({ joining: false, joinError: payload.err, From 0db66313e2435d5ced590cef2a1f9ee70094861e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 21 Jul 2020 10:20:30 +0100 Subject: [PATCH 3/7] Add more causes to blank out active room Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/stores/RoomViewStore.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index cb4ed39a1d..ea1f3e04c9 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -99,6 +99,9 @@ class RoomViewStore extends Store { case 'view_room': this.viewRoom(payload); break; + case 'view_create_group': + case 'view_welcome_page': + case 'view_home_page': case 'view_my_groups': case 'view_group': this.setState({ From a69560d0de78c71ebac66c000c54a5587a13936f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 21 Jul 2020 10:22:03 +0100 Subject: [PATCH 4/7] add comment Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/stores/RoomViewStore.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index ea1f3e04c9..6a6468d5d0 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -99,6 +99,7 @@ class RoomViewStore extends Store { case 'view_room': this.viewRoom(payload); break; + // for these events blank out the roomId as we are no longer in the RoomView case 'view_create_group': case 'view_welcome_page': case 'view_home_page': From 6f34c365370b38014bf55f0b9d3ee531f4c1df75 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 21 Jul 2020 17:56:50 +0100 Subject: [PATCH 5/7] tidy up Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/@types/global.d.ts | 2 +- src/ActiveRoomObserver.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index e719da92c2..5d72061be5 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -41,7 +41,7 @@ declare global { mxRebrandListener: RebrandListener; mxRoomListStore: RoomListStoreClass; mxRoomListLayoutStore: RoomListLayoutStore; - mx_ActiveRoomObserver: ActiveRoomObserver; + mxActiveRoomObserver: ActiveRoomObserver; mxPlatformPeg: PlatformPeg; mxIntegrationManagers: typeof IntegrationManagers; singletonModalManager: ModalManager; diff --git a/src/ActiveRoomObserver.ts b/src/ActiveRoomObserver.ts index 4ff4951915..cc3f29dc42 100644 --- a/src/ActiveRoomObserver.ts +++ b/src/ActiveRoomObserver.ts @@ -77,7 +77,7 @@ export class ActiveRoomObserver { }; } -if (window.mx_ActiveRoomObserver === undefined) { - window.mx_ActiveRoomObserver = new ActiveRoomObserver(); +if (window.mxActiveRoomObserver === undefined) { + window.mxActiveRoomObserver = new ActiveRoomObserver(); } -export default window.mx_ActiveRoomObserver; +export default window.mxActiveRoomObserver; From 7faf94cd8dd8c12a2d8798e8a9246e10d0e070e3 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 21 Jul 2020 17:57:08 +0100 Subject: [PATCH 6/7] remove stale comment Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/ActiveRoomObserver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ActiveRoomObserver.ts b/src/ActiveRoomObserver.ts index cc3f29dc42..1126dc9496 100644 --- a/src/ActiveRoomObserver.ts +++ b/src/ActiveRoomObserver.ts @@ -29,7 +29,7 @@ type Listener = (isActive: boolean) => void; */ export class ActiveRoomObserver { private listeners: {[key: string]: Listener[]} = {}; - private _activeRoomId = RoomViewStore.getRoomId(); // TODO + private _activeRoomId = RoomViewStore.getRoomId(); private readonly roomStoreToken: string; constructor() { From 9ce96bc28db8a5f078c7808c08d970c46d683248 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 4 Aug 2020 21:35:42 +0100 Subject: [PATCH 7/7] delint --- src/stores/RoomViewStore.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index bfcbaf9029..a0f0fb8f68 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -285,7 +285,7 @@ class RoomViewStore extends Store { {_t("Please contact your homeserver administrator.")} ; } else if (err.httpStatus === 404) { - const invitingUserId = this.getInvitingUserId(this._state.roomId); + const invitingUserId = this.getInvitingUserId(this.state.roomId); // only provide a better error message for invites if (invitingUserId) { // if the inviting user is on the same HS, there can only be one cause: they left.