Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 8f6d31b

Browse files
authored
Merge pull request #6251 from SimonBrandner/ts/entity-and-member-tile
2 parents 767b8cd + dc2f71b commit 8f6d31b

File tree

3 files changed

+115
-107
lines changed

3 files changed

+115
-107
lines changed

src/components/views/rooms/EntityTile.js renamed to src/components/views/rooms/EntityTile.tsx

+47-46
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,38 @@ limitations under the License.
1717
*/
1818

1919
import React from 'react';
20-
import PropTypes from 'prop-types';
21-
import * as sdk from '../../../index';
2220
import AccessibleButton from '../elements/AccessibleButton';
23-
import { _t } from '../../../languageHandler';
21+
import { _td } from '../../../languageHandler';
2422
import classNames from "classnames";
2523
import E2EIcon from './E2EIcon';
26-
import {replaceableComponent} from "../../../utils/replaceableComponent";
24+
import { replaceableComponent } from "../../../utils/replaceableComponent";
25+
import BaseAvatar from '../avatars/BaseAvatar';
26+
import PresenceLabel from "./PresenceLabel";
27+
28+
export enum PowerStatus {
29+
Admin = "admin",
30+
Moderator = "moderator",
31+
}
32+
33+
const PowerLabel: Record<PowerStatus, string> = {
34+
[PowerStatus.Admin]: _td("Admin"),
35+
[PowerStatus.Moderator]: _td("Mod"),
36+
}
2737

2838
const PRESENCE_CLASS = {
2939
"offline": "mx_EntityTile_offline",
3040
"online": "mx_EntityTile_online",
3141
"unavailable": "mx_EntityTile_unavailable",
3242
};
3343

