Merge pull request #5663 from matrix-org/t3chguy/spaces1
Use and create new room helperspull/21833/head
						commit
						a581c36f58
					
				|  | @ -390,7 +390,7 @@ export class ContextMenu extends React.PureComponent<IProps, IState> { | |||
| } | ||||
| 
 | ||||
| // Placement method for <ContextMenu /> to position context menu to right of elementRect with chevronOffset
 | ||||
| export const toRightOf = (elementRect: DOMRect, chevronOffset = 12) => { | ||||
| export const toRightOf = (elementRect: Pick<DOMRect, "right" | "top" | "height">, chevronOffset = 12) => { | ||||
|     const left = elementRect.right + window.pageXOffset + 3; | ||||
|     let top = elementRect.top + (elementRect.height / 2) + window.pageYOffset; | ||||
|     top -= chevronOffset + 8; // where 8 is half the height of the chevron
 | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ 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 React from 'react'; | ||||
| import React, {ComponentProps} from 'react'; | ||||
| import Room from 'matrix-js-sdk/src/models/room'; | ||||
| import {getHttpUriForMxc} from 'matrix-js-sdk/src/content-repo'; | ||||
| 
 | ||||
|  | @ -24,7 +24,7 @@ import Modal from '../../../Modal'; | |||
| import * as Avatar from '../../../Avatar'; | ||||
| import {ResizeMethod} from "../../../Avatar"; | ||||
| 
 | ||||
| interface IProps { | ||||
| interface IProps extends Omit<ComponentProps<typeof BaseAvatar>, "name" | "idName" | "url" | "onClick">{ | ||||
|     // Room may be left unset here, but if it is,
 | ||||
|     // oobData.avatarUrl should be set (else there
 | ||||
|     // would be nowhere to get the avatar from)
 | ||||
|  |  | |||
|  | @ -0,0 +1,40 @@ | |||
| /* | ||||
| Copyright 2021 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 {useEffect, useState} from "react"; | ||||
| import {Room} from "matrix-js-sdk/src/models/room"; | ||||
| 
 | ||||
| import {useEventEmitter} from "../../../hooks/useEventEmitter"; | ||||
| 
 | ||||
| interface IProps { | ||||
|     room: Room; | ||||
|     children?(name: string): JSX.Element; | ||||
| } | ||||
| 
 | ||||
| const RoomName = ({ room, children }: IProps): JSX.Element => { | ||||
|     const [name, setName] = useState(room?.name); | ||||
|     useEventEmitter(room, "Room.name", () => { | ||||
|         setName(room?.name); | ||||
|     }); | ||||
|     useEffect(() => { | ||||
|         setName(room?.name); | ||||
|     }, [room]); | ||||
| 
 | ||||
|     if (children) return children(name); | ||||
|     return name || ""; | ||||
| }; | ||||
| 
 | ||||
| export default RoomName; | ||||
|  | @ -0,0 +1,45 @@ | |||
| /* | ||||
| Copyright 2021 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 React, {useEffect, useState} from "react"; | ||||
| import {EventType} from "matrix-js-sdk/src/@types/event"; | ||||
| import {Room} from "matrix-js-sdk/src/models/room"; | ||||
| 
 | ||||
| import {useEventEmitter} from "../../../hooks/useEventEmitter"; | ||||
| import {linkifyElement} from "../../../HtmlUtils"; | ||||
| 
 | ||||
| interface IProps { | ||||
|     room?: Room; | ||||
|     children?(topic: string, ref: (element: HTMLElement) => void): JSX.Element; | ||||
| } | ||||
| 
 | ||||
| export const getTopic = room => room?.currentState?.getStateEvents(EventType.RoomTopic, "")?.getContent()?.topic; | ||||
| 
 | ||||
| const RoomTopic = ({ room, children }: IProps): JSX.Element => { | ||||
|     const [topic, setTopic] = useState(getTopic(room)); | ||||
|     useEventEmitter(room.currentState, "RoomState.events", () => { | ||||
|         setTopic(getTopic(room)); | ||||
|     }); | ||||
|     useEffect(() => { | ||||
|         setTopic(getTopic(room)); | ||||
|     }, [room]); | ||||
| 
 | ||||
|     const ref = e => e && linkifyElement(e); | ||||
|     if (children) return children(topic, ref); | ||||
|     return <span ref={ref}>{ topic }</span>; | ||||
| }; | ||||
| 
 | ||||
| export default RoomTopic; | ||||
|  | @ -450,17 +450,7 @@ export default class MemberList extends React.Component { | |||
|         let inviteButton; | ||||
| 
 | ||||
|         if (room && room.getMyMembership() === 'join') { | ||||
|             // assume we can invite until proven false
 | ||||
|             let canInvite = true; | ||||
| 
 | ||||
|             const plEvent = room.currentState.getStateEvents("m.room.power_levels", ""); | ||||
|             const me = room.getMember(cli.getUserId()); | ||||
|             if (plEvent && me) { | ||||
|                 const content = plEvent.getContent(); | ||||
|                 if (content && content.invite > me.powerLevel) { | ||||
|                     canInvite = false; | ||||
|                 } | ||||
|             } | ||||
|             const canInvite = room.canInvite(cli.getUserId()); | ||||
| 
 | ||||
|             let inviteButtonText = _t("Invite to this room"); | ||||
|             const chat = CommunityPrototypeStore.instance.getSelectedCommunityGeneralChat(); | ||||
|  |  | |||
|  | @ -100,15 +100,8 @@ const NewRoomIntro = () => { | |||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         let canInvite = inRoom; | ||||
|         const powerLevels = room.currentState.getStateEvents(EventType.RoomPowerLevels, "")?.getContent(); | ||||
|         const me = room.getMember(cli.getUserId()); | ||||
|         if (powerLevels && me && powerLevels.invite > me.powerLevel) { | ||||
|             canInvite = false; | ||||
|         } | ||||
| 
 | ||||
|         let buttons; | ||||
|         if (canInvite) { | ||||
|         if (room.canInvite(cli.getUserId())) { | ||||
|             const onInviteClick = () => { | ||||
|                 dis.dispatch({ action: "view_invite", roomId }); | ||||
|             }; | ||||
|  |  | |||
|  | @ -15,14 +15,13 @@ See the License for the specific language governing permissions and | |||
| limitations under the License. | ||||
| */ | ||||
| 
 | ||||
| import React, {createRef} from 'react'; | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import classNames from 'classnames'; | ||||
| import { _t } from '../../../languageHandler'; | ||||
| import {MatrixClientPeg} from '../../../MatrixClientPeg'; | ||||
| import RateLimitedFunc from '../../../ratelimitedfunc'; | ||||
| 
 | ||||
| import { linkifyElement } from '../../../HtmlUtils'; | ||||
| import {CancelButton} from './SimpleRoomHeader'; | ||||
| import SettingsStore from "../../../settings/SettingsStore"; | ||||
| import RoomHeaderButtons from '../right_panel/RoomHeaderButtons'; | ||||
|  | @ -30,6 +29,8 @@ import E2EIcon from './E2EIcon'; | |||
| import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar"; | ||||
| import {DefaultTagID} from "../../../stores/room-list/models"; | ||||
| import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; | ||||
| import RoomTopic from "../elements/RoomTopic"; | ||||
| import RoomName from "../elements/RoomName"; | ||||
| 
 | ||||
| export default class RoomHeader extends React.Component { | ||||
|     static propTypes = { | ||||
|  | @ -52,35 +53,13 @@ export default class RoomHeader extends React.Component { | |||
|         onCancelClick: null, | ||||
|     }; | ||||
| 
 | ||||
|     constructor(props) { | ||||
|         super(props); | ||||
| 
 | ||||
|         this._topic = createRef(); | ||||
|     } | ||||
| 
 | ||||
|     componentDidMount() { | ||||
|         const cli = MatrixClientPeg.get(); | ||||
|         cli.on("RoomState.events", this._onRoomStateEvents); | ||||
|         cli.on("Room.accountData", this._onRoomAccountData); | ||||
| 
 | ||||
|         // When a room name occurs, RoomState.events is fired *before*
 | ||||
|         // room.name is updated. So we have to listen to Room.name as well as
 | ||||
|         // RoomState.events.
 | ||||
|         if (this.props.room) { | ||||
|             this.props.room.on("Room.name", this._onRoomNameChange); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     componentDidUpdate() { | ||||
|         if (this._topic.current) { | ||||
|             linkifyElement(this._topic.current); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     componentWillUnmount() { | ||||
|         if (this.props.room) { | ||||
|             this.props.room.removeListener("Room.name", this._onRoomNameChange); | ||||
|         } | ||||
|         const cli = MatrixClientPeg.get(); | ||||
|         if (cli) { | ||||
|             cli.removeListener("RoomState.events", this._onRoomStateEvents); | ||||
|  | @ -109,10 +88,6 @@ export default class RoomHeader extends React.Component { | |||
|         this.forceUpdate(); | ||||
|     }, 500); | ||||
| 
 | ||||
|     _onRoomNameChange = (room) => { | ||||
|         this.forceUpdate(); | ||||
|     }; | ||||
| 
 | ||||
|     _hasUnreadPins() { | ||||
|         const currentPinEvent = this.props.room.currentState.getStateEvents("m.room.pinned_events", ''); | ||||
|         if (!currentPinEvent) return false; | ||||
|  | @ -170,29 +145,28 @@ export default class RoomHeader extends React.Component { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let roomName = _t("Join Room"); | ||||
|         let oobName = _t("Join Room"); | ||||
|         if (this.props.oobData && this.props.oobData.name) { | ||||
|             roomName = this.props.oobData.name; | ||||
|         } else if (this.props.room) { | ||||
|             roomName = this.props.room.name; | ||||
|             oobName = this.props.oobData.name; | ||||
|         } | ||||
| 
 | ||||
|         const textClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint }); | ||||
|         const name = | ||||
|             <div className="mx_RoomHeader_name" onClick={this.props.onSettingsClick}> | ||||
|                 <div dir="auto" className={textClasses} title={roomName}>{ roomName }</div> | ||||
|                 <RoomName room={this.props.room}> | ||||
|                     {(name) => { | ||||
|                         const roomName = name || oobName; | ||||
|                         return <div dir="auto" className={textClasses} title={roomName}>{ roomName }</div>; | ||||
|                     }} | ||||
|                 </RoomName> | ||||
|                 { searchStatus } | ||||
|             </div>; | ||||
| 
 | ||||
|         let topic; | ||||
|         if (this.props.room) { | ||||
|             const ev = this.props.room.currentState.getStateEvents('m.room.topic', ''); | ||||
|             if (ev) { | ||||
|                 topic = ev.getContent().topic; | ||||
|             } | ||||
|         } | ||||
|         const topicElement = | ||||
|             <div className="mx_RoomHeader_topic" ref={this._topic} title={topic} dir="auto">{ topic }</div>; | ||||
|         const topicElement = <RoomTopic room={this.props.room}> | ||||
|             {(topic, ref) => <div className="mx_RoomHeader_topic" ref={ref} title={topic} dir="auto"> | ||||
|                 { topic } | ||||
|             </div>} | ||||
|         </RoomTopic>; | ||||
| 
 | ||||
|         let roomAvatar; | ||||
|         if (this.props.room) { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Michael Telatynski
						Michael Telatynski