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

Show rooms in common with another user #4897

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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 Jul 5, 2020
e901aae
Fix lint
Half-Shot Jul 5, 2020
d06b90b
Add strings
Half-Shot Jul 5, 2020
f6d2e49
Add "compact" view for SharedRooms view
Half-Shot Jul 5, 2020
9aed1c0
Show shared rooms to users when being invited
Half-Shot Jul 5, 2020
db2b642
Lint
Half-Shot Jul 5, 2020
e6d2c89
Typescriptify RoomListSorter
Half-Shot Jul 6, 2020
29ce381
Order by activity
Half-Shot Jul 6, 2020
23fe7d0
Limit to 3 rooms, but allow expansion
Half-Shot Jul 6, 2020
a617eb5
Fix lint
Half-Shot Jul 6, 2020
a3a9f19
Show count more
Half-Shot Jul 6, 2020
81c68aa
Update if a new user is selected
Half-Shot Jul 6, 2020
b3a7215
Merge remote-tracking branch 'origin/develop' into hs/shared-rooms
Half-Shot Aug 18, 2020
169a66c
Add UserInfoRoomTile
Half-Shot Aug 18, 2020
f9cfa60
Refactor to work with new room tiles
Half-Shot Aug 18, 2020
5473f63
Fix builds
Half-Shot Aug 18, 2020
f73f937
Fix feature code
Half-Shot Aug 20, 2020
76ab806
Merge branch 'develop' into hs/shared-rooms
Half-Shot Sep 7, 2020
30384ac
Apply suggestions from code review
Half-Shot Nov 20, 2020
7c828f4
Merge remote-tracking branch 'origin/develop' into hs/shared-rooms
Half-Shot Dec 14, 2020
f57dca7
Drop roomIds state
Half-Shot Dec 14, 2020
ba7ccbf
Tweaks
Half-Shot Dec 14, 2020
51a4371
Linting
Half-Shot Dec 14, 2020
b2a188f
Merge remote-tracking branch 'origin/develop' into hs/shared-rooms
Half-Shot Feb 16, 2021
deafdb8
Initial stab at rendering shared rooms in the side panel
Half-Shot Feb 16, 2021
fbcaaab
Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into…
t3chguy Jul 6, 2021
ec90183
Iterate PR
t3chguy Jul 6, 2021
135c2f7
Iterate PR some more
t3chguy Jul 6, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions res/css/_components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@
@import "./views/right_panel/_PinnedMessagesCard.scss";
@import "./views/right_panel/_RoomSummaryCard.scss";
@import "./views/right_panel/_UserInfo.scss";
@import "./views/right_panel/_UserInfoSharedRooms.scss";
@import "./views/right_panel/_VerificationPanel.scss";
@import "./views/right_panel/_WidgetCard.scss";
@import "./views/room_settings/_AliasSettings.scss";
Expand Down
79 changes: 40 additions & 39 deletions res/css/views/right_panel/_BaseCard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,46 @@ See the License for the specific language governing permissions and
limitations under the License.
*/


.mx_BaseCard_Button {
padding: 10px 38px 10px 12px;
margin: 0;
position: relative;
font-size: $font-13px;
height: 20px;
line-height: 20px;
border-radius: 8px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;

&:hover {
background-color: rgba(141, 151, 165, 0.1);
}

&::after {
content: '';
position: absolute;
top: 10px;
right: 6px;
height: 20px;
width: 20px;
mask-repeat: no-repeat;
mask-position: center;
background-color: $icon-button-color;
transform: rotate(270deg);
mask-size: 20px;
mask-image: url('$(res)/img/feather-customised/chevron-down.svg');
}

&.mx_AccessibleButton_disabled {
padding-right: 12px;
&::after {
content: unset;
}
}
}

.mx_BaseCard {
padding: 0 8px;
overflow: hidden;
Expand Down Expand Up @@ -97,45 +137,6 @@ limitations under the License.
font-size: $font-12px;
font-weight: 500;
}

