From 1479690ac45ad4e8fe188235908d410f0693838c Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 28 Aug 2020 10:45:20 +0100 Subject: [PATCH 1/9] RightPanel use room instead of roomId --- src/components/structures/RightPanel.js | 20 ++++++++++---------- src/components/structures/RoomView.js | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index a4e3254e4c..beba09d359 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -34,7 +34,7 @@ import {Action} from "../../dispatcher/actions"; export default class RightPanel extends React.Component { static get propTypes() { return { - roomId: PropTypes.string, // if showing panels for a given room, this is set + room: PropTypes.string, // if showing panels for a given room, this is set groupId: PropTypes.string, // if showing panels for a given group, this is set user: PropTypes.object, // used if we know the user ahead of opening the panel }; @@ -161,13 +161,13 @@ export default class RightPanel extends React.Component { } onRoomStateMember(ev, state, member) { - if (member.roomId !== this.props.roomId) { + if (member.roomId !== this.props.room.roomId) { return; } // redraw the badge on the membership list - if (this.state.phase === RightPanelPhases.RoomMemberList && member.roomId === this.props.roomId) { + if (this.state.phase === RightPanelPhases.RoomMemberList && member.roomId === this.props.room.roomId) { this._delayedUpdate(); - } else if (this.state.phase === RightPanelPhases.RoomMemberInfo && member.roomId === this.props.roomId && + } else if (this.state.phase === RightPanelPhases.RoomMemberInfo && member.roomId === this.props.room.roomId && member.userId === this.state.member.userId) { // refresh the member info (e.g. new power level) this._delayedUpdate(); @@ -226,8 +226,8 @@ export default class RightPanel extends React.Component { switch (this.state.phase) { case RightPanelPhases.RoomMemberList: - if (this.props.roomId) { - panel = ; + if (this.props.room.roomId) { + panel = ; } break; case RightPanelPhases.GroupMemberList: @@ -242,8 +242,8 @@ export default class RightPanel extends React.Component { case RightPanelPhases.EncryptionPanel: panel = ; break; case RightPanelPhases.Room3pidMemberInfo: - panel = ; + panel = ; break; case RightPanelPhases.GroupMemberInfo: panel = ; break; case RightPanelPhases.FilePanel: - panel = ; + panel = ; break; } diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index a79e5b0aa8..f576de8dae 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -2064,7 +2064,7 @@ export default createReactClass({ const showRightPanel = !forceHideRightPanel && this.state.room && this.state.showRightPanel; const rightPanel = showRightPanel - ? + ? : null; const timelineClasses = classNames("mx_RoomView_timeline", { From 8b4250c1429478c40666a0eb55db6073d82a1e51 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 28 Aug 2020 10:46:29 +0100 Subject: [PATCH 2/9] expose RightPanelStore in window --- src/@types/global.d.ts | 2 ++ src/stores/RightPanelStore.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 84340d8219..1a361e7b55 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -28,6 +28,7 @@ import SettingsStore from "../settings/SettingsStore"; import {ActiveRoomObserver} from "../ActiveRoomObserver"; import {Notifier} from "../Notifier"; import type {Renderer} from "react-dom"; +import RightPanelStore from "../stores/RightPanelStore"; declare global { interface Window { @@ -49,6 +50,7 @@ declare global { singletonModalManager: ModalManager; mxSettingsStore: SettingsStore; mxNotifier: typeof Notifier; + mxRightPanelStore: RightPanelStore; } interface Document { diff --git a/src/stores/RightPanelStore.ts b/src/stores/RightPanelStore.ts index c1799978ad..34445d007b 100644 --- a/src/stores/RightPanelStore.ts +++ b/src/stores/RightPanelStore.ts @@ -223,3 +223,5 @@ export default class RightPanelStore extends Store { return RightPanelStore.instance; } } + +window.mxRightPanelStore = RightPanelStore.getSharedInstance(); From c7e40d0751f7594891d9ef91eb95b59f1eb87d8a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 3 Sep 2020 15:00:14 +0100 Subject: [PATCH 3/9] Fix MemberAvatar props interface --- src/components/views/avatars/MemberAvatar.tsx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/views/avatars/MemberAvatar.tsx b/src/components/views/avatars/MemberAvatar.tsx index 1d23d85b0f..8fd51d3715 100644 --- a/src/components/views/avatars/MemberAvatar.tsx +++ b/src/components/views/avatars/MemberAvatar.tsx @@ -16,23 +16,24 @@ limitations under the License. */ import React from 'react'; +import {RoomMember} from "matrix-js-sdk/src/models/room-member"; + import dis from "../../../dispatcher/dispatcher"; import {Action} from "../../../dispatcher/actions"; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import BaseAvatar from "./BaseAvatar"; interface IProps { - // TODO: replace with correct type - member: any; - fallbackUserId: string; + member: RoomMember; + fallbackUserId?: string; width: number; height: number; - resizeMethod: string; + resizeMethod?: string; // The onClick to give the avatar - onClick: React.MouseEventHandler; + onClick?: React.MouseEventHandler; // Whether the onClick of the avatar should be overriden to dispatch `Action.ViewUser` - viewUserOnClick: boolean; - title: string; + viewUserOnClick?: boolean; + title?: string; } interface IState { From ad9be61477b72bef1a3db5e8a26bec88b92aa3a6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 3 Sep 2020 15:01:32 +0100 Subject: [PATCH 4/9] Move HeaderButtons to an abstract class --- src/components/views/right_panel/GroupHeaderButtons.tsx | 2 -- src/components/views/right_panel/HeaderButtons.tsx | 4 +--- src/components/views/right_panel/RoomHeaderButtons.tsx | 4 ---- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/components/views/right_panel/GroupHeaderButtons.tsx b/src/components/views/right_panel/GroupHeaderButtons.tsx index 44237e401f..c468658eb6 100644 --- a/src/components/views/right_panel/GroupHeaderButtons.tsx +++ b/src/components/views/right_panel/GroupHeaderButtons.tsx @@ -46,8 +46,6 @@ export default class GroupHeaderButtons extends HeaderButtons { } protected onAction(payload: ActionPayload) { - super.onAction(payload); - if (payload.action === Action.ViewUser) { if ((payload as ViewUserPayload).member) { this.setPhase(RightPanelPhases.RoomMemberInfo, {member: payload.member}); diff --git a/src/components/views/right_panel/HeaderButtons.tsx b/src/components/views/right_panel/HeaderButtons.tsx index bbb783ccb9..e922959bbb 100644 --- a/src/components/views/right_panel/HeaderButtons.tsx +++ b/src/components/views/right_panel/HeaderButtons.tsx @@ -65,9 +65,7 @@ export default abstract class HeaderButtons extends React.Component) { dis.dispatch({ diff --git a/src/components/views/right_panel/RoomHeaderButtons.tsx b/src/components/views/right_panel/RoomHeaderButtons.tsx index 7ac547f499..671d9b0068 100644 --- a/src/components/views/right_panel/RoomHeaderButtons.tsx +++ b/src/components/views/right_panel/RoomHeaderButtons.tsx @@ -36,13 +36,9 @@ const MEMBER_PHASES = [ export default class RoomHeaderButtons extends HeaderButtons { constructor(props) { super(props, HeaderKind.Room); - this.onMembersClicked = this.onMembersClicked.bind(this); - this.onFilesClicked = this.onFilesClicked.bind(this); - this.onNotificationsClicked = this.onNotificationsClicked.bind(this); } protected onAction(payload: ActionPayload) { - super.onAction(payload); if (payload.action === Action.ViewUser) { if (payload.member) { this.setPhase(RightPanelPhases.RoomMemberInfo, {member: payload.member}); From 6d4de4d22b4dc0d8e18c1bae452ed89e690b5ad5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 3 Sep 2020 11:48:29 +0100 Subject: [PATCH 5/9] tidy up ScrollPanel comments --- src/components/structures/ScrollPanel.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 51113f4f56..4ff101c0e9 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -97,7 +97,7 @@ export default createReactClass({ /* startAtBottom: if set to true, the view is assumed to start * scrolled to the bottom. - * XXX: It's likley this is unecessary and can be derived from + * XXX: It's likely this is unnecessary and can be derived from * stickyBottom, but I'm adding an extra parameter to ensure * behaviour stays the same for other uses of ScrollPanel. * If so, let's remove this parameter down the line. @@ -141,6 +141,7 @@ export default createReactClass({ /* style: styles to add to the top-level div */ style: PropTypes.object, + /* resizeNotifier: ResizeNotifier to know when middle column has changed size */ resizeNotifier: PropTypes.object, From 3a8499259e248179b8b3a5f10968942583fc31fc Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 28 Aug 2020 10:47:30 +0100 Subject: [PATCH 6/9] factor out the useIsEncrypted hook --- src/hooks/useIsEncrypted.ts | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/hooks/useIsEncrypted.ts diff --git a/src/hooks/useIsEncrypted.ts b/src/hooks/useIsEncrypted.ts new file mode 100644 index 0000000000..79f3e539cd --- /dev/null +++ b/src/hooks/useIsEncrypted.ts @@ -0,0 +1,36 @@ +/* +Copyright 2020 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. +*/ + +import {useCallback, useState} from "react"; +import {MatrixClient} from "matrix-js-sdk/src/client"; +import {MatrixEvent} from "matrix-js-sdk/src/models/event"; +import {Room} from "matrix-js-sdk/src/models/room"; + +import {useEventEmitter} from "./useEventEmitter"; + +// Hook to simplify watching whether a Matrix room is encrypted, returns undefined if room is undefined +export function useIsEncrypted(cli: MatrixClient, room?: Room): boolean | undefined { + const [isEncrypted, setIsEncrypted] = useState(room ? cli.isRoomEncrypted(room.roomId) : undefined); + + const update = useCallback((event: MatrixEvent) => { + if (room && event.getType() === "m.room.encryption") { + setIsEncrypted(cli.isRoomEncrypted(room.roomId)); + } + }, [cli, room]); + useEventEmitter(room ? room.currentState : undefined, "RoomState.events", update); + + return isEncrypted; +} From 280690cf3c7618b3873e87750c1ee826a942d46b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 28 Aug 2020 10:59:52 +0100 Subject: [PATCH 7/9] use useIsEncrypted hook in UserInfo --- src/components/views/right_panel/UserInfo.js | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index 71ee86a1ea..518bb133ce 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -45,6 +45,7 @@ import EncryptionPanel from "./EncryptionPanel"; import { useAsyncMemo } from '../../../hooks/useAsyncMemo'; import { verifyUser, legacyVerifyUser, verifyDevice } from '../../../verification'; import {Action} from "../../../dispatcher/actions"; +import {useIsEncrypted} from "../../../hooks/useIsEncrypted"; const _disambiguateDevices = (devices) => { const names = Object.create(null); @@ -124,18 +125,6 @@ async function openDMForUser(matrixClient, userId) { createRoom(createRoomOptions); } -function useIsEncrypted(cli, room) { - const [isEncrypted, setIsEncrypted] = useState(room ? cli.isRoomEncrypted(room.roomId) : undefined); - - const update = useCallback((event) => { - if (event.getType() === "m.room.encryption") { - setIsEncrypted(cli.isRoomEncrypted(room.roomId)); - } - }, [cli, room]); - useEventEmitter(room ? room.currentState : undefined, "RoomState.events", update); - return isEncrypted; -} - function useHasCrossSigningKeys(cli, member, canVerify, setUpdating) { return useAsyncMemo(async () => { if (!canVerify) { @@ -1485,7 +1474,7 @@ const UserInfoHeader = ({onClose, member, e2eStatus}) => { const UserInfo = ({user, groupId, roomId, onClose, phase=RightPanelPhases.RoomMemberInfo, ...props}) => { const cli = useContext(MatrixClientContext); - // Load room if we are given a room id and memoize it + // Load room if we are given a room id and memoize it - this can be undefined for User Info/Group Member Info const room = useMemo(() => roomId ? cli.getRoom(roomId) : null, [cli, roomId]); // fetch latest room member if we have a room, so we don't show historical information, falling back to user const member = useMemo(() => room ? (room.getMember(user.userId) || user) : user, [room, user]); From bdfb77077ae4e3bdf3a20937614f81300b453af4 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 3 Sep 2020 16:08:10 +0100 Subject: [PATCH 8/9] Fix RightPanel propTypes --- src/components/structures/RightPanel.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index beba09d359..53459b9457 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -21,6 +21,8 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; +import {Room} from "matrix-js-sdk/src/models/room"; + import * as sdk from '../../index'; import dis from '../../dispatcher/dispatcher'; import RateLimitedFunc from '../../ratelimitedfunc'; @@ -34,7 +36,7 @@ import {Action} from "../../dispatcher/actions"; export default class RightPanel extends React.Component { static get propTypes() { return { - room: PropTypes.string, // if showing panels for a given room, this is set + room: PropTypes.instanceOf(Room), // if showing panels for a given room, this is set groupId: PropTypes.string, // if showing panels for a given group, this is set user: PropTypes.object, // used if we know the user ahead of opening the panel }; From f28c396b1eec1f91b52e01c1db3c227ba2370ed3 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 4 Sep 2020 12:14:43 +0100 Subject: [PATCH 9/9] Fix HeaderButtons handler bindings --- .../views/right_panel/GroupHeaderButtons.tsx | 10 ++++------ .../views/right_panel/RoomHeaderButtons.tsx | 12 ++++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/components/views/right_panel/GroupHeaderButtons.tsx b/src/components/views/right_panel/GroupHeaderButtons.tsx index c468658eb6..dd4a82e645 100644 --- a/src/components/views/right_panel/GroupHeaderButtons.tsx +++ b/src/components/views/right_panel/GroupHeaderButtons.tsx @@ -41,8 +41,6 @@ interface IProps {} export default class GroupHeaderButtons extends HeaderButtons { constructor(props: IProps) { super(props, HeaderKind.Group); - this.onMembersClicked = this.onMembersClicked.bind(this); - this.onRoomsClicked = this.onRoomsClicked.bind(this); } protected onAction(payload: ActionPayload) { @@ -68,7 +66,7 @@ export default class GroupHeaderButtons extends HeaderButtons { } } - private onMembersClicked() { + private onMembersClicked = () => { if (this.state.phase === RightPanelPhases.GroupMemberInfo) { // send the active phase to trigger a toggle this.setPhase(RightPanelPhases.GroupMemberInfo); @@ -76,12 +74,12 @@ export default class GroupHeaderButtons extends HeaderButtons { // This toggles for us, if needed this.setPhase(RightPanelPhases.GroupMemberList); } - } + }; - private onRoomsClicked() { + private onRoomsClicked = () => { // This toggles for us, if needed this.setPhase(RightPanelPhases.GroupRoomList); - } + }; renderButtons() { return [ diff --git a/src/components/views/right_panel/RoomHeaderButtons.tsx b/src/components/views/right_panel/RoomHeaderButtons.tsx index 671d9b0068..7d732b8ae3 100644 --- a/src/components/views/right_panel/RoomHeaderButtons.tsx +++ b/src/components/views/right_panel/RoomHeaderButtons.tsx @@ -54,7 +54,7 @@ export default class RoomHeaderButtons extends HeaderButtons { } } - private onMembersClicked() { + private onMembersClicked = () => { if (this.state.phase === RightPanelPhases.RoomMemberInfo) { // send the active phase to trigger a toggle // XXX: we should pass refireParams here but then it won't collapse as we desire it to @@ -63,17 +63,17 @@ export default class RoomHeaderButtons extends HeaderButtons { // This toggles for us, if needed this.setPhase(RightPanelPhases.RoomMemberList); } - } + }; - private onFilesClicked() { + private onFilesClicked = () => { // This toggles for us, if needed this.setPhase(RightPanelPhases.FilePanel); - } + }; - private onNotificationsClicked() { + private onNotificationsClicked = () => { // This toggles for us, if needed this.setPhase(RightPanelPhases.NotificationPanel); - } + }; public renderButtons() { return [