From d5acfc6cf453915deed0bf6ac6bca2b5920d73f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com> Date: Wed, 23 Jun 2021 17:27:53 +0200 Subject: [PATCH 01/11] Convert EntityTile to TS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> --- .../rooms/{EntityTile.js => EntityTile.tsx} | 94 ++++++++++--------- 1 file changed, 49 insertions(+), 45 deletions(-) rename src/components/views/rooms/{EntityTile.js => EntityTile.tsx} (75%) diff --git a/src/components/views/rooms/EntityTile.js b/src/components/views/rooms/EntityTile.tsx similarity index 75% rename from src/components/views/rooms/EntityTile.js rename to src/components/views/rooms/EntityTile.tsx index a92d87643c..53c5900fbf 100644 --- a/src/components/views/rooms/EntityTile.js +++ b/src/components/views/rooms/EntityTile.tsx @@ -16,14 +16,19 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; -import PropTypes from 'prop-types'; -import * as sdk from '../../../index'; +import React, { createRef } from 'react'; import AccessibleButton from '../elements/AccessibleButton'; -import { _t } from '../../../languageHandler'; +import { _td } from '../../../languageHandler'; import classNames from "classnames"; import E2EIcon from './E2EIcon'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import BaseAvatar from '../avatars/BaseAvatar'; +import PresenceLabel from "./PresenceLabel"; + +const PowerLabel: Record<string, string> = { + "admin": _td("Admin"), + "moderator": _td("Mod"), +} const PRESENCE_CLASS = { "offline": "mx_EntityTile_offline", @@ -31,14 +36,14 @@ const PRESENCE_CLASS = { "unavailable": "mx_EntityTile_unavailable", }; -function presenceClassForMember(presenceState, lastActiveAgo, showPresence) { +function presenceClassForMember(presenceState: string, lastActiveAgo: number, showPresence: boolean) { if (showPresence === false) { return 'mx_EntityTile_online_beenactive'; } // offline is split into two categories depending on whether we have // a last_active_ago for them. - if (presenceState == 'offline') { + if (presenceState === 'offline') { if (lastActiveAgo) { return PRESENCE_CLASS['offline'] + '_beenactive'; } else { @@ -51,29 +56,34 @@ function presenceClassForMember(presenceState, lastActiveAgo, showPresence) { } } -@replaceableComponent("views.rooms.EntityTile") -class EntityTile extends React.Component { - static propTypes = { - name: PropTypes.string, - title: PropTypes.string, - avatarJsx: PropTypes.any, // <BaseAvatar /> - className: PropTypes.string, - presenceState: PropTypes.string, - presenceLastActiveAgo: PropTypes.number, - presenceLastTs: PropTypes.number, - presenceCurrentlyActive: PropTypes.bool, - showInviteButton: PropTypes.bool, - shouldComponentUpdate: PropTypes.func, - onClick: PropTypes.func, - suppressOnHover: PropTypes.bool, - showPresence: PropTypes.bool, - subtextLabel: PropTypes.string, - e2eStatus: PropTypes.string, - }; +interface IProps { + name?: string, + title?: string, + avatarJsx?: JSX.Element, // <BaseAvatar /> + className?: string, + presenceState?: string, + presenceLastActiveAgo?: number, + presenceLastTs?: number, + presenceCurrentlyActive?: boolean, + showInviteButton?: boolean, + shouldComponentUpdate?(nextProps: IProps, nextState: IState): boolean, + onClick?(): void, + suppressOnHover?: boolean, + showPresence?: boolean, + subtextLabel?: string, + e2eStatus?: string, + powerStatus?: string, +} +interface IState { + hover: boolean; +} + +@replaceableComponent("views.rooms.EntityTile") +export default class EntityTile extends React.Component<IProps, IState> { static defaultProps = { - shouldComponentUpdate: function(nextProps, nextState) { return true; }, - onClick: function() {}, + shouldComponentUpdate: (nextProps: IProps, nextState: IState) => { return true; }, + onClick: () => {}, presenceState: "offline", presenceLastActiveAgo: 0, presenceLastTs: 0, @@ -81,12 +91,17 @@ class EntityTile extends React.Component { suppressOnHover: false, showPresence: true, }; + private container = createRef<HTMLDivElement>(); - state = { - hover: false, - }; + constructor(props: IProps) { + super(props); - shouldComponentUpdate(nextProps, nextState) { + this.state = { + hover: false, + }; + } + + shouldComponentUpdate(nextProps: IProps, nextState: IState) { if (this.state.hover !== nextState.hover) return true; return this.props.shouldComponentUpdate(nextProps, nextState); } @@ -110,7 +125,6 @@ class EntityTile extends React.Component { const activeAgo = this.props.presenceLastActiveAgo ? (Date.now() - (this.props.presenceLastTs - this.props.presenceLastActiveAgo)) : -1; - const PresenceLabel = sdk.getComponent("rooms.PresenceLabel"); let presenceLabel = null; if (this.props.showPresence) { presenceLabel = <PresenceLabel activeAgo={activeAgo} @@ -155,10 +169,7 @@ class EntityTile extends React.Component { let powerLabel; const powerStatus = this.props.powerStatus; if (powerStatus) { - const powerText = { - [EntityTile.POWER_STATUS_MODERATOR]: _t("Mod"), - [EntityTile.POWER_STATUS_ADMIN]: _t("Admin"), - }[powerStatus]; + const powerText = PowerLabel[powerStatus]; powerLabel = <div className="mx_EntityTile_power">{powerText}</div>; } @@ -168,14 +179,12 @@ class EntityTile extends React.Component { e2eIcon = <E2EIcon status={e2eStatus} isUser={true} bordered={true} />; } - const BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); - const av = this.props.avatarJsx || <BaseAvatar name={this.props.name} width={36} height={36} aria-hidden="true" />; // The wrapping div is required to make the magic mouse listener work, for some reason. return ( - <div ref={(c) => this.container = c} > + <div ref={this.container} > <AccessibleButton className={classNames(mainClassNames)} title={this.props.title} @@ -193,8 +202,3 @@ class EntityTile extends React.Component { ); } } - -EntityTile.POWER_STATUS_MODERATOR = "moderator"; -EntityTile.POWER_STATUS_ADMIN = "admin"; - -export default EntityTile; From 87d27593de06f92f9dc39cbe818dc71f25778cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com> Date: Wed, 23 Jun 2021 17:28:02 +0200 Subject: [PATCH 02/11] Convert MemberTile to TS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> --- .../rooms/{MemberTile.js => MemberTile.tsx} | 68 +++++++++++-------- 1 file changed, 40 insertions(+), 28 deletions(-) rename src/components/views/rooms/{MemberTile.js => MemberTile.tsx} (79%) diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.tsx similarity index 79% rename from src/components/views/rooms/MemberTile.js rename to src/components/views/rooms/MemberTile.tsx index f8df7ed78f..e0ee0e5daf 100644 --- a/src/components/views/rooms/MemberTile.js +++ b/src/components/views/rooms/MemberTile.tsx @@ -17,20 +17,32 @@ limitations under the License. import SettingsStore from "../../../settings/SettingsStore"; import React from 'react'; -import PropTypes from 'prop-types'; import * as sdk from "../../../index"; import dis from "../../../dispatcher/dispatcher"; import { _t } from '../../../languageHandler'; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import {Action} from "../../../dispatcher/actions"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { RoomMember } from "matrix-js-sdk/src/models/room-member"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { EventType } from "matrix-js-sdk/src/@types/event"; +import { DeviceInfo } from "matrix-js-sdk/src/crypto"; + +interface IProps { + member: RoomMember, + showPresence?: boolean, +} + +interface IState { + statusMessage: string, + isRoomEncrypted: boolean, + e2eStatus: string, +} @replaceableComponent("views.rooms.MemberTile") -export default class MemberTile extends React.Component { - static propTypes = { - member: PropTypes.any.isRequired, // RoomMember - showPresence: PropTypes.bool, - }; +export default class MemberTile extends React.Component<IProps, IState> { + private userLastModifiedTime: number; + private memberLastModifiedTime: number; static defaultProps = { showPresence: true, @@ -52,7 +64,7 @@ export default class MemberTile extends React.Component { if (SettingsStore.getValue("feature_custom_status")) { const { user } = this.props.member; if (user) { - user.on("User._unstable_statusMessage", this._onStatusMessageCommitted); + user.on("User._unstable_statusMessage", this.onStatusMessageCommitted); } } @@ -80,7 +92,7 @@ export default class MemberTile extends React.Component { if (user) { user.removeListener( "User._unstable_statusMessage", - this._onStatusMessageCommitted, + this.onStatusMessageCommitted, ); } @@ -91,8 +103,8 @@ export default class MemberTile extends React.Component { } } - onRoomStateEvents = ev => { - if (ev.getType() !== "m.room.encryption") return; + private onRoomStateEvents = (ev: MatrixEvent): void => { + if (ev.getType() !== EventType.RoomEncryption) return; const { roomId } = this.props.member; if (ev.getRoomId() !== roomId) return; @@ -105,17 +117,17 @@ export default class MemberTile extends React.Component { this.updateE2EStatus(); }; - onUserTrustStatusChanged = (userId, trustStatus) => { + private onUserTrustStatusChanged = (userId: string, trustStatus: string): void => { if (userId !== this.props.member.userId) return; this.updateE2EStatus(); }; - onDeviceVerificationChanged = (userId, deviceId, deviceInfo) => { + private onDeviceVerificationChanged = (userId: string, deviceId: string, deviceInfo: DeviceInfo): void => { if (userId !== this.props.member.userId) return; this.updateE2EStatus(); }; - async updateE2EStatus() { + private async updateE2EStatus(): Promise<void> { const cli = MatrixClientPeg.get(); const { userId } = this.props.member; const isMe = userId === cli.getUserId(); @@ -143,32 +155,32 @@ export default class MemberTile extends React.Component { }); } - getStatusMessage() { + private getStatusMessage(): string { const { user } = this.props.member; if (!user) { return ""; } - return user._unstable_statusMessage; + return user.unstable_statusMessage; } - _onStatusMessageCommitted = () => { + private onStatusMessageCommitted = (): void => { // The `User` object has observed a status message change. this.setState({ statusMessage: this.getStatusMessage(), }); }; - shouldComponentUpdate(nextProps, nextState) { + shouldComponentUpdate(nextProps: IProps, nextState: IState): boolean { if ( - this.member_last_modified_time === undefined || - this.member_last_modified_time < nextProps.member.getLastModifiedTime() + this.memberLastModifiedTime === undefined || + this.memberLastModifiedTime < nextProps.member.getLastModifiedTime() ) { return true; } if ( nextProps.member.user && - (this.user_last_modified_time === undefined || - this.user_last_modified_time < nextProps.member.user.getLastModifiedTime()) + (this.userLastModifiedTime === undefined || + this.userLastModifiedTime < nextProps.member.user.getLastModifiedTime()) ) { return true; } @@ -181,18 +193,18 @@ export default class MemberTile extends React.Component { return false; } - onClick = e => { + private onClick = (e: MouseEvent): void => { dis.dispatch({ action: Action.ViewUser, member: this.props.member, }); }; - _getDisplayName() { + private getDisplayName(): string { return this.props.member.name; } - getPowerLabel() { + private getPowerLabel(): string { return _t("%(userName)s (power %(powerLevelNumber)s)", { userName: this.props.member.userId, powerLevelNumber: this.props.member.powerLevel, @@ -204,7 +216,7 @@ export default class MemberTile extends React.Component { const EntityTile = sdk.getComponent('rooms.EntityTile'); const member = this.props.member; - const name = this._getDisplayName(); + const name = this.getDisplayName(); const presenceState = member.user ? member.user.presence : null; let statusMessage = null; @@ -217,9 +229,9 @@ export default class MemberTile extends React.Component { ); if (member.user) { - this.user_last_modified_time = member.user.getLastModifiedTime(); + this.userLastModifiedTime = member.user.getLastModifiedTime(); } - this.member_last_modified_time = member.getLastModifiedTime(); + this.memberLastModifiedTime = member.getLastModifiedTime(); const powerStatusMap = new Map([ [100, EntityTile.POWER_STATUS_ADMIN], From e25940cbdd18630c58e6b4d58f577d85f30fd97b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com> Date: Wed, 23 Jun 2021 19:18:36 +0200 Subject: [PATCH 03/11] Convert PresenceLabel to TS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> --- .../{PresenceLabel.js => PresenceLabel.tsx} | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) rename src/components/views/rooms/{PresenceLabel.js => PresenceLabel.tsx} (69%) diff --git a/src/components/views/rooms/PresenceLabel.js b/src/components/views/rooms/PresenceLabel.tsx similarity index 69% rename from src/components/views/rooms/PresenceLabel.js rename to src/components/views/rooms/PresenceLabel.tsx index ca21afe63d..513fecfd43 100644 --- a/src/components/views/rooms/PresenceLabel.js +++ b/src/components/views/rooms/PresenceLabel.tsx @@ -15,26 +15,23 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import {replaceableComponent} from "../../../utils/replaceableComponent"; +interface IProps { + // number of milliseconds ago this user was last active. + // zero = unknown + activeAgo?: number, + // if true, activeAgo is an approximation and "Now" should + // be shown instead + currentlyActive?: boolean, + // offline, online, etc + presenceState?: string, +} + @replaceableComponent("views.rooms.PresenceLabel") -export default class PresenceLabel extends React.Component { - static propTypes = { - // number of milliseconds ago this user was last active. - // zero = unknown - activeAgo: PropTypes.number, - - // if true, activeAgo is an approximation and "Now" should - // be shown instead - currentlyActive: PropTypes.bool, - - // offline, online, etc - presenceState: PropTypes.string, - }; - +export default class PresenceLabel extends React.Component<IProps> { static defaultProps = { activeAgo: -1, presenceState: null, @@ -42,29 +39,29 @@ export default class PresenceLabel extends React.Component { // Return duration as a string using appropriate time units // XXX: This would be better handled using a culture-aware library, but we don't use one yet. - getDuration(time) { + private getDuration(time: number): string { if (!time) return; - const t = parseInt(time / 1000); + const t = time / 1000; const s = t % 60; - const m = parseInt(t / 60) % 60; - const h = parseInt(t / (60 * 60)) % 24; - const d = parseInt(t / (60 * 60 * 24)); + const m = t / 60 % 60; + const h = t / (60 * 60) % 24; + const d = t / (60 * 60 * 24); if (t < 60) { if (t < 0) { - return _t("%(duration)ss", {duration: 0}); + return _t("%(duration)ss", { duration: 0 }); } - return _t("%(duration)ss", {duration: s}); + return _t("%(duration)ss", { duration: s }); } if (t < 60 * 60) { - return _t("%(duration)sm", {duration: m}); + return _t("%(duration)sm", { duration: m }); } if (t < 24 * 60 * 60) { - return _t("%(duration)sh", {duration: h}); + return _t("%(duration)sh", { duration: h }); } - return _t("%(duration)sd", {duration: d}); + return _t("%(duration)sd", { duration: d }); } - getPrettyPresence(presence, activeAgo, currentlyActive) { + private getPrettyPresence(presence: string, activeAgo: number, currentlyActive: boolean): string { if (!currentlyActive && activeAgo !== undefined && activeAgo > 0) { const duration = this.getDuration(activeAgo); if (presence === "online") return _t("Online for %(duration)s", { duration: duration }); From 298e505381e96e30535bd1ce28b66b1e523be094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com> Date: Thu, 24 Jun 2021 14:29:24 +0200 Subject: [PATCH 04/11] Iterate EntityTile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> --- src/components/views/rooms/EntityTile.tsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/components/views/rooms/EntityTile.tsx b/src/components/views/rooms/EntityTile.tsx index 53c5900fbf..106449b391 100644 --- a/src/components/views/rooms/EntityTile.tsx +++ b/src/components/views/rooms/EntityTile.tsx @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { createRef } from 'react'; +import React from 'react'; import AccessibleButton from '../elements/AccessibleButton'; import { _td } from '../../../languageHandler'; import classNames from "classnames"; @@ -25,7 +25,12 @@ import { replaceableComponent } from "../../../utils/replaceableComponent"; import BaseAvatar from '../avatars/BaseAvatar'; import PresenceLabel from "./PresenceLabel"; -const PowerLabel: Record<string, string> = { +enum PowerStatus { + Admin = "admin", + Moderator = "moderator", +} + +const PowerLabel: Record<PowerStatus, string> = { "admin": _td("Admin"), "moderator": _td("Mod"), } @@ -36,7 +41,7 @@ const PRESENCE_CLASS = { "unavailable": "mx_EntityTile_unavailable", }; -function presenceClassForMember(presenceState: string, lastActiveAgo: number, showPresence: boolean) { +function presenceClassForMember(presenceState: string, lastActiveAgo: number, showPresence: boolean): string { if (showPresence === false) { return 'mx_EntityTile_online_beenactive'; } @@ -66,13 +71,12 @@ interface IProps { presenceLastTs?: number, presenceCurrentlyActive?: boolean, showInviteButton?: boolean, - shouldComponentUpdate?(nextProps: IProps, nextState: IState): boolean, onClick?(): void, suppressOnHover?: boolean, showPresence?: boolean, subtextLabel?: string, e2eStatus?: string, - powerStatus?: string, + powerStatus?: PowerStatus, } interface IState { @@ -82,7 +86,6 @@ interface IState { @replaceableComponent("views.rooms.EntityTile") export default class EntityTile extends React.Component<IProps, IState> { static defaultProps = { - shouldComponentUpdate: (nextProps: IProps, nextState: IState) => { return true; }, onClick: () => {}, presenceState: "offline", presenceLastActiveAgo: 0, @@ -91,7 +94,6 @@ export default class EntityTile extends React.Component<IProps, IState> { suppressOnHover: false, showPresence: true, }; - private container = createRef<HTMLDivElement>(); constructor(props: IProps) { super(props); @@ -103,7 +105,6 @@ export default class EntityTile extends React.Component<IProps, IState> { shouldComponentUpdate(nextProps: IProps, nextState: IState) { if (this.state.hover !== nextState.hover) return true; - return this.props.shouldComponentUpdate(nextProps, nextState); } render() { @@ -184,7 +185,7 @@ export default class EntityTile extends React.Component<IProps, IState> { // The wrapping div is required to make the magic mouse listener work, for some reason. return ( - <div ref={this.container} > + <div> <AccessibleButton className={classNames(mainClassNames)} title={this.props.title} From 1b64cd0c88bb1092f11e680460c4f983c9d7d0b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com> Date: Thu, 24 Jun 2021 14:36:22 +0200 Subject: [PATCH 05/11] Iterate PresenceLabel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> --- src/components/views/rooms/PresenceLabel.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/rooms/PresenceLabel.tsx b/src/components/views/rooms/PresenceLabel.tsx index 513fecfd43..abedb394b5 100644 --- a/src/components/views/rooms/PresenceLabel.tsx +++ b/src/components/views/rooms/PresenceLabel.tsx @@ -17,17 +17,17 @@ limitations under the License. import React from 'react'; import { _t } from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { // number of milliseconds ago this user was last active. // zero = unknown - activeAgo?: number, + activeAgo?: number; // if true, activeAgo is an approximation and "Now" should // be shown instead - currentlyActive?: boolean, + currentlyActive?: boolean; // offline, online, etc - presenceState?: string, + presenceState?: string; } @replaceableComponent("views.rooms.PresenceLabel") From 5b21cff24098b62fa45e7c46964ec8841d02a3fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com> Date: Thu, 24 Jun 2021 14:38:21 +0200 Subject: [PATCH 06/11] Iterate MemberTile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> --- src/components/views/rooms/MemberTile.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/views/rooms/MemberTile.tsx b/src/components/views/rooms/MemberTile.tsx index e0ee0e5daf..390cbdbf9f 100644 --- a/src/components/views/rooms/MemberTile.tsx +++ b/src/components/views/rooms/MemberTile.tsx @@ -29,14 +29,14 @@ import { EventType } from "matrix-js-sdk/src/@types/event"; import { DeviceInfo } from "matrix-js-sdk/src/crypto"; interface IProps { - member: RoomMember, - showPresence?: boolean, + member: RoomMember; + showPresence?: boolean; } interface IState { - statusMessage: string, - isRoomEncrypted: boolean, - e2eStatus: string, + statusMessage: string; + isRoomEncrypted: boolean; + e2eStatus: string; } @replaceableComponent("views.rooms.MemberTile") From 8fb788ae5679c44b46d70cf9887be01fe50f07ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com> Date: Thu, 24 Jun 2021 14:39:51 +0200 Subject: [PATCH 07/11] Iterate EntityTile once more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> --- src/components/views/rooms/EntityTile.tsx | 30 +++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/components/views/rooms/EntityTile.tsx b/src/components/views/rooms/EntityTile.tsx index 106449b391..de37d6caf0 100644 --- a/src/components/views/rooms/EntityTile.tsx +++ b/src/components/views/rooms/EntityTile.tsx @@ -62,21 +62,21 @@ function presenceClassForMember(presenceState: string, lastActiveAgo: number, sh } interface IProps { - name?: string, - title?: string, - avatarJsx?: JSX.Element, // <BaseAvatar /> - className?: string, - presenceState?: string, - presenceLastActiveAgo?: number, - presenceLastTs?: number, - presenceCurrentlyActive?: boolean, - showInviteButton?: boolean, - onClick?(): void, - suppressOnHover?: boolean, - showPresence?: boolean, - subtextLabel?: string, - e2eStatus?: string, - powerStatus?: PowerStatus, + name?: string; + title?: string; + avatarJsx?: JSX.Element; // <BaseAvatar /> + className?: string; + presenceState?: string; + presenceLastActiveAgo?: number; + presenceLastTs?: number; + presenceCurrentlyActive?: boolean; + showInviteButton?: boolean; + onClick?(): void; + suppressOnHover?: boolean; + showPresence?: boolean; + subtextLabel?: string; + e2eStatus?: string; + powerStatus?: PowerStatus; } interface IState { From f08b92309f95f018fcc7cd972a3ca16577df5196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com> Date: Thu, 24 Jun 2021 16:35:33 +0200 Subject: [PATCH 08/11] Iterate EntityTile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> --- src/components/views/rooms/EntityTile.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/components/views/rooms/EntityTile.tsx b/src/components/views/rooms/EntityTile.tsx index de37d6caf0..fedb0b2964 100644 --- a/src/components/views/rooms/EntityTile.tsx +++ b/src/components/views/rooms/EntityTile.tsx @@ -31,8 +31,8 @@ enum PowerStatus { } const PowerLabel: Record<PowerStatus, string> = { - "admin": _td("Admin"), - "moderator": _td("Mod"), + [PowerStatus.Admin]: _td("Admin"), + [PowerStatus.Moderator]: _td("Mod"), } const PRESENCE_CLASS = { @@ -84,7 +84,7 @@ interface IState { } @replaceableComponent("views.rooms.EntityTile") -export default class EntityTile extends React.Component<IProps, IState> { +export default class EntityTile extends React.PureComponent<IProps, IState> { static defaultProps = { onClick: () => {}, presenceState: "offline", @@ -103,10 +103,6 @@ export default class EntityTile extends React.Component<IProps, IState> { }; } - shouldComponentUpdate(nextProps: IProps, nextState: IState) { - if (this.state.hover !== nextState.hover) return true; - } - render() { const mainClassNames = { "mx_EntityTile": true, From c0a1127cb70a0bac98e13126927dd6d5f8450758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com> Date: Thu, 24 Jun 2021 16:43:11 +0200 Subject: [PATCH 09/11] Fix PowerStatus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> --- src/components/views/rooms/EntityTile.tsx | 2 +- src/components/views/rooms/MemberTile.tsx | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/views/rooms/EntityTile.tsx b/src/components/views/rooms/EntityTile.tsx index fedb0b2964..2032856500 100644 --- a/src/components/views/rooms/EntityTile.tsx +++ b/src/components/views/rooms/EntityTile.tsx @@ -25,7 +25,7 @@ import { replaceableComponent } from "../../../utils/replaceableComponent"; import BaseAvatar from '../avatars/BaseAvatar'; import PresenceLabel from "./PresenceLabel"; -enum PowerStatus { +export enum PowerStatus { Admin = "admin", Moderator = "moderator", } diff --git a/src/components/views/rooms/MemberTile.tsx b/src/components/views/rooms/MemberTile.tsx index 390cbdbf9f..c6077fb47f 100644 --- a/src/components/views/rooms/MemberTile.tsx +++ b/src/components/views/rooms/MemberTile.tsx @@ -27,6 +27,8 @@ import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { EventType } from "matrix-js-sdk/src/@types/event"; import { DeviceInfo } from "matrix-js-sdk/src/crypto"; +import EntityTile, { PowerStatus } from "./EntityTile"; +import MemberAvatar from "./../avatars/MemberAvatar"; interface IProps { member: RoomMember; @@ -212,9 +214,6 @@ export default class MemberTile extends React.Component<IProps, IState> { } render() { - const MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); - const EntityTile = sdk.getComponent('rooms.EntityTile'); - const member = this.props.member; const name = this.getDisplayName(); const presenceState = member.user ? member.user.presence : null; @@ -234,8 +233,8 @@ export default class MemberTile extends React.Component<IProps, IState> { this.memberLastModifiedTime = member.getLastModifiedTime(); const powerStatusMap = new Map([ - [100, EntityTile.POWER_STATUS_ADMIN], - [50, EntityTile.POWER_STATUS_MODERATOR], + [100, PowerStatus.Admin], + [50, PowerStatus.Moderator], ]); // Find the nearest power level with a badge From b065f6d1a4b591fce8da33183810598825b088f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com> Date: Thu, 24 Jun 2021 16:48:36 +0200 Subject: [PATCH 10/11] Remove sdk... MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> --- src/components/views/rooms/MemberTile.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/rooms/MemberTile.tsx b/src/components/views/rooms/MemberTile.tsx index c6077fb47f..a97ce6995b 100644 --- a/src/components/views/rooms/MemberTile.tsx +++ b/src/components/views/rooms/MemberTile.tsx @@ -17,7 +17,6 @@ limitations under the License. import SettingsStore from "../../../settings/SettingsStore"; import React from 'react'; -import * as sdk from "../../../index"; import dis from "../../../dispatcher/dispatcher"; import { _t } from '../../../languageHandler'; import { MatrixClientPeg } from "../../../MatrixClientPeg"; From dc2f71bee67b3e65f73b335e4d1d5cb0d15a1534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com> Date: Thu, 24 Jun 2021 16:55:44 +0200 Subject: [PATCH 11/11] Even more fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> --- src/components/views/rooms/MemberTile.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MemberTile.tsx b/src/components/views/rooms/MemberTile.tsx index a97ce6995b..2f9927a756 100644 --- a/src/components/views/rooms/MemberTile.tsx +++ b/src/components/views/rooms/MemberTile.tsx @@ -25,7 +25,7 @@ import { replaceableComponent } from "../../../utils/replaceableComponent"; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { EventType } from "matrix-js-sdk/src/@types/event"; -import { DeviceInfo } from "matrix-js-sdk/src/crypto"; +import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo"; import EntityTile, { PowerStatus } from "./EntityTile"; import MemberAvatar from "./../avatars/MemberAvatar"; @@ -194,7 +194,7 @@ export default class MemberTile extends React.Component<IProps, IState> { return false; } - private onClick = (e: MouseEvent): void => { + private onClick = (): void => { dis.dispatch({ action: Action.ViewUser, member: this.props.member,