96 lines
3.4 KiB
TypeScript
96 lines
3.4 KiB
TypeScript
/*
|
|
Copyright 2024 New Vector Ltd.
|
|
Copyright 2023 The Matrix.org Foundation C.I.C.
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
Please see LICENSE files in the repository root for full details.
|
|
*/
|
|
|
|
import { Room } from "matrix-js-sdk/src/matrix";
|
|
import { useEffect, useState } from "react";
|
|
|
|
import { PillType } from "../components/views/elements/Pill";
|
|
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
import { PermalinkParts } from "../utils/permalinks/PermalinkConstructor";
|
|
|
|
/**
|
|
* Tries to determine the initial room.
|
|
* Initial here means it should be possible to load the room without sending API requests.
|
|
* For an @room or a user mention it is the permalinkRoom.
|
|
* If the parse result contains a room Id or alias try to find it with {@link findRoom}.
|
|
* Otherwise returns null.
|
|
*
|
|
* @param type - Pill type
|
|
* @param permalinkRoom - Room in which the permalink is displayed.
|
|
* @param parseResult - Permalink parser result
|
|
* @returns Initial room or null if it cannot be determined.
|
|
*/
|
|
const determineInitialRoom = (
|
|
type: PillType | null,
|
|
parseResult: PermalinkParts | null,
|
|
permalinkRoom: Room | undefined,
|
|
): Room | null => {
|
|
if (type === PillType.AtRoomMention && permalinkRoom) return permalinkRoom;
|
|
|
|
if (type === PillType.UserMention && permalinkRoom) {
|
|
return permalinkRoom;
|
|
}
|
|
|
|
if (parseResult?.roomIdOrAlias) {
|
|
const room = findRoom(parseResult.roomIdOrAlias);
|
|
if (room) return room;
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Tries to find a room by room Id or searching all rooms for an alias.
|
|
*
|
|
* @param roomIdOrAlias - Id or alias of the room to find.
|
|
* @returns Room if found, else null.
|
|
*/
|
|
const findRoom = (roomIdOrAlias: string): Room | null => {
|
|
const client = MatrixClientPeg.safeGet();
|
|
|
|
return roomIdOrAlias[0] === "#"
|
|
? (client.getRooms().find((r) => {
|
|
return r.getCanonicalAlias() === roomIdOrAlias || r.getAltAliases().includes(roomIdOrAlias);
|
|
}) ?? null)
|
|
: client.getRoom(roomIdOrAlias);
|
|
};
|
|
|
|
/**
|
|
* Hook to get the permalink target room:
|
|
*
|
|
* @param type - Permalink type
|
|
* @param parseResult - Permalink parse result
|
|
* @param permalinkRoom - Room in which the permalink is rendered
|
|
* @returns Returns the target room:
|
|
* - The permalinkRoom for an @room or user mention
|
|
* - The room of the parse result for a room mention
|
|
* - The room of the event for an event permalink
|
|
* - Null in other cases or if the room cannot be found
|
|
*/
|
|
export const usePermalinkTargetRoom = (
|
|
type: PillType | null,
|
|
parseResult: PermalinkParts | null,
|
|
permalinkRoom: Room | undefined,
|
|
): Room | null => {
|
|
// The listed permalink types require a room.
|
|
// If it cannot be initially determined, it will be looked up later by a memo hook.
|
|
const shouldLookUpRoom =
|
|
type && [PillType.RoomMention, PillType.EventInSameRoom, PillType.EventInOtherRoom, "space"].includes(type);
|
|
const initialRoom = determineInitialRoom(type, parseResult, permalinkRoom);
|
|
const [targetRoom, setTargetRoom] = useState<Room | null>(initialRoom);
|
|
|
|
useEffect(() => {
|
|
if (shouldLookUpRoom && !targetRoom && parseResult?.roomIdOrAlias) {
|
|
const newRoom = findRoom(parseResult.roomIdOrAlias);
|
|
setTargetRoom(newRoom);
|
|
}
|
|
}, [parseResult?.roomIdOrAlias, shouldLookUpRoom, targetRoom]);
|
|
|
|
return targetRoom;
|
|
};
|