.mx_BaseCard_Button {
padding: 10px 38px 10px 12px;
margin: 0;
position: relative;
font-size: $font-13px;
height: 20px;
line-height: 20px;
border-radius: 8px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;

&:hover {
background-color: rgba(141, 151, 165, 0.1);
}

&::after {
content: '';
position: absolute;
top: 10px;
right: 6px;
height: 20px;
width: 20px;
mask-repeat: no-repeat;
mask-position: center;
background-color: $icon-button-color;
transform: rotate(270deg);
mask-size: 20px;
mask-image: url('$(res)/img/feather-customised/chevron-down.svg');
}

&.mx_AccessibleButton_disabled {
padding-right: 12px;
&::after {
content: unset;
}
}
}
}

.mx_BaseCard_footer {
Expand Down
20 changes: 20 additions & 0 deletions res/css/views/right_panel/_UserInfoSharedRooms.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
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.
*/

.mx_SharedRoomList {
padding: 10px;
margin-top: 10px;
}
13 changes: 13 additions & 0 deletions src/components/structures/RightPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import MatrixClientContext from "../../contexts/MatrixClientContext";
import { Action } from "../../dispatcher/actions";
import RoomSummaryCard from "../views/right_panel/RoomSummaryCard";
import WidgetCard from "../views/right_panel/WidgetCard";
import SharedRoomList from "../views/right_panel/SharedRoomsList";
import { replaceableComponent } from "../../utils/replaceableComponent";
import SettingsStore from "../../settings/SettingsStore";
import { ActionPayload } from "../../dispatcher/payloads";
Expand Down Expand Up @@ -67,6 +68,7 @@ interface IState {
groupRoomId?: string;
groupId?: string;
event: MatrixEvent;
userId?: string;
}

@replaceableComponent("structures.RightPanel")
Expand Down Expand Up @@ -201,6 +203,11 @@ export default class RightPanel extends React.Component<IProps, IState> {
space: payload.space,
});
}
if (payload.action === Action.SetRightPanelPhase && payload.phase === RightPanelPhases.SharedRoomsList) {
this.setState({
userId: payload.userId,
});
}
};

private onClose = () => {
Expand Down Expand Up @@ -234,6 +241,8 @@ export default class RightPanel extends React.Component<IProps, IState> {
let panel = <div />;
const roomId = this.props.room ? this.props.room.roomId : undefined;

console.log(this.state, this.props);

switch (this.state.phase) {
case RightPanelPhases.RoomMemberList:
if (roomId) {
Expand All @@ -258,6 +267,10 @@ export default class RightPanel extends React.Component<IProps, IState> {
panel = <GroupRoomList groupId={this.props.groupId} key={this.props.groupId} />;
break;

case RightPanelPhases.SharedRoomsList:
panel = <SharedRoomList onClose={this.onClose} userId={this.state.userId} key={this.state.userId} />;
break;

case RightPanelPhases.RoomMemberInfo:
case RightPanelPhases.SpaceMemberInfo:
case RightPanelPhases.EncryptionPanel:
Expand Down
88 changes: 88 additions & 0 deletions src/components/views/elements/UserInfoRoomTile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 New Vector Ltd
Copyright 2018 Michael Telatynski <7t3chguy@gmail.com>
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 DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
import dis from '../../../dispatcher/dispatcher';
import { Key } from "../../../Keyboard";

interface IProps {
room: Room;
}

interface IState {
selected: boolean;
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,
};
}

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", {
"mx_RoomTile_selected": this.state.selected,
});

const roomAvatar = <DecoratedRoomAvatar room={this.props.room} avatarSize={32} displayBadge={false} />;

const name = this.props.room.name;
const nameContainer = (
<div className="mx_RoomTile_nameContainer">
<div title={name} className={"mx_RoomTile_name"} tabIndex={-1} dir="auto">
{name}
</div>
</div>
);

return (
<AccessibleButton
className={classes}
onClick={this.onTileClick}
role="treeitem"
aria-label={name}
aria-selected={this.state.selected}
>
{ roomAvatar }
{ nameContainer }
</AccessibleButton>
);
}
}
90 changes: 90 additions & 0 deletions src/components/views/right_panel/SharedRoomsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
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 from 'react';
import { RecentAlgorithm } from '../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm';
import { DefaultTagID } from '../../../stores/room-list/models';
import BaseCard from './BaseCard';
import UserInfoSharedRooms from './UserInfoSharedRooms';
import { Room } from "matrix-js-sdk/src/models/room";
import Spinner from "../elements/Spinner";
import TruncatedList from "../elements/TruncatedList";
import UserInfoRoomTile from '../elements/UserInfoRoomTile';
import { _t } from "../../../languageHandler";

