Merge pull request #5168 from matrix-org/t3chguy/dpsah/6785.2

Small code clean ups and tweaks
This commit is contained in:
Michael Telatynski 2020-09-04 12:25:46 +01:00 committed by GitHub
commit a713c9763b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 76 additions and 53 deletions

View file

@ -28,6 +28,7 @@ import SettingsStore from "../settings/SettingsStore";
import {ActiveRoomObserver} from "../ActiveRoomObserver"; import {ActiveRoomObserver} from "../ActiveRoomObserver";
import {Notifier} from "../Notifier"; import {Notifier} from "../Notifier";
import type {Renderer} from "react-dom"; import type {Renderer} from "react-dom";
import RightPanelStore from "../stores/RightPanelStore";
declare global { declare global {
interface Window { interface Window {
@ -49,6 +50,7 @@ declare global {
singletonModalManager: ModalManager; singletonModalManager: ModalManager;
mxSettingsStore: SettingsStore; mxSettingsStore: SettingsStore;
mxNotifier: typeof Notifier; mxNotifier: typeof Notifier;
mxRightPanelStore: RightPanelStore;
} }
interface Document { interface Document {

View file

@ -21,6 +21,8 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import {Room} from "matrix-js-sdk/src/models/room";
import * as sdk from '../../index'; import * as sdk from '../../index';
import dis from '../../dispatcher/dispatcher'; import dis from '../../dispatcher/dispatcher';
import RateLimitedFunc from '../../ratelimitedfunc'; import RateLimitedFunc from '../../ratelimitedfunc';
@ -34,7 +36,7 @@ import {Action} from "../../dispatcher/actions";
export default class RightPanel extends React.Component { export default class RightPanel extends React.Component {
static get propTypes() { static get propTypes() {
return { return {
roomId: 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 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 user: PropTypes.object, // used if we know the user ahead of opening the panel
}; };
@ -161,13 +163,13 @@ export default class RightPanel extends React.Component {
} }
onRoomStateMember(ev, state, member) { onRoomStateMember(ev, state, member) {
if (member.roomId !== this.props.roomId) { if (member.roomId !== this.props.room.roomId) {
return; return;
} }
// redraw the badge on the membership list // 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(); 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) { member.userId === this.state.member.userId) {
// refresh the member info (e.g. new power level) // refresh the member info (e.g. new power level)
this._delayedUpdate(); this._delayedUpdate();
@ -226,8 +228,8 @@ export default class RightPanel extends React.Component {
switch (this.state.phase) { switch (this.state.phase) {
case RightPanelPhases.RoomMemberList: case RightPanelPhases.RoomMemberList:
if (this.props.roomId) { if (this.props.room.roomId) {
panel = <MemberList roomId={this.props.roomId} key={this.props.roomId} />; panel = <MemberList roomId={this.props.room.roomId} key={this.props.room.roomId} />;
} }
break; break;
case RightPanelPhases.GroupMemberList: case RightPanelPhases.GroupMemberList:
@ -242,8 +244,8 @@ export default class RightPanel extends React.Component {
case RightPanelPhases.EncryptionPanel: case RightPanelPhases.EncryptionPanel:
panel = <UserInfo panel = <UserInfo
user={this.state.member} user={this.state.member}
roomId={this.props.roomId} roomId={this.props.room.roomId}
key={this.props.roomId || this.state.member.userId} key={this.props.room.roomId || this.state.member.userId}
onClose={this.onCloseUserInfo} onClose={this.onCloseUserInfo}
phase={this.state.phase} phase={this.state.phase}
verificationRequest={this.state.verificationRequest} verificationRequest={this.state.verificationRequest}
@ -251,7 +253,7 @@ export default class RightPanel extends React.Component {
/>; />;
break; break;
case RightPanelPhases.Room3pidMemberInfo: case RightPanelPhases.Room3pidMemberInfo:
panel = <ThirdPartyMemberInfo event={this.state.event} key={this.props.roomId} />; panel = <ThirdPartyMemberInfo event={this.state.event} key={this.props.room.roomId} />;
break; break;
case RightPanelPhases.GroupMemberInfo: case RightPanelPhases.GroupMemberInfo:
panel = <UserInfo panel = <UserInfo
@ -270,7 +272,7 @@ export default class RightPanel extends React.Component {
panel = <NotificationPanel />; panel = <NotificationPanel />;
break; break;
case RightPanelPhases.FilePanel: case RightPanelPhases.FilePanel:
panel = <FilePanel roomId={this.props.roomId} resizeNotifier={this.props.resizeNotifier} />; panel = <FilePanel roomId={this.props.room.roomId} resizeNotifier={this.props.resizeNotifier} />;
break; break;
} }

View file

@ -2062,7 +2062,7 @@ export default class RoomView extends React.Component {
const showRightPanel = !forceHideRightPanel && this.state.room && this.state.showRightPanel; const showRightPanel = !forceHideRightPanel && this.state.room && this.state.showRightPanel;
const rightPanel = showRightPanel const rightPanel = showRightPanel
? <RightPanel roomId={this.state.room.roomId} resizeNotifier={this.props.resizeNotifier} /> ? <RightPanel room={this.state.room} resizeNotifier={this.props.resizeNotifier} />
: null; : null;
const timelineClasses = classNames("mx_RoomView_timeline", { const timelineClasses = classNames("mx_RoomView_timeline", {

View file

@ -94,7 +94,7 @@ export default class ScrollPanel extends React.Component {
/* startAtBottom: if set to true, the view is assumed to start /* startAtBottom: if set to true, the view is assumed to start
* scrolled to the bottom. * 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 * stickyBottom, but I'm adding an extra parameter to ensure
* behaviour stays the same for other uses of ScrollPanel. * behaviour stays the same for other uses of ScrollPanel.
* If so, let's remove this parameter down the line. * If so, let's remove this parameter down the line.
@ -138,6 +138,7 @@ export default class ScrollPanel extends React.Component {
/* style: styles to add to the top-level div /* style: styles to add to the top-level div
*/ */
style: PropTypes.object, style: PropTypes.object,
/* resizeNotifier: ResizeNotifier to know when middle column has changed size /* resizeNotifier: ResizeNotifier to know when middle column has changed size
*/ */
resizeNotifier: PropTypes.object, resizeNotifier: PropTypes.object,

View file

@ -16,23 +16,24 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import {RoomMember} from "matrix-js-sdk/src/models/room-member";
import dis from "../../../dispatcher/dispatcher"; import dis from "../../../dispatcher/dispatcher";
import {Action} from "../../../dispatcher/actions"; import {Action} from "../../../dispatcher/actions";
import {MatrixClientPeg} from "../../../MatrixClientPeg"; import {MatrixClientPeg} from "../../../MatrixClientPeg";
import BaseAvatar from "./BaseAvatar"; import BaseAvatar from "./BaseAvatar";
interface IProps { interface IProps {
// TODO: replace with correct type member: RoomMember;
member: any; fallbackUserId?: string;
fallbackUserId: string;
width: number; width: number;
height: number; height: number;
resizeMethod: string; resizeMethod?: string;
// The onClick to give the avatar // 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` // Whether the onClick of the avatar should be overriden to dispatch `Action.ViewUser`
viewUserOnClick: boolean; viewUserOnClick?: boolean;
title: string; title?: string;
} }
interface IState { interface IState {

View file

@ -41,13 +41,9 @@ interface IProps {}
export default class GroupHeaderButtons extends HeaderButtons { export default class GroupHeaderButtons extends HeaderButtons {
constructor(props: IProps) { constructor(props: IProps) {
super(props, HeaderKind.Group); super(props, HeaderKind.Group);
this.onMembersClicked = this.onMembersClicked.bind(this);
this.onRoomsClicked = this.onRoomsClicked.bind(this);
} }
protected onAction(payload: ActionPayload) { protected onAction(payload: ActionPayload) {
super.onAction(payload);
if (payload.action === Action.ViewUser) { if (payload.action === Action.ViewUser) {
if ((payload as ViewUserPayload).member) { if ((payload as ViewUserPayload).member) {
this.setPhase(RightPanelPhases.RoomMemberInfo, {member: payload.member}); this.setPhase(RightPanelPhases.RoomMemberInfo, {member: payload.member});
@ -70,7 +66,7 @@ export default class GroupHeaderButtons extends HeaderButtons {
} }
} }
private onMembersClicked() { private onMembersClicked = () => {
if (this.state.phase === RightPanelPhases.GroupMemberInfo) { if (this.state.phase === RightPanelPhases.GroupMemberInfo) {
// send the active phase to trigger a toggle // send the active phase to trigger a toggle
this.setPhase(RightPanelPhases.GroupMemberInfo); this.setPhase(RightPanelPhases.GroupMemberInfo);
@ -78,12 +74,12 @@ export default class GroupHeaderButtons extends HeaderButtons {
// This toggles for us, if needed // This toggles for us, if needed
this.setPhase(RightPanelPhases.GroupMemberList); this.setPhase(RightPanelPhases.GroupMemberList);
} }
} };
private onRoomsClicked() { private onRoomsClicked = () => {
// This toggles for us, if needed // This toggles for us, if needed
this.setPhase(RightPanelPhases.GroupRoomList); this.setPhase(RightPanelPhases.GroupRoomList);
} };
renderButtons() { renderButtons() {
return [ return [

View file

@ -65,9 +65,7 @@ export default abstract class HeaderButtons extends React.Component<IProps, ISta
if (this.dispatcherRef) dis.unregister(this.dispatcherRef); if (this.dispatcherRef) dis.unregister(this.dispatcherRef);
} }
protected onAction(payload) { protected abstract onAction(payload);
// Ignore - intended to be overridden by subclasses
}
public setPhase(phase: RightPanelPhases, extras?: Partial<SetRightPanelPhaseRefireParams>) { public setPhase(phase: RightPanelPhases, extras?: Partial<SetRightPanelPhaseRefireParams>) {
dis.dispatch<SetRightPanelPhasePayload>({ dis.dispatch<SetRightPanelPhasePayload>({

View file

@ -36,13 +36,9 @@ const MEMBER_PHASES = [
export default class RoomHeaderButtons extends HeaderButtons { export default class RoomHeaderButtons extends HeaderButtons {
constructor(props) { constructor(props) {
super(props, HeaderKind.Room); 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) { protected onAction(payload: ActionPayload) {
super.onAction(payload);
if (payload.action === Action.ViewUser) { if (payload.action === Action.ViewUser) {
if (payload.member) { if (payload.member) {
this.setPhase(RightPanelPhases.RoomMemberInfo, {member: payload.member}); this.setPhase(RightPanelPhases.RoomMemberInfo, {member: payload.member});
@ -58,7 +54,7 @@ export default class RoomHeaderButtons extends HeaderButtons {
} }
} }
private onMembersClicked() { private onMembersClicked = () => {
if (this.state.phase === RightPanelPhases.RoomMemberInfo) { if (this.state.phase === RightPanelPhases.RoomMemberInfo) {
// send the active phase to trigger a toggle // 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 // XXX: we should pass refireParams here but then it won't collapse as we desire it to
@ -67,17 +63,17 @@ export default class RoomHeaderButtons extends HeaderButtons {
// This toggles for us, if needed // This toggles for us, if needed
this.setPhase(RightPanelPhases.RoomMemberList); this.setPhase(RightPanelPhases.RoomMemberList);
} }
} };
private onFilesClicked() { private onFilesClicked = () => {
// This toggles for us, if needed // This toggles for us, if needed
this.setPhase(RightPanelPhases.FilePanel); this.setPhase(RightPanelPhases.FilePanel);
} };
private onNotificationsClicked() { private onNotificationsClicked = () => {
// This toggles for us, if needed // This toggles for us, if needed
this.setPhase(RightPanelPhases.NotificationPanel); this.setPhase(RightPanelPhases.NotificationPanel);
} };
public renderButtons() { public renderButtons() {
return [ return [

View file

@ -45,6 +45,7 @@ import EncryptionPanel from "./EncryptionPanel";
import { useAsyncMemo } from '../../../hooks/useAsyncMemo'; import { useAsyncMemo } from '../../../hooks/useAsyncMemo';
import { verifyUser, legacyVerifyUser, verifyDevice } from '../../../verification'; import { verifyUser, legacyVerifyUser, verifyDevice } from '../../../verification';
import {Action} from "../../../dispatcher/actions"; import {Action} from "../../../dispatcher/actions";
import {useIsEncrypted} from "../../../hooks/useIsEncrypted";
const _disambiguateDevices = (devices) => { const _disambiguateDevices = (devices) => {
const names = Object.create(null); const names = Object.create(null);
@ -124,18 +125,6 @@ async function openDMForUser(matrixClient, userId) {
createRoom(createRoomOptions); 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) { function useHasCrossSigningKeys(cli, member, canVerify, setUpdating) {
return useAsyncMemo(async () => { return useAsyncMemo(async () => {
if (!canVerify) { if (!canVerify) {
@ -1485,7 +1474,7 @@ const UserInfoHeader = ({onClose, member, e2eStatus}) => {
const UserInfo = ({user, groupId, roomId, onClose, phase=RightPanelPhases.RoomMemberInfo, ...props}) => { const UserInfo = ({user, groupId, roomId, onClose, phase=RightPanelPhases.RoomMemberInfo, ...props}) => {
const cli = useContext(MatrixClientContext); 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]); 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 // 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]); const member = useMemo(() => room ? (room.getMember(user.userId) || user) : user, [room, user]);

View file

@ -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;
}

View file

@ -223,3 +223,5 @@ export default class RightPanelStore extends Store<ActionPayload> {
return RightPanelStore.instance; return RightPanelStore.instance;
} }
} }
window.mxRightPanelStore = RightPanelStore.getSharedInstance();