Pillify event permalinks (#10392)
This commit is contained in:
@@ -14,16 +14,18 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { MatrixEvent, Room, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { Room, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { ButtonEvent } from "../components/views/elements/AccessibleButton";
|
||||
import { PillType } from "../components/views/elements/Pill";
|
||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||
import { parsePermalink } from "../utils/permalinks/Permalinks";
|
||||
import dis from "../dispatcher/dispatcher";
|
||||
import { Action } from "../dispatcher/actions";
|
||||
import { PermalinkParts } from "../utils/permalinks/PermalinkConstructor";
|
||||
import { _t } from "../languageHandler";
|
||||
import { usePermalinkTargetRoom } from "./usePermalinkTargetRoom";
|
||||
import { usePermalinkEvent } from "./usePermalinkEvent";
|
||||
import { usePermalinkMember } from "./usePermalinkMember";
|
||||
|
||||
interface Args {
|
||||
/** Room in which the permalink should be displayed. */
|
||||
@@ -71,97 +73,77 @@ interface HookResult {
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to retrieve all information to display a permalink.
|
||||
* Tries to determine the pill type.
|
||||
*
|
||||
* If forcedType is present it will be returned.
|
||||
* If the parse result contains a room Id or alias and an event Id:
|
||||
* - Type is EventInSameRoom if the permalink room Id or alias equals the parsed room Id or alias
|
||||
* - Type is EventInOtherRoom if the permalink room Id or alias not equals the parsed room Id or alias
|
||||
* If the parse result contains a primary entity Id it will try to detect the type from it.
|
||||
* Otherwise returns null.
|
||||
*
|
||||
* @param forcedType - Forced pill type. Will be used if present and short-circuits all othe conditions.
|
||||
* @param parseResult - Permalink parser result
|
||||
* @param permalinkRoom - Room in which the permalink is displayed.
|
||||
* @returns Pill type or null if unable to determine.
|
||||
*/
|
||||
export const usePermalink: (args: Args) => HookResult = ({ room, type: argType, url }): HookResult => {
|
||||
const [member, setMember] = useState<RoomMember | null>(null);
|
||||
// room of the entity this pill points to
|
||||
const [targetRoom, setTargetRoom] = useState<Room | null>(room ?? null);
|
||||
const determineType = (
|
||||
forcedType: PillType | undefined,
|
||||
parseResult: PermalinkParts | null,
|
||||
permalinkRoom: Room | undefined,
|
||||
): PillType | null => {
|
||||
if (forcedType) return forcedType;
|
||||
|
||||
if (parseResult?.roomIdOrAlias && parseResult?.eventId) {
|
||||
if (parseResult.roomIdOrAlias === permalinkRoom?.roomId) {
|
||||
return PillType.EventInSameRoom;
|
||||
}
|
||||
|
||||
return PillType.EventInOtherRoom;
|
||||
}
|
||||
|
||||
if (parseResult?.primaryEntityId) {
|
||||
const prefix = parseResult.primaryEntityId[0] || "";
|
||||
return (
|
||||
{
|
||||
"@": PillType.UserMention,
|
||||
"#": PillType.RoomMention,
|
||||
"!": PillType.RoomMention,
|
||||
}[prefix] || null
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Can be used to retrieve all information needed to display a permalink.
|
||||
*/
|
||||
export const usePermalink: (args: Args) => HookResult = ({
|
||||
room: permalinkRoom,
|
||||
type: forcedType,
|
||||
url,
|
||||
}): HookResult => {
|
||||
let resourceId: string | null = null;
|
||||
let parseResult: PermalinkParts | null = null;
|
||||
|
||||
if (url) {
|
||||
const parseResult = parsePermalink(url);
|
||||
parseResult = parsePermalink(url);
|
||||
|
||||
if (parseResult?.primaryEntityId) {
|
||||
resourceId = parseResult.primaryEntityId;
|
||||
}
|
||||
}
|
||||
const prefix = resourceId ? resourceId[0] : "";
|
||||
const type =
|
||||
argType ||
|
||||
// try to detect the permalink type from the URL prefix
|
||||
{
|
||||
"@": PillType.UserMention,
|
||||
"#": PillType.RoomMention,
|
||||
"!": PillType.RoomMention,
|
||||
}[prefix] ||
|
||||
null;
|
||||
|
||||
const doProfileLookup = useCallback((userId: string, member: RoomMember): void => {
|
||||
MatrixClientPeg.get()
|
||||
.getProfileInfo(userId)
|
||||
.then((resp) => {
|
||||
const newMember = new RoomMember(member.roomId, userId);
|
||||
newMember.name = resp.displayname || userId;
|
||||
newMember.rawDisplayName = resp.displayname || userId;
|
||||
newMember.getMxcAvatarUrl();
|
||||
newMember.events.member = {
|
||||
getContent: () => {
|
||||
return { avatar_url: resp.avatar_url };
|
||||
},
|
||||
getDirectionalContent: function () {
|
||||
// eslint-disable-next-line
|
||||
return this.getContent();
|
||||
},
|
||||
} as MatrixEvent;
|
||||
setMember(newMember);
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.error("Could not retrieve profile data for " + userId + ":", err);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useMemo(() => {
|
||||
switch (type) {
|
||||
case PillType.UserMention:
|
||||
{
|
||||
if (resourceId) {
|
||||
let member = room?.getMember(resourceId) || null;
|
||||
setMember(member);
|
||||
|
||||
if (!member) {
|
||||
member = new RoomMember("", resourceId);
|
||||
doProfileLookup(resourceId, member);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PillType.RoomMention:
|
||||
{
|
||||
if (resourceId) {
|
||||
const newRoom =
|
||||
resourceId[0] === "#"
|
||||
? MatrixClientPeg.get()
|
||||
.getRooms()
|
||||
.find((r) => {
|
||||
return (
|
||||
r.getCanonicalAlias() === resourceId ||
|
||||
(resourceId && r.getAltAliases().includes(resourceId))
|
||||
);
|
||||
})
|
||||
: MatrixClientPeg.get().getRoom(resourceId);
|
||||
setTargetRoom(newRoom || null);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}, [doProfileLookup, type, resourceId, room]);
|
||||
const type = determineType(forcedType, parseResult, permalinkRoom);
|
||||
const targetRoom = usePermalinkTargetRoom(type, parseResult, permalinkRoom);
|
||||
const event = usePermalinkEvent(type, parseResult, targetRoom);
|
||||
const member = usePermalinkMember(type, parseResult, targetRoom, event);
|
||||
|
||||
let onClick: (e: ButtonEvent) => void = () => {};
|
||||
let text = resourceId;
|
||||
|
||||
if (type === PillType.AtRoomMention && room) {
|
||||
if (type === PillType.AtRoomMention && permalinkRoom) {
|
||||
text = "@room";
|
||||
} else if (type === PillType.UserMention && member) {
|
||||
text = member.name || resourceId;
|
||||
@@ -177,6 +159,10 @@ export const usePermalink: (args: Args) => HookResult = ({ room, type: argType,
|
||||
if (targetRoom) {
|
||||
text = targetRoom.name || resourceId;
|
||||
}
|
||||
} else if (type === PillType.EventInSameRoom) {
|
||||
text = member?.name || _t("User");
|
||||
} else if (type === PillType.EventInOtherRoom) {
|
||||
text = targetRoom?.name || _t("Room");
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user