56 lines
1.8 KiB
TypeScript
56 lines
1.8 KiB
TypeScript
|
|
import { EventStatus, IThreadBundledRelationship, MatrixEvent, RelationType } from 'matrix-js-sdk';
|
||
|
|
|
||
|
|
export type ThreadSummaryData = {
|
||
|
|
count: number;
|
||
|
|
latestTs: number | undefined;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Summary data for a thread root's "N replies" chip.
|
||
|
|
*
|
||
|
|
* Prefers the live {@link Thread} object when it exists (it reflects local
|
||
|
|
* echo + pagination), otherwise falls back to the server-aggregated bundle
|
||
|
|
* (`unsigned['m.relations']['m.thread']`) so the chip renders before any
|
||
|
|
* Thread object has been created. Returns `undefined` when the root has no
|
||
|
|
* thread at all.
|
||
|
|
*/
|
||
|
|
export const getThreadSummary = (rootEvent: MatrixEvent): ThreadSummaryData | undefined => {
|
||
|
|
const thread = rootEvent.getThread();
|
||
|
|
if (thread) {
|
||
|
|
const lastReply = thread.lastReply();
|
||
|
|
return {
|
||
|
|
count: thread.length,
|
||
|
|
latestTs: lastReply?.getTs(),
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
const bundle = rootEvent.getServerAggregatedRelation<IThreadBundledRelationship>(
|
||
|
|
RelationType.Thread,
|
||
|
|
);
|
||
|
|
if (bundle) {
|
||
|
|
return {
|
||
|
|
count: bundle.count,
|
||
|
|
latestTs: bundle.latest_event?.origin_server_ts,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
return undefined;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* True when `event` is a still-in-flight (local echo) reply belonging to the
|
||
|
|
* given thread root. Used to render the pending strip, since pending thread
|
||
|
|
* sends never enter the thread's timelineSet.
|
||
|
|
*/
|
||
|
|
export const isPendingThreadReply = (event: MatrixEvent, threadRootId: string): boolean => {
|
||
|
|
const { status } = event;
|
||
|
|
if (status !== EventStatus.SENDING && status !== EventStatus.NOT_SENT) return false;
|
||
|
|
|
||
|
|
// Prefer the SDK's resolved thread root id; fall back to the raw relation
|
||
|
|
// content for events the SDK hasn't associated with a thread yet.
|
||
|
|
if (event.threadRootId === threadRootId) return true;
|
||
|
|
|
||
|
|
const relation = event.getRelation();
|
||
|
|
return relation?.rel_type === RelationType.Thread && relation.event_id === threadRootId;
|
||
|
|
};
|