97 lines
3.3 KiB
TypeScript
97 lines
3.3 KiB
TypeScript
/*
|
|||
|
|
Copyright 2026 Element Creations Ltd.
|
||
|
|
|
||
|
|
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 { type MatrixEvent, type Thread } from "matrix-js-sdk/src/matrix";
|
||
|
|
|
||
|
|
import { TimelineRenderingType } from "../../../../contexts/RoomContext";
|
||
|
|
|
||
|
|
/** Minimal room surface used to look up a thread for an event. */
|
||
|
|
export interface EventTileThreadLookup {
|
||
|
|
/** Finds the thread associated with an event. */
|
||
|
|
findThreadForEvent(mxEvent: MatrixEvent): Thread | null | undefined;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Search thread-info rendering kind. */
|
||
|
|
export type SearchThreadInfoKind = "none" | "text" | "link";
|
||
|
|
|
||
|
|
/** Search timeline thread-info display state. */
|
||
|
|
export interface EventTileSearchThreadInfo {
|
||
|
|
/** Kind of search thread info to render. */
|
||
|
|
kind: SearchThreadInfoKind;
|
||
|
|
/** Link target when rendering linked thread info. */
|
||
|
|
href?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Inputs for deriving EventTile thread display state. */
|
||
|
|
export interface EventTileThreadStateInput {
|
||
|
|
/** Matrix event rendered by the tile. */
|
||
|
|
mxEvent: MatrixEvent;
|
||
|
|
/** Thread associated with the event, when available. */
|
||
|
|
thread: Thread | null;
|
||
|
|
/** Current timeline rendering mode. */
|
||
|
|
timelineRenderingType: TimelineRenderingType;
|
||
|
|
/** Optional search-result link for thread info. */
|
||
|
|
highlightLink?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** EventTile thread display state. */
|
||
|
|
export interface EventTileThreadState {
|
||
|
|
/** Thread associated with the event, when available. */
|
||
|
|
thread: Thread | null;
|
||
|
|
/** Whether EventTile should render the main thread summary. */
|
||
|
|
shouldShowThreadSummary: boolean;
|
||
|
|
/** Whether EventTile should render the thread panel reply summary. */
|
||
|
|
shouldShowThreadPanelSummary: boolean;
|
||
|
|
/** Timestamp of the latest thread reply, when available. */
|
||
|
|
threadReplyEventTs?: number;
|
||
|
|
/** Search timeline thread-info display state. */
|
||
|
|
searchThreadInfo: EventTileSearchThreadInfo;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Finds the thread associated with an event.
|
||
|
|
*
|
||
|
|
* Accessing the thread through the room covers a race where the event has not
|
||
|
|
* discovered its thread yet during sync.
|
||
|
|
*/
|
||
|
|
export function getEventTileThread(mxEvent: MatrixEvent, room?: EventTileThreadLookup | null): Thread | null {
|
||
|
|
return mxEvent.getThread() ?? room?.findThreadForEvent(mxEvent) ?? null;
|
||
|
|
}
|
||
|
|
|
||
|
|
function getSearchThreadInfo(shouldShowSearchThreadInfo: boolean, highlightLink?: string): EventTileSearchThreadInfo {
|
||
|
|
if (!shouldShowSearchThreadInfo) {
|
||
|
|
return { kind: "none" };
|
||
|
|
}
|
||
|
|
|
||
|
|
if (highlightLink) {
|
||
|
|
return { kind: "link", href: highlightLink };
|
||
|
|
}
|
||
|
|
|
||
|
|
return { kind: "text" };
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Derives thread display state for EventTile. */
|
||
|
|
export function getEventTileThreadState({
|
||
|
|
mxEvent,
|
||
|
|
thread,
|
||
|
|
timelineRenderingType,
|
||
|
|
highlightLink,
|
||
|
|
}: EventTileThreadStateInput): EventTileThreadState {
|
||
|
|
const shouldShowThreadSummary = !!thread && thread.id === mxEvent.getId();
|
||
|
|
const shouldShowSearchThreadInfo =
|
||
|
|
!shouldShowThreadSummary && timelineRenderingType === TimelineRenderingType.Search && !!mxEvent.threadRootId;
|
||
|
|
const searchThreadInfo = getSearchThreadInfo(shouldShowSearchThreadInfo, highlightLink);
|
||
|
|
|
||
|
|
return {
|
||
|
|
thread,
|
||
|
|
shouldShowThreadSummary,
|
||
|
|
shouldShowThreadPanelSummary: !!thread,
|
||
|
|
threadReplyEventTs: thread?.replyToEvent?.getTs(),
|
||
|
|
searchThreadInfo,
|
||
|
|
};
|
||
|
|
}
|