This repository was archived by the owner on Sep 11, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 812
Show rooms in common with another user #4897
Closed
Closed
Changes from 18 commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
354089b
Show rooms in common with another user
Half-Shot e901aae
Fix lint
Half-Shot d06b90b
Add strings
Half-Shot f6d2e49
Add "compact" view for SharedRooms view
Half-Shot 9aed1c0
Show shared rooms to users when being invited
Half-Shot db2b642
Lint
Half-Shot e6d2c89
Typescriptify RoomListSorter
Half-Shot 29ce381
Order by activity
Half-Shot 23fe7d0
Limit to 3 rooms, but allow expansion
Half-Shot a617eb5
Fix lint
Half-Shot a3a9f19
Show count more
Half-Shot 81c68aa
Update if a new user is selected
Half-Shot b3a7215
Merge remote-tracking branch 'origin/develop' into hs/shared-rooms
Half-Shot 169a66c
Add UserInfoRoomTile
Half-Shot f9cfa60
Refactor to work with new room tiles
Half-Shot 5473f63
Fix builds
Half-Shot f73f937
Fix feature code
Half-Shot 76ab806
Merge branch 'develop' into hs/shared-rooms
Half-Shot 30384ac
Apply suggestions from code review
Half-Shot 7c828f4
Merge remote-tracking branch 'origin/develop' into hs/shared-rooms
Half-Shot f57dca7
Drop roomIds state
Half-Shot ba7ccbf
Tweaks
Half-Shot 51a4371
Linting
Half-Shot b2a188f
Merge remote-tracking branch 'origin/develop' into hs/shared-rooms
Half-Shot deafdb8
Initial stab at rendering shared rooms in the side panel
Half-Shot fbcaaab
Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into…
t3chguy ec90183
Iterate PR
t3chguy 135c2f7
Iterate PR some more
t3chguy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| .mx_UserInfoSharedRooms ul { | ||
| padding-left: 0px; | ||
| > li { | ||
| padding-left: 0px; | ||
| list-style: none; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| /* | ||
| Copyright 2015, 2016 OpenMarket Ltd | ||
| Copyright 2017 New Vector Ltd | ||
| Copyright 2018 Michael Telatynski <[email protected]> | ||
| Copyright 2019, 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 React from "react"; | ||
| import { Room } from "matrix-js-sdk/src/models/room"; | ||
| import classNames from "classnames"; | ||
| import AccessibleButton from "../../views/elements/AccessibleButton"; | ||
| import ActiveRoomObserver from "../../../ActiveRoomObserver"; | ||
| import { _t } from "../../../languageHandler"; | ||
| import { TagID, DefaultTagID } from "../../../stores/room-list/models"; | ||
| import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar"; | ||
| import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; | ||
| import dis from '../../../dispatcher/dispatcher'; | ||
| import { Key } from "../../../Keyboard"; | ||
|
|
||
| interface IProps { | ||
| room: Room; | ||
| } | ||
|
|
||
| type PartialDOMRect = Pick<DOMRect, "left" | "bottom">; | ||
|
|
||
| interface IState { | ||
| selected: boolean; | ||
| notificationsMenuPosition: PartialDOMRect; | ||
| generalMenuPosition: PartialDOMRect; | ||
| messagePreview?: string; | ||
| } | ||
|
|
||
| export default class UserInfoRoomTile extends React.PureComponent<IProps, IState> { | ||
| constructor(props: IProps) { | ||
| super(props); | ||
|
|
||
| this.state = { | ||
| selected: ActiveRoomObserver.activeRoomId === this.props.room.roomId, | ||
| notificationsMenuPosition: null, | ||
| generalMenuPosition: null, | ||
| }; | ||
| } | ||
|
|
||
| private onTileClick = (ev: React.KeyboardEvent) => { | ||
| ev.preventDefault(); | ||
| ev.stopPropagation(); | ||
| dis.dispatch({ | ||
| action: 'view_room', | ||
| show_room_tile: true, // make sure the room is visible in the list | ||
| room_id: this.props.room.roomId, | ||
| clear_search: (ev && (ev.key === Key.ENTER || ev.key === Key.SPACE)), | ||
| }); | ||
| }; | ||
|
|
||
| public render(): React.ReactElement { | ||
| const classes = classNames({ | ||
| 'mx_RoomTile': true, | ||
| 'mx_RoomTile_selected': this.state.selected, | ||
| }); | ||
|
|
||
| const roomAvatar = <DecoratedRoomAvatar | ||
| room={this.props.room} | ||
| avatarSize={32} | ||
| tag={DefaultTagID.Untagged} | ||
| displayBadge={false} | ||
| />; | ||
|
|
||
| let badge: React.ReactNode; | ||
|
|
||
| let name = this.props.room.name; | ||
| if (typeof name !== 'string') name = ''; | ||
| name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon | ||
|
|
||
| let nameContainer = ( | ||
| <div className="mx_RoomTile_nameContainer"> | ||
| <div title={name} className={"mx_RoomTile_name"} tabIndex={-1} dir="auto"> | ||
| {name} | ||
| </div> | ||
| </div> | ||
| ); | ||
|
|
||
| let ariaLabel = name; | ||
| let ariaDescribedBy: string; | ||
|
|
||
| const props: Partial<React.ComponentProps<typeof AccessibleTooltipButton>> = {}; | ||
| let Button: React.ComponentType<React.ComponentProps<typeof AccessibleButton>> = AccessibleButton; | ||
|
|
||
| return ( | ||
| <React.Fragment> | ||
| <Button | ||
| {...props} | ||
| className={classes} | ||
| onClick={this.onTileClick} | ||
| role="treeitem" | ||
| aria-label={ariaLabel} | ||
| aria-selected={this.state.selected} | ||
| aria-describedby={ariaDescribedBy} | ||
| > | ||
| {roomAvatar} | ||
| {nameContainer} | ||
| {badge} | ||
| </Button> | ||
| </React.Fragment> | ||
Half-Shot marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
177 changes: 177 additions & 0 deletions
177
src/components/views/right_panel/UserInfoSharedRooms.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| /* | ||
| 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 React from 'react'; | ||
| import { MatrixClientPeg } from '../../../MatrixClientPeg'; | ||
| import Spinner from "../elements/Spinner"; | ||
| import { _t } from '../../../languageHandler'; | ||
| import Pill from '../../views/elements/Pill'; | ||
| import AccessibleButton from '../../views/elements/AccessibleButton'; | ||
| import SpecPermalinkConstructor from '../../../utils/permalinks/SpecPermalinkConstructor'; | ||
| import { mostRecentActivityFirst } from '../../../RoomListSorter'; | ||
| import UserInfoRoomTile from "../elements/UserInfoRoomTile"; | ||
|
|
||
| interface IProps { | ||
| userId: string; | ||
| compact: boolean; | ||
| } | ||
|
|
||
| interface IState { | ||
| roomIds?: []; | ||
| error: boolean; | ||
| showAll: boolean; | ||
| } | ||
|
|
||
| const LIMITED_VIEW_SHOW_COUNT = 3; | ||
|
|
||
| export default class UserInfoSharedRooms extends React.PureComponent<IProps, IState> { | ||
|
|
||
| constructor(props: IProps) { | ||
| super(props); | ||
|
|
||
| this.state = { | ||
| error: false, | ||
| showAll: false, | ||
| }; | ||
| } | ||
|
|
||
| componentDidMount() { | ||
| return this.componentDidUpdate(); | ||
| } | ||
|
|
||
| async componentDidUpdate(prevProps?: IProps) { | ||
| if (prevProps && prevProps.userId === this.props.userId) { | ||
| // Nothing to update. | ||
| return; | ||
| } | ||
|
|
||
| // Reset because this is a new user | ||
| this.setState({ | ||
| error: false, | ||
| showAll: false, | ||
| roomIds: undefined, | ||
| }); | ||
|
|
||
| try { | ||
| const roomIds = await MatrixClientPeg.get()._unstable_getSharedRooms(this.props.userId); | ||
| this.setState({ | ||
| roomIds, | ||
| }); | ||
| } catch (ex) { | ||
| console.log(`Failed to get shared rooms for ${this.props.userId}`, ex); | ||
| this.setState({ error: true }); | ||
| } | ||
| } | ||
|
|
||
| private onShowMoreClick() { | ||
| console.log("Showing more"); | ||
| this.setState({ | ||
| showAll: true, | ||
| }); | ||
| } | ||
|
|
||
| private renderRoomTile(room) { | ||
| // If the room cannot be found, hide it. | ||
| if (!room) { | ||
| return null; | ||
| } | ||
|
|
||
| // If the room has been upgraded, hide it. | ||
| const tombstone = room.currentState.getStateEvents("m.room.tombstone", ""); | ||
| if (tombstone) { | ||
| return null; | ||
| } | ||
|
|
||
| if (this.props.compact) { | ||
| // XXX: This is inefficent as we only render COMPACT_VIEW_SHOW_COUNT rooms at a time, the other pills are wasted. | ||
| const alias = room.getCanonicalAlias(); | ||
| if (!alias) { | ||
| // Without an alias we get ugly room_ids, hide it. | ||
| return null; | ||
| } | ||
| return <a href={`#/room/${alias}`}><Pill | ||
| key={room.roomId} | ||
| type={Pill.TYPE_ROOM_MENTION} | ||
| room={room} | ||
| url={new SpecPermalinkConstructor().forRoom(alias)} | ||
| inMessage={false} | ||
| shouldShowPillAvatar={true} | ||
| isSelected={false} | ||
| /></a>; | ||
| } | ||
|
|
||
| return <li key={room.roomId}> | ||
| <UserInfoRoomTile room={room}/> | ||
| </li>; | ||
| } | ||
|
|
||
| private renderRoomTiles() { | ||
| const peg = MatrixClientPeg.get(); | ||
| const orderedActiveRooms = mostRecentActivityFirst(this.state.roomIds.map( | ||
| (roomId) => peg.getRoom(roomId) | ||
| )); | ||
|
|
||
| // We must remove the null values in order for the slice to work in render() | ||
| return orderedActiveRooms.map((room) => this.renderRoomTile(room)).filter((tile => tile !== null)); | ||
| } | ||
|
|
||
| render(): React.ReactNode { | ||
| let content; | ||
| let realCount = 0; | ||
|
|
||
| if (this.state.roomIds && this.state.roomIds.length > 0) { | ||
| content = this.renderRoomTiles(); | ||
| realCount = content.length; | ||
| if (!this.state.showAll) { | ||
| content = content.slice(0, LIMITED_VIEW_SHOW_COUNT); | ||
| } | ||
| } else if (this.state.roomIds) { | ||
| content = <p> {_t("You share no rooms in common with this user.")} </p>; | ||
| } else if (this.state.error) { | ||
| content = <p> {_t("There was an error fetching shared rooms with this user.")} </p>; | ||
| } else { | ||
| // We're still loading | ||
| content = <Spinner/>; | ||
| } | ||
|
|
||
| // Compact view: Show as a single line. | ||
| if (this.props.compact && content.length) { | ||
| if (realCount <= content.length) { | ||
| return <p> {_t("You are both participating in <rooms></rooms>", {}, {rooms: content})} </p>; | ||
| } else { | ||
| return <p> {_t("You are both participating in <rooms></rooms> and %(hidden)s more", { | ||
| hidden: realCount - content.length, | ||
| }, { | ||
| rooms: content | ||
| })}</p>; | ||
| } | ||
| } else if (this.props.compact) { | ||
| return content; | ||
| } | ||
|
|
||
| const canShowMore = !this.state.showAll && realCount > LIMITED_VIEW_SHOW_COUNT; | ||
| // Normal view: Show as a list with a header | ||
| return <div className="mx_UserInfoSharedRooms mx_UserInfo_container"> | ||
| <h3>{ _t("Shared Rooms") }</h3> | ||
| <ul> | ||
| {content} | ||
| </ul> | ||
| { canShowMore && <AccessibleButton className="mx_UserInfo_field" onClick={() => this.onShowMoreClick()}> | ||
| { _t("Show %(count)s more", { count: realCount - content.length}) } | ||
| </AccessibleButton> } | ||
| </div>; | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.