34-
function presenceClassForMember(presenceState, lastActiveAgo, showPresence) {
44+
function presenceClassForMember(presenceState: string, lastActiveAgo: number, showPresence: boolean): string {
3545
if (showPresence === false) {
3646
return 'mx_EntityTile_online_beenactive';
3747
}
3848

3949
// offline is split into two categories depending on whether we have
4050
// a last_active_ago for them.
41-
if (presenceState == 'offline') {
51+
if (presenceState === 'offline') {
4252
if (lastActiveAgo) {
4353
return PRESENCE_CLASS['offline'] + '_beenactive';
4454
} else {
@@ -51,29 +61,32 @@ function presenceClassForMember(presenceState, lastActiveAgo, showPresence) {
5161
}
5262
}
5363

54-
@replaceableComponent("views.rooms.EntityTile")
55-
class EntityTile extends React.Component {
56-
static propTypes = {
57-
name: PropTypes.string,
58-
title: PropTypes.string,
59-
avatarJsx: PropTypes.any, // <BaseAvatar />
60-
className: PropTypes.string,
61-
presenceState: PropTypes.string,
62-
presenceLastActiveAgo: PropTypes.number,
63-
presenceLastTs: PropTypes.number,
64-
presenceCurrentlyActive: PropTypes.bool,
65-
showInviteButton: PropTypes.bool,
66-
shouldComponentUpdate: PropTypes.func,
67-
onClick: PropTypes.func,
68-
suppressOnHover: PropTypes.bool,
69-
showPresence: PropTypes.bool,
70-
subtextLabel: PropTypes.string,
71-
e2eStatus: PropTypes.string,
72-
};
64+
interface IProps {
65+
name?: string;
66+
title?: string;
67+
avatarJsx?: JSX.Element; // <BaseAvatar />
68+
className?: string;
69+
presenceState?: string;
70+
presenceLastActiveAgo?: number;
71+
presenceLastTs?: number;
72+
presenceCurrentlyActive?: boolean;
73+
showInviteButton?: boolean;
74+
onClick?(): void;
75+
suppressOnHover?: boolean;
76+
showPresence?: boolean;
77+
subtextLabel?: string;
78+
e2eStatus?: string;
79+
powerStatus?: PowerStatus;
80+
}
7381

82+
interface IState {
83+
hover: boolean;
84+
}
85+
86+
@replaceableComponent("views.rooms.EntityTile")
87+
export default class EntityTile extends React.PureComponent<IProps, IState> {
7488
static defaultProps = {
75-
shouldComponentUpdate: function(nextProps, nextState) { return true; },
76-
onClick: function() {},
89+
onClick: () => {},
7790
presenceState: "offline",
7891
presenceLastActiveAgo: 0,
7992
presenceLastTs: 0,
@@ -82,13 +95,12 @@ class EntityTile extends React.Component {
8295
showPresence: true,
8396
};
8497

85-
state = {
86-
hover: false,
87-
};
98+
constructor(props: IProps) {
99+
super(props);
88100

89-
shouldComponentUpdate(nextProps, nextState) {
90-
if (this.state.hover !== nextState.hover) return true;
91-
return this.props.shouldComponentUpdate(nextProps, nextState);
101+
this.state = {
102+
hover: false,
103+
};
92104
}
93105

94106
render() {
@@ -110,7 +122,6 @@ class EntityTile extends React.Component {
110122
const activeAgo = this.props.presenceLastActiveAgo ?
111123
(Date.now() - (this.props.presenceLastTs - this.props.presenceLastActiveAgo)) : -1;
112124

113-
const PresenceLabel = sdk.getComponent("rooms.PresenceLabel");
114125
let presenceLabel = null;
115126
if (this.props.showPresence) {
116127
presenceLabel = <PresenceLabel activeAgo={activeAgo}
@@ -155,10 +166,7 @@ class EntityTile extends React.Component {
155166
let powerLabel;
156167
const powerStatus = this.props.powerStatus;
157168
if (powerStatus) {
158-
const powerText = {
159-
[EntityTile.POWER_STATUS_MODERATOR]: _t("Mod"),
160-
[EntityTile.POWER_STATUS_ADMIN]: _t("Admin"),
161-
}[powerStatus];
169+
const powerText = PowerLabel[powerStatus];
162170
powerLabel = <div className="mx_EntityTile_power">{powerText}</div>;
163171
}
164172

@@ -168,14 +176,12 @@ class EntityTile extends React.Component {
168176
e2eIcon = <E2EIcon status={e2eStatus} isUser={true} bordered={true} />;
169177
}
170178

171-
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
172-
173179
const av = this.props.avatarJsx ||
174180
<BaseAvatar name={this.props.name} width={36} height={36} aria-hidden="true" />;
175181

176182
// The wrapping div is required to make the magic mouse listener work, for some reason.
177183
return (
178-
<div ref={(c) => this.container = c} >
184+
<div>
179185
<AccessibleButton
180186
className={classNames(mainClassNames)}
181187
title={this.props.title}
@@ -193,8 +199,3 @@ class EntityTile extends React.Component {
193199
);
194200
}
195201
}
196-
197-
EntityTile.POWER_STATUS_MODERATOR = "moderator";
198-
EntityTile.POWER_STATUS_ADMIN = "admin";
199-
200-
export default EntityTile;

src/components/views/rooms/MemberTile.js renamed to src/components/views/rooms/MemberTile.tsx

+44-34
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,33 @@ limitations under the License.
1717

1818
import SettingsStore from "../../../settings/SettingsStore";
1919
import React from 'react';
20-
import PropTypes from 'prop-types';
21-
import * as sdk from "../../../index";
2220
import dis from "../../../dispatcher/dispatcher";
2321
import { _t } from '../../../languageHandler';
2422
import { MatrixClientPeg } from "../../../MatrixClientPeg";
2523
import {Action} from "../../../dispatcher/actions";
26-
import {replaceableComponent} from "../../../utils/replaceableComponent";
24+
import { replaceableComponent } from "../../../utils/replaceableComponent";
25+
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
26+
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
27+
import { EventType } from "matrix-js-sdk/src/@types/event";
28+
import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
29+
import EntityTile, { PowerStatus } from "./EntityTile";
30+
import MemberAvatar from "./../avatars/MemberAvatar";
31+
32+
interface IProps {
33+
member: RoomMember;
34+
showPresence?: boolean;
35+
}
36+
37+
interface IState {
38+
statusMessage: string;
39+
isRoomEncrypted: boolean;
40+
e2eStatus: string;
41+
}
2742

2843
@replaceableComponent("views.rooms.MemberTile")
29-
export default class MemberTile extends React.Component {
30-
static propTypes = {
31-
member: PropTypes.any.isRequired, // RoomMember
32-
showPresence: PropTypes.bool,
33-
};
44+
export default class MemberTile extends React.Component<IProps, IState> {
45+
private userLastModifiedTime: number;
46+
private memberLastModifiedTime: number;
3447

3548
static defaultProps = {
3649
showPresence: true,
@@ -52,7 +65,7 @@ export default class MemberTile extends React.Component {
5265
if (SettingsStore.getValue("feature_custom_status")) {
5366
const { user } = this.props.member;
5467
if (user) {
55-
user.on("User._unstable_statusMessage", this._onStatusMessageCommitted);
68+
user.on("User._unstable_statusMessage", this.onStatusMessageCommitted);
5669
}
5770
}
5871

@@ -80,7 +93,7 @@ export default class MemberTile extends React.Component {
8093
if (user) {
8194
user.removeListener(
8295
"User._unstable_statusMessage",
83-
this._onStatusMessageCommitted,
96+
this.onStatusMessageCommitted,
8497
);
8598
}
8699

@@ -91,8 +104,8 @@ export default class MemberTile extends React.Component {
91104
}
92105
}
93106

94-
onRoomStateEvents = ev => {
95-
if (ev.getType() !== "m.room.encryption") return;
107+
private onRoomStateEvents = (ev: MatrixEvent): void => {
108+
if (ev.getType() !== EventType.RoomEncryption) return;
96109
const { roomId } = this.props.member;
97110
if (ev.getRoomId() !== roomId) return;
98111

@@ -105,17 +118,17 @@ export default class MemberTile extends React.Component {
105118
this.updateE2EStatus();
106119
};
107120

108-
onUserTrustStatusChanged = (userId, trustStatus) => {
121+
private onUserTrustStatusChanged = (userId: string, trustStatus: string): void => {
109122
if (userId !== this.props.member.userId) return;
110123
this.updateE2EStatus();
111124
};
112125

113-
onDeviceVerificationChanged = (userId, deviceId, deviceInfo) => {
126+
private onDeviceVerificationChanged = (userId: string, deviceId: string, deviceInfo: DeviceInfo): void => {
114127
if (userId !== this.props.member.userId) return;
115128
this.updateE2EStatus();
116129
};
117130

118-
async updateE2EStatus() {
131+
private async updateE2EStatus(): Promise<void> {
119132
const cli = MatrixClientPeg.get();
120133
const { userId } = this.props.member;
121134
const isMe = userId === cli.getUserId();
@@ -143,32 +156,32 @@ export default class MemberTile extends React.Component {
143156
});
144157
}
145158

146-
getStatusMessage() {
159+
private getStatusMessage(): string {
147160
const { user } = this.props.member;
148161
if (!user) {
149162
return "";
150163
}
151-
return user._unstable_statusMessage;
164+
return user.unstable_statusMessage;
152165
}
153166

154-
_onStatusMessageCommitted = () => {
167+
private onStatusMessageCommitted = (): void => {
155168
// The `User` object has observed a status message change.
156169
this.setState({
157170
statusMessage: this.getStatusMessage(),
158171
});
159172
};
160173

161-
shouldComponentUpdate(nextProps, nextState) {
174+
shouldComponentUpdate(nextProps: IProps, nextState: IState): boolean {
162175
if (
163-
this.member_last_modified_time === undefined ||
164-
this.member_last_modified_time < nextProps.member.getLastModifiedTime()
176+
this.memberLastModifiedTime === undefined ||
177+
this.memberLastModifiedTime < nextProps.member.getLastModifiedTime()
165178
) {
166179
return true;
167180
}
168181
if (
169182
nextProps.member.user &&
170-
(this.user_last_modified_time === undefined ||
171-
this.user_last_modified_time < nextProps.member.user.getLastModifiedTime())
183+
(this.userLastModifiedTime === undefined ||
184+
this.userLastModifiedTime < nextProps.member.user.getLastModifiedTime())
172185
) {
173186
return true;
174187
}
@@ -181,30 +194,27 @@ export default class MemberTile extends React.Component {
181194
return false;
182195
}
183196

184-
onClick = e => {
197+
private onClick = (): void => {
185198
dis.dispatch({
186199
action: Action.ViewUser,
187200
member: this.props.member,
188201
});
189202
};
190203

191-
_getDisplayName() {
204+
private getDisplayName(): string {
192205
return this.props.member.name;
193206
}
194207

195-
getPowerLabel() {
208+
private getPowerLabel(): string {
196209
return _t("%(userName)s (power %(powerLevelNumber)s)", {
197210
userName: this.props.member.userId,
198211
powerLevelNumber: this.props.member.powerLevel,
199212
});
200213
}
201214

202215
render() {
203-
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
204-
const EntityTile = sdk.getComponent('rooms.EntityTile');
205-
206216
const member = this.props.member;
207-
const name = this._getDisplayName();
217+
const name = this.getDisplayName();
208218
const presenceState = member.user ? member.user.presence : null;
209219

210220
let statusMessage = null;
@@ -217,13 +227,13 @@ export default class MemberTile extends React.Component {
217227
);
218228

219229
if (member.user) {
220-
this.user_last_modified_time = member.user.getLastModifiedTime();
230+
this.userLastModifiedTime = member.user.getLastModifiedTime();
221231
}
222-
this.member_last_modified_time = member.getLastModifiedTime();
232+
this.memberLastModifiedTime = member.getLastModifiedTime();
223233

224234
const powerStatusMap = new Map([
225-
[100, EntityTile.POWER_STATUS_ADMIN],
226-
[50, EntityTile.POWER_STATUS_MODERATOR],
235+
[100, PowerStatus.Admin],
236+
[50, PowerStatus.Moderator],
227237
]);
228238

229239
// Find the nearest power level with a badge

0 commit comments

Comments
 (0)