diff --git a/src/components/views/room_settings/RoomProfileSettings.js b/src/components/views/room_settings/RoomProfileSettings.tsx similarity index 76% rename from src/components/views/room_settings/RoomProfileSettings.js rename to src/components/views/room_settings/RoomProfileSettings.tsx index a1dfbe31dc..6533028e8c 100644 --- a/src/components/views/room_settings/RoomProfileSettings.js +++ b/src/components/views/room_settings/RoomProfileSettings.tsx @@ -15,27 +15,43 @@ limitations under the License. */ import React, { createRef } from 'react'; -import PropTypes from 'prop-types'; import { _t } from "../../../languageHandler"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import Field from "../elements/Field"; -import * as sdk from "../../../index"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import { mediaFromMxc } from "../../../customisations/Media"; +import AccessibleButton from "../elements/AccessibleButton"; +import AvatarSetting from "../settings/AvatarSetting"; + +interface IProps { + roomId: string; +} + +interface IState { + originalDisplayName: string; + displayName: string; + originalAvatarUrl: string; + avatarUrl: string; + avatarFile: File; + originalTopic: string; + topic: string; + enableProfileSave: boolean; + canSetName: boolean; + canSetTopic: boolean; + canSetAvatar: boolean; +} // TODO: Merge with ProfileSettings? @replaceableComponent("views.room_settings.RoomProfileSettings") -export default class RoomProfileSettings extends React.Component { - static propTypes = { - roomId: PropTypes.string.isRequired, - }; +export default class RoomProfileSettings extends React.Component { + private avatarUpload = createRef(); - constructor(props) { + constructor(props: IProps) { super(props); const client = MatrixClientPeg.get(); const room = client.getRoom(props.roomId); - if (!room) throw new Error("Expected a room for ID: ", props.roomId); + if (!room) throw new Error(`Expected a room for ID: ${props.roomId}`); const avatarEvent = room.currentState.getStateEvents("m.room.avatar", ""); let avatarUrl = avatarEvent && avatarEvent.getContent() ? avatarEvent.getContent()["url"] : null; @@ -60,17 +76,15 @@ export default class RoomProfileSettings extends React.Component { canSetTopic: room.currentState.maySendStateEvent('m.room.topic', client.getUserId()), canSetAvatar: room.currentState.maySendStateEvent('m.room.avatar', client.getUserId()), }; - - this._avatarUpload = createRef(); } - _uploadAvatar = () => { - this._avatarUpload.current.click(); + private uploadAvatar = (): void => { + this.avatarUpload.current.click(); }; - _removeAvatar = () => { + private removeAvatar = (): void => { // clear file upload field so same file can be selected - this._avatarUpload.current.value = ""; + this.avatarUpload.current.value = ""; this.setState({ avatarUrl: null, avatarFile: null, @@ -78,7 +92,7 @@ export default class RoomProfileSettings extends React.Component { }); }; - _cancelProfileChanges = async (e) => { + private cancelProfileChanges = async (e: React.MouseEvent): Promise => { e.stopPropagation(); e.preventDefault(); @@ -92,7 +106,7 @@ export default class RoomProfileSettings extends React.Component { }); }; - _saveProfile = async (e) => { + private saveProfile = async (e: React.FormEvent): Promise => { e.stopPropagation(); e.preventDefault(); @@ -100,35 +114,46 @@ export default class RoomProfileSettings extends React.Component { this.setState({ enableProfileSave: false }); const client = MatrixClientPeg.get(); - const newState = {}; + + let originalDisplayName: string; + let avatarUrl: string; + let originalAvatarUrl: string; + let originalTopic: string; + let avatarFile: File; // TODO: What do we do about errors? const displayName = this.state.displayName.trim(); if (this.state.originalDisplayName !== this.state.displayName) { await client.setRoomName(this.props.roomId, displayName); - newState.originalDisplayName = displayName; - newState.displayName = displayName; + originalDisplayName = displayName; } if (this.state.avatarFile) { const uri = await client.uploadContent(this.state.avatarFile); await client.sendStateEvent(this.props.roomId, 'm.room.avatar', { url: uri }, ''); - newState.avatarUrl = mediaFromMxc(uri).getSquareThumbnailHttp(96); - newState.originalAvatarUrl = newState.avatarUrl; - newState.avatarFile = null; + avatarUrl = mediaFromMxc(uri).getSquareThumbnailHttp(96); + originalAvatarUrl = avatarUrl; + avatarFile = null; } else if (this.state.originalAvatarUrl !== this.state.avatarUrl) { await client.sendStateEvent(this.props.roomId, 'm.room.avatar', {}, ''); } if (this.state.originalTopic !== this.state.topic) { await client.setRoomTopic(this.props.roomId, this.state.topic); - newState.originalTopic = this.state.topic; + originalTopic = this.state.topic; } - this.setState(newState); + this.setState({ + originalAvatarUrl, + avatarUrl, + originalDisplayName, + originalTopic, + displayName, + avatarFile, + }); }; - _onDisplayNameChanged = (e) => { + private onDisplayNameChanged = (e: React.ChangeEvent): void => { this.setState({ displayName: e.target.value }); if (this.state.originalDisplayName === e.target.value) { this.setState({ enableProfileSave: false }); @@ -137,7 +162,7 @@ export default class RoomProfileSettings extends React.Component { } }; - _onTopicChanged = (e) => { + private onTopicChanged = (e: React.ChangeEvent): void => { this.setState({ topic: e.target.value }); if (this.state.originalTopic === e.target.value) { this.setState({ enableProfileSave: false }); @@ -146,7 +171,7 @@ export default class RoomProfileSettings extends React.Component { } }; - _onAvatarChanged = (e) => { + private onAvatarChanged = (e: React.ChangeEvent): void => { if (!e.target.files || !e.target.files.length) { this.setState({ avatarUrl: this.state.originalAvatarUrl, @@ -160,7 +185,7 @@ export default class RoomProfileSettings extends React.Component { const reader = new FileReader(); reader.onload = (ev) => { this.setState({ - avatarUrl: ev.target.result, + avatarUrl: String(ev.target.result), avatarFile: file, enableProfileSave: true, }); @@ -168,10 +193,7 @@ export default class RoomProfileSettings extends React.Component { reader.readAsDataURL(file); }; - render() { - const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); - const AvatarSetting = sdk.getComponent('settings.AvatarSetting'); - + public render(): JSX.Element { let profileSettingsButtons; if ( this.state.canSetName || @@ -181,14 +203,14 @@ export default class RoomProfileSettings extends React.Component { profileSettingsButtons = (
{ _t("Cancel") } @@ -200,16 +222,16 @@ export default class RoomProfileSettings extends React.Component { return (
@@ -219,7 +241,7 @@ export default class RoomProfileSettings extends React.Component { type="text" value={this.state.displayName} autoComplete="off" - onChange={this._onDisplayNameChanged} + onChange={this.onDisplayNameChanged} disabled={!this.state.canSetName} />
@@ -238,8 +260,8 @@ export default class RoomProfileSettings extends React.Component { avatarUrl={this.state.avatarUrl} avatarName={this.state.displayName || this.props.roomId} avatarAltText={_t("Room avatar")} - uploadAvatar={this.state.canSetAvatar ? this._uploadAvatar : undefined} - removeAvatar={this.state.canSetAvatar ? this._removeAvatar : undefined} /> + uploadAvatar={this.state.canSetAvatar ? this.uploadAvatar : undefined} + removeAvatar={this.state.canSetAvatar ? this.removeAvatar : undefined} />
{ profileSettingsButtons } diff --git a/src/components/views/room_settings/UrlPreviewSettings.js b/src/components/views/room_settings/UrlPreviewSettings.tsx similarity index 88% rename from src/components/views/room_settings/UrlPreviewSettings.js rename to src/components/views/room_settings/UrlPreviewSettings.tsx index 0ff3b051d6..bb639b691a 100644 --- a/src/components/views/room_settings/UrlPreviewSettings.js +++ b/src/components/views/room_settings/UrlPreviewSettings.tsx @@ -18,8 +18,6 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; -import * as sdk from "../../../index"; import { _t, _td } from '../../../languageHandler'; import SettingsStore from "../../../settings/SettingsStore"; import dis from "../../../dispatcher/dispatcher"; @@ -27,21 +25,22 @@ import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { Action } from "../../../dispatcher/actions"; import { SettingLevel } from "../../../settings/SettingLevel"; import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { Room } from "matrix-js-sdk/src/models/room"; +import SettingsFlag from "../elements/SettingsFlag"; + +interface IProps { + room: Room; +} @replaceableComponent("views.room_settings.UrlPreviewSettings") -export default class UrlPreviewSettings extends React.Component { - static propTypes = { - room: PropTypes.object, - }; - - _onClickUserSettings = (e) => { +export default class UrlPreviewSettings extends React.Component { + private onClickUserSettings = (e: React.MouseEvent): void => { e.preventDefault(); e.stopPropagation(); dis.fire(Action.ViewUserSettings); }; - render() { - const SettingsFlag = sdk.getComponent("elements.SettingsFlag"); + public render(): JSX.Element { const roomId = this.props.room.roomId; const isEncrypted = MatrixClientPeg.get().isRoomEncrypted(roomId); @@ -54,18 +53,18 @@ export default class UrlPreviewSettings extends React.Component { if (accountEnabled) { previewsForAccount = ( _t("You have enabled URL previews by default.", {}, { - 'a': (sub)=>{ sub }, + 'a': (sub)=>{ sub }, }) ); } else { previewsForAccount = ( _t("You have disabled URL previews by default.", {}, { - 'a': (sub)=>{ sub }, + 'a': (sub)=>{ sub }, }) ); } - if (SettingsStore.canSetValue("urlPreviewsEnabled", roomId, "room")) { + if (SettingsStore.canSetValue("urlPreviewsEnabled", roomId, SettingLevel.ROOM)) { previewsForRoom = (