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

Commit

Permalink
Make join button on space hierarchy action in the background (#7041)
Browse files Browse the repository at this point in the history
  • Loading branch information
t3chguy authored Oct 27, 2021
1 parent 43cbb94 commit 27e1636
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 61 deletions.
5 changes: 5 additions & 0 deletions res/css/structures/_SpaceHierarchy.scss
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,11 @@ limitations under the License.
visibility: visible;
}
}

&.mx_SpaceHierarchy_joining .mx_AccessibleButton {
visibility: visible;
padding: 4px 18px;
}
}

li.mx_SpaceHierarchy_roomTileWrapper {
Expand Down
88 changes: 57 additions & 31 deletions src/components/structures/SpaceHierarchy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,15 @@ import { getDisplayAliasForRoom } from "./RoomDirectory";
import MatrixClientContext from "../../contexts/MatrixClientContext";
import { useEventEmitterState } from "../../hooks/useEventEmitter";
import { IOOBData } from "../../stores/ThreepidInviteStore";
import { awaitRoomDownSync } from "../../utils/RoomUpgrade";
import RoomViewStore from "../../stores/RoomViewStore";

interface IProps {
space: Room;
initialText?: string;
additionalButtons?: ReactNode;
showRoom(
cli: MatrixClient,
hierarchy: RoomHierarchy,
roomId: string,
autoJoin?: boolean,
roomType?: RoomType,
): void;
showRoom(cli: MatrixClient, hierarchy: RoomHierarchy, roomId: string, roomType?: RoomType): void;
joinRoom(cli: MatrixClient, hierarchy: RoomHierarchy, roomId: string): void;
}

interface ITileProps {
Expand All @@ -80,7 +77,8 @@ interface ITileProps {
selected?: boolean;
numChildRooms?: number;
hasPermissions?: boolean;
onViewRoomClick(autoJoin: boolean, roomType: RoomType): void;
onViewRoomClick(): void;
onJoinRoomClick(): void;
onToggleClick?(): void;
}

Expand All @@ -91,31 +89,50 @@ const Tile: React.FC<ITileProps> = ({
hasPermissions,
onToggleClick,
onViewRoomClick,
onJoinRoomClick,
numChildRooms,
children,
}) => {
const cli = useContext(MatrixClientContext);
const joinedRoom = cli.getRoom(room.room_id)?.getMyMembership() === "join" ? cli.getRoom(room.room_id) : null;
const [joinedRoom, setJoinedRoom] = useState<Room>(() => {
const cliRoom = cli.getRoom(room.room_id);
return cliRoom?.getMyMembership() === "join" ? cliRoom : null;
});
const joinedRoomName = useEventEmitterState(joinedRoom, "Room.name", room => room?.name);
const name = joinedRoomName || room.name || room.canonical_alias || room.aliases?.[0]
|| (room.room_type === RoomType.Space ? _t("Unnamed Space") : _t("Unnamed Room"));

const [showChildren, toggleShowChildren] = useStateToggle(true);
const [onFocus, isActive, ref] = useRovingTabIndex();
const [busy, setBusy] = useState(false);

const onPreviewClick = (ev: ButtonEvent) => {
ev.preventDefault();
ev.stopPropagation();
onViewRoomClick(false, room.room_type as RoomType);
onViewRoomClick();
};
const onJoinClick = (ev: ButtonEvent) => {
const onJoinClick = async (ev: ButtonEvent) => {
setBusy(true);
ev.preventDefault();
ev.stopPropagation();
onViewRoomClick(true, room.room_type as RoomType);
onJoinRoomClick();
setJoinedRoom(await awaitRoomDownSync(cli, room.room_id));
setBusy(false);
};

let button;
if (joinedRoom) {
if (busy) {
button = <AccessibleTooltipButton
disabled={true}
onClick={onJoinClick}
kind="primary_outline"
onFocus={onFocus}
tabIndex={isActive ? 0 : -1}
title={_t("Joining")}
>
<Spinner w={24} h={24} />
</AccessibleTooltipButton>;
} else if (joinedRoom) {
button = <AccessibleButton
onClick={onPreviewClick}
kind="primary_outline"
Expand Down Expand Up @@ -282,6 +299,7 @@ const Tile: React.FC<ITileProps> = ({
<AccessibleButton
className={classNames("mx_SpaceHierarchy_roomTile", {
mx_SpaceHierarchy_subspace: room.room_type === RoomType.Space,
mx_SpaceHierarchy_joining: busy,
})}
onClick={(hasPermissions && onToggleClick) ? onToggleClick : onPreviewClick}
onKeyDown={onKeyDown}
Expand All @@ -296,13 +314,7 @@ const Tile: React.FC<ITileProps> = ({
</li>;
};

export const showRoom = (
cli: MatrixClient,
hierarchy: RoomHierarchy,
roomId: string,
autoJoin = false,
roomType?: RoomType,
) => {
export const showRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: string, roomType?: RoomType): void => {
const room = hierarchy.roomMap.get(roomId);

// Don't let the user view a room they won't be able to either peek or join:
Expand All @@ -317,7 +329,6 @@ export const showRoom = (
const roomAlias = getDisplayAliasForRoom(room) || undefined;
dis.dispatch({
action: "view_room",
auto_join: autoJoin,
should_peek: true,
_type: "room_directory", // instrumentation
room_alias: roomAlias,
Expand All @@ -332,13 +343,29 @@ export const showRoom = (
});
};

export const joinRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: string): void => {
// Don't let the user view a room they won't be able to either peek or join:
// fail earlier so they don't have to click back to the directory.
if (cli.isGuest()) {
dis.dispatch({ action: "require_registration" });
return;
}

cli.joinRoom(roomId, {
viaServers: Array.from(hierarchy.viaMap.get(roomId) || []),
}).catch(err => {
RoomViewStore.showJoinRoomError(err, roomId);
});
};

interface IHierarchyLevelProps {
root: IHierarchyRoom;
roomSet: Set<IHierarchyRoom>;
hierarchy: RoomHierarchy;
parents: Set<string>;
selectedMap?: Map<string, Set<string>>;
onViewRoomClick(roomId: string, autoJoin: boolean, roomType?: RoomType): void;
onViewRoomClick(roomId: string, roomType?: RoomType): void;
onJoinRoomClick(roomId: string): void;
onToggleClick?(parentId: string, childId: string): void;
}

Expand Down Expand Up @@ -373,6 +400,7 @@ export const HierarchyLevel = ({
parents,
selectedMap,
onViewRoomClick,
onJoinRoomClick,
onToggleClick,
}: IHierarchyLevelProps) => {
const cli = useContext(MatrixClientContext);
Expand Down Expand Up @@ -400,9 +428,8 @@ export const HierarchyLevel = ({
room={room}
suggested={hierarchy.isSuggested(root.room_id, room.room_id)}
selected={selectedMap?.get(root.room_id)?.has(room.room_id)}
onViewRoomClick={(autoJoin, roomType) => {
onViewRoomClick(room.room_id, autoJoin, roomType);
}}
onViewRoomClick={() => onViewRoomClick(room.room_id, room.room_type as RoomType)}
onJoinRoomClick={() => onJoinRoomClick(room.room_id)}
hasPermissions={hasPermissions}
onToggleClick={onToggleClick ? () => onToggleClick(root.room_id, room.room_id) : undefined}
/>
Expand All @@ -420,9 +447,8 @@ export const HierarchyLevel = ({
}).length}
suggested={hierarchy.isSuggested(root.room_id, space.room_id)}
selected={selectedMap?.get(root.room_id)?.has(space.room_id)}
onViewRoomClick={(autoJoin, roomType) => {
onViewRoomClick(space.room_id, autoJoin, roomType);
}}
onViewRoomClick={() => onViewRoomClick(space.room_id, RoomType.Space)}
onJoinRoomClick={() => onJoinRoomClick(space.room_id)}
hasPermissions={hasPermissions}
onToggleClick={onToggleClick ? () => onToggleClick(root.room_id, space.room_id) : undefined}
>
Expand All @@ -433,6 +459,7 @@ export const HierarchyLevel = ({
parents={newParents}
selectedMap={selectedMap}
onViewRoomClick={onViewRoomClick}
onJoinRoomClick={onJoinRoomClick}
onToggleClick={onToggleClick}
/>
</Tile>
Expand Down Expand Up @@ -696,9 +723,8 @@ const SpaceHierarchy = ({
parents={new Set()}
selectedMap={selected}
onToggleClick={hasPermissions ? onToggleClick : undefined}
onViewRoomClick={(roomId, autoJoin, roomType) => {
showRoom(cli, hierarchy, roomId, autoJoin, roomType);
}}
onViewRoomClick={(roomId, roomType) => showRoom(cli, hierarchy, roomId, roomType)}
onJoinRoomClick={(roomId) => joinRoom(cli, hierarchy, roomId)}
/>
</>;
} else if (!hierarchy.canLoadMore) {
Expand Down
4 changes: 2 additions & 2 deletions src/components/structures/SpaceRoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ import {
showSpaceInvite,
showSpaceSettings,
} from "../../utils/space";
import SpaceHierarchy, { showRoom } from "./SpaceHierarchy";
import SpaceHierarchy, { joinRoom, showRoom } from "./SpaceHierarchy";
import MemberAvatar from "../views/avatars/MemberAvatar";
import SpaceStore from "../../stores/SpaceStore";
import FacePile from "../views/elements/FacePile";
Expand Down Expand Up @@ -508,7 +508,7 @@ const SpaceLanding = ({ space }: { space: Room }) => {
) }
</RoomTopic>

<SpaceHierarchy space={space} showRoom={showRoom} additionalButtons={addRoomButton} />
<SpaceHierarchy space={space} showRoom={showRoom} joinRoom={joinRoom} additionalButtons={addRoomButton} />
</div>;
};

Expand Down
4 changes: 2 additions & 2 deletions src/components/views/avatars/RoomAvatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
import React, { ComponentProps } from 'react';
import { Room } from 'matrix-js-sdk/src/models/room';
import { ResizeMethod } from 'matrix-js-sdk/src/@types/partials';
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
import classNames from "classnames";

import BaseAvatar from './BaseAvatar';
Expand Down Expand Up @@ -83,8 +84,7 @@ export default class RoomAvatar extends React.Component<IProps, IState> {
};
}

// TODO: type when js-sdk has types
private onRoomStateEvents = (ev: any) => {
private onRoomStateEvents = (ev: MatrixEvent) => {
if (!this.props.room ||
ev.getRoomId() !== this.props.room.roomId ||
ev.getType() !== 'm.room.avatar'
Expand Down
1 change: 1 addition & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2930,6 +2930,7 @@
"Drop file here to upload": "Drop file here to upload",
"You have %(count)s unread notifications in a prior version of this room.|other": "You have %(count)s unread notifications in a prior version of this room.",
"You have %(count)s unread notifications in a prior version of this room.|one": "You have %(count)s unread notification in a prior version of this room.",
"Joining": "Joining",
"You don't have permission": "You don't have permission",
"Joined": "Joined",
"This room is suggested as a good one to join": "This room is suggested as a good one to join",
Expand Down
19 changes: 11 additions & 8 deletions src/stores/RoomViewStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ class RoomViewStore extends Store<ActionPayload> {
}
}

private getInvitingUserId(roomId: string): string {
private static getInvitingUserId(roomId: string): string {
const cli = MatrixClientPeg.get();
const room = cli.getRoom(roomId);
if (room && room.getMyMembership() === "invite") {
Expand All @@ -318,12 +318,7 @@ class RoomViewStore extends Store<ActionPayload> {
}
}

private joinRoomError(payload: ActionPayload) {
this.setState({
joining: false,
joinError: payload.err,
});
const err = payload.err;
public showJoinRoomError(err: Error | MatrixError, roomId: string) {
let msg = err.message ? err.message : JSON.stringify(err);
logger.log("Failed to join room:", msg);

Expand All @@ -335,7 +330,7 @@ class RoomViewStore extends Store<ActionPayload> {
{ _t("Please contact your homeserver administrator.") }
</div>;
} else if (err.httpStatus === 404) {
const invitingUserId = this.getInvitingUserId(this.state.roomId);
const invitingUserId = RoomViewStore.getInvitingUserId(roomId);
// only provide a better error message for invites
if (invitingUserId) {
// if the inviting user is on the same HS, there can only be one cause: they left.
Expand All @@ -355,6 +350,14 @@ class RoomViewStore extends Store<ActionPayload> {
});
}

private joinRoomError(payload: ActionPayload) {
this.setState({
joining: false,
joinError: payload.err,
});
this.showJoinRoomError(payload.err, this.state.roomId);
}

public reset() {
this.state = Object.assign({}, INITIAL_STATE);
}
Expand Down
37 changes: 19 additions & 18 deletions src/utils/RoomUpgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import SpaceStore from "../stores/SpaceStore";
import Spinner from "../components/views/elements/Spinner";

import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClient } from "matrix-js-sdk/src/client";

interface IProgress {
roomUpgraded: boolean;
Expand All @@ -35,6 +36,23 @@ interface IProgress {
updateSpacesTotal: number;
}

export async function awaitRoomDownSync(cli: MatrixClient, roomId: string): Promise<Room> {
const room = cli.getRoom(roomId);
if (room) return room; // already have the room

return new Promise<Room>(resolve => {
// We have to wait for the js-sdk to give us the room back so
// we can more effectively abuse the MultiInviter behaviour
// which heavily relies on the Room object being available.
const checkForRoomFn = (room: Room) => {
if (room.roomId !== roomId) return;
resolve(room);
cli.off("Room", checkForRoomFn);
};
cli.on("Room", checkForRoomFn);
});
}

export async function upgradeRoom(
room: Room,
targetVersion: string,
Expand Down Expand Up @@ -93,24 +111,7 @@ export async function upgradeRoom(
progressCallback?.(progress);

if (awaitRoom || inviteUsers) {
await new Promise<void>(resolve => {
// already have the room
if (room.client.getRoom(newRoomId)) {
resolve();
return;
}

// We have to wait for the js-sdk to give us the room back so
// we can more effectively abuse the MultiInviter behaviour
// which heavily relies on the Room object being available.
const checkForRoomFn = (newRoom: Room) => {
if (newRoom.roomId !== newRoomId) return;
resolve();
cli.off("Room", checkForRoomFn);
};
cli.on("Room", checkForRoomFn);
});

await awaitRoomDownSync(room.client, newRoomId);
progress.roomSynced = true;
progressCallback?.(progress);
}
Expand Down

0 comments on commit 27e1636

Please sign in to comment.