interface IProps {
onClose: () => void;
userId: string;
}

interface IState {
rooms?: Room[];
error: boolean;
}

const TRUNCATE_AT = 30;

/*
* Component which shows the global notification list using a TimelinePanel
*/
export default class SharedRoomList extends React.PureComponent<IProps, IState> {
algorithm: RecentAlgorithm;
constructor(props: IProps) {
super(props);
this.state = {
error: false,
};
this.algorithm = new RecentAlgorithm();
}

async componentDidMount() {
try {
const rooms = await UserInfoSharedRooms.getSharedRoomsForUser(this.props.userId);
const sortedRooms = await this.algorithm.sortRooms(rooms, DefaultTagID.Untagged);
this.setState({ rooms: sortedRooms });
} catch (ex) {
console.log("Error fetching shared rooms for user", ex);
this.setState({ error: true });
}
}

private makeRoomTiles() {
return this.state.rooms.map(r => <UserInfoRoomTile key={r.roomId} room={r} />);
}

private renderContent() {
if (this.state.error) {
// In theory this shouldn't happen, because the button for this view
// validates that the client can fetch shared rooms for this user.
return <p>{ _t("Could not fetch shared rooms for user.") }</p>;
}
if (!this.state.rooms) {
return <Spinner />;
}
return <TruncatedList className="mx_SharedRoomList" truncateAt={TRUNCATE_AT}>
{ this.makeRoomTiles() }
</TruncatedList>;
}

render() {
return <BaseCard
// We don't know the right refire args for this :(
// previousPhase={RightPanelPhases.RoomMemberInfo}
onClose={this.props.onClose}>
{ this.renderContent() }
</BaseCard>;
}
}
12 changes: 12 additions & 0 deletions src/components/views/right_panel/UserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import EncryptionPanel from "./EncryptionPanel";
import { useAsyncMemo } from '../../../hooks/useAsyncMemo';
import { legacyVerifyUser, verifyDevice, verifyUser } from '../../../verification';
import { Action } from "../../../dispatcher/actions";
import UserInfoSharedRooms from "./UserInfoSharedRooms";
import { UserTab } from "../dialogs/UserSettingsDialog";
import { useIsEncrypted } from "../../../hooks/useIsEncrypted";
import BaseCard from "./BaseCard";
Expand Down Expand Up @@ -1342,6 +1343,8 @@ const BasicUserInfo: React.FC<{
const canVerify = cryptoEnabled && homeserverSupportsCrossSigning && !userVerified && !isMe &&
devices && devices.length > 0;

const isSharedRoomsFeatureEnabled = SettingsStore.getValue("feature_show_shared_rooms");

const setUpdating = (updating) => {
setPendingUpdateCount(count => count + (updating ? 1 : -1));
};
Expand Down Expand Up @@ -1397,10 +1400,19 @@ const BasicUserInfo: React.FC<{
</div>
);

let sharedRooms = null;
if (isSharedRoomsFeatureEnabled && !isMe) {
sharedRooms = <div className="mx_UserInfo_container">
<h3>{ _t("Shared Rooms") }</h3>
<UserInfoSharedRooms userId={member.userId} />
</div>;
}

return <React.Fragment>
{ memberDetails }

{ securitySection }
{ sharedRooms }
<UserOptionsSection
canInvite={roomPermissions.canInvite}
isIgnored={isIgnored}
Expand Down
Loading