1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-23 17:02:25 +03:00

Start using Namespaced value everywhere.

This commit is contained in:
Half-Shot
2025-10-13 11:25:33 +01:00
parent fd949fe486
commit 44404b6e24
7 changed files with 55 additions and 22 deletions

View File

@@ -315,6 +315,28 @@ export const UNSIGNED_THREAD_ID_FIELD = new UnstableValue("thread_id", "org.matr
*/
export const UNSIGNED_MEMBERSHIP_FIELD = new NamespacedValue("membership", "io.element.msc4115.membership");
/**
* https://github.com/matrix-org/matrix-spec-proposals/pull/4354
*
* @experimental
*/
export const STICKY_EVENT_FIELD = new NamespacedValue(null, "msc4354_sticky");
/**
* https://github.com/matrix-org/matrix-spec-proposals/pull/4354
*
* @experimental
*/
export const STICKY_EVENT_KEY_FIELD = new NamespacedValue(null, "msc4354_sticky_key");
/**
* https://github.com/matrix-org/matrix-spec-proposals/pull/4354
*
* @experimental
*/
export const STICKY_EVENT_DURATION_TTL_MS = new NamespacedValue(null, "msc4354_sticky_duration_ttl_ms")
/**
* Mapped type from event type to content type for all specified non-state room events.
*/

View File

@@ -143,6 +143,7 @@ import {
RoomCreateTypeField,
RoomType,
type StateEvents,
STICKY_EVENT_KEY_FIELD,
type TimelineEvents,
UNSTABLE_MSC3088_ENABLED,
UNSTABLE_MSC3088_PURPOSE,
@@ -3443,7 +3444,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
delayOpts: SendDelayedEventRequestOpts,
threadId: string | null,
eventType: K,
content: TimelineEvents[K] & { msc4354_sticky_key: string },
content: TimelineEvents[K] & { [STICKY_EVENT_KEY_FIELD.name]: string },
txnId?: string,
): Promise<SendDelayedEventResponse> {
if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) {

View File

@@ -20,7 +20,7 @@ import { type LivekitFocusSelection } from "./LivekitTransport.ts";
import { slotDescriptionToId, slotIdToDescription, type SlotDescription } from "./MatrixRTCSession.ts";
import type { RTCCallIntent, Transport } from "./types.ts";
import { type IContent, type MatrixEvent } from "../models/event.ts";
import { type RelationType } from "../@types/event.ts";
import { STICKY_EVENT_KEY_FIELD, type RelationType } from "../@types/event.ts";
import { logger } from "../logger.ts";
/**
@@ -47,7 +47,7 @@ export interface RtcMembershipData {
};
"rtc_transports": Transport[];
"versions": string[];
"msc4354_sticky_key"?: string;
[STICKY_EVENT_KEY_FIELD.name]?: string;
"sticky_key"?: string;
}

View File

@@ -31,6 +31,8 @@ import {
ToDeviceMessageId,
UNSIGNED_THREAD_ID_FIELD,
UNSIGNED_MEMBERSHIP_FIELD,
STICKY_EVENT_DURATION_TTL_MS,
STICKY_EVENT_FIELD,
} from "../@types/event.ts";
import { deepSortedObjectEntries, internaliseString } from "../utils.ts";
import { type RoomMember } from "./room-member.ts";
@@ -75,7 +77,7 @@ export interface IUnsigned {
"transaction_id"?: string;
"invite_room_state"?: StrippedState[];
"m.relations"?: Record<RelationType | string, any>; // No common pattern for aggregated relations
"msc4354_sticky_duration_ttl_ms"?: number;
[STICKY_EVENT_DURATION_TTL_MS.name]?: number;
[UNSIGNED_THREAD_ID_FIELD.name]?: string;
}
@@ -97,7 +99,7 @@ export interface IEvent {
membership?: Membership;
unsigned: IUnsigned;
redacts?: string;
msc4354_sticky?: { duration_ms: number };
[STICKY_EVENT_FIELD.name]?: { duration_ms: number };
}
export interface IAggregatedRelation {
@@ -1771,13 +1773,14 @@ export class MatrixEvent extends TypedEventEmitter<MatrixEventEmittedEvents, Mat
* `duration_ms` is safely bounded to a hour.
*/
public get unstableStickyInfo(): { duration_ms: number; duration_ttl_ms?: number } | undefined {
if (!this.event.msc4354_sticky?.duration_ms) {
const stickyInfo = (this.event[STICKY_EVENT_FIELD.name] ?? this.event[STICKY_EVENT_FIELD.unstable!]) as { duration_ms: number }|undefined;
if (!stickyInfo?.duration_ms) {
return undefined;
}
return {
duration_ms: Math.min(MAX_STICKY_DURATION_MS, this.event.msc4354_sticky.duration_ms),
duration_ms: Math.min(MAX_STICKY_DURATION_MS, stickyInfo.duration_ms),
// This is assumed to be bounded server-side.
duration_ttl_ms: this.event.unsigned?.msc4354_sticky_duration_ttl_ms,
duration_ttl_ms: this.event.unsigned?.[STICKY_EVENT_DURATION_TTL_MS.name] ?? this.event.unsigned?.[STICKY_EVENT_DURATION_TTL_MS.unstable!],
};
}
}

View File

@@ -1,3 +1,4 @@
import { STICKY_EVENT_KEY_FIELD } from "src/matrix.ts";
import { logger as loggerInstance } from "../logger.ts";
import { type MatrixEvent } from "./event.ts";
import { TypedEventEmitter } from "./typed-event-emitter.ts";
@@ -78,14 +79,14 @@ export class RoomStickyEventsStore extends TypedEventEmitter<RoomStickyEventsEve
* and the previous event it may have replaced.
*/
private addStickyEvent(event: MatrixEvent): { added: true; prevEvent?: StickyMatrixEvent } | { added: false } {
const stickyKey = event.getContent().msc4354_sticky_key;
const stickyKey = event.getContent()[STICKY_EVENT_KEY_FIELD.name] ?? event.getContent()[STICKY_EVENT_KEY_FIELD.unstable!];
if (typeof stickyKey !== "string" && stickyKey !== undefined) {
throw new Error(`${event.getId()} is missing msc4354_sticky_key`);
throw new Error(`${event.getId()} is missing ${STICKY_EVENT_KEY_FIELD.name}`);
}
// With this we have the guarantee, that all events in stickyEventsMap are correctly formatted
if (event.unstableStickyExpiresAt === undefined) {
throw new Error(`${event.getId()} is missing msc4354_sticky.duration_ms`);
throw new Error(`${event.getId()} is missing ${STICKY_EVENT_KEY_FIELD.name}.duration_ms`);
}
const sender = event.getSender();
const type = event.getType();

View File

@@ -22,7 +22,7 @@ import { logger } from "./logger.ts";
import { deepCopy } from "./utils.ts";
import { MAX_STICKY_DURATION_MS, type IContent, type IUnsigned } from "./models/event.ts";
import { type IRoomSummary } from "./models/room-summary.ts";
import { type EventType } from "./@types/event.ts";
import { STICKY_EVENT_FIELD, STICKY_EVENT_KEY_FIELD, type EventType } from "./@types/event.ts";
import { UNREAD_THREAD_NOTIFICATIONS } from "./@types/sync.ts";
import { ReceiptAccumulator } from "./receipt-accumulator.ts";
import { type OlmEncryptionInfo } from "./crypto-api/index.ts";
@@ -77,8 +77,8 @@ export interface ITimeline {
}
type StickyEventFields = {
msc4354_sticky: { duration_ms: number };
content: { msc4354_sticky_key?: string };
[STICKY_EVENT_FIELD.name]: { duration_ms: number };
content: { [STICKY_EVENT_KEY_FIELD.name]?: string };
};
export type IStickyEvent = IRoomEvent & StickyEventFields;
@@ -94,7 +94,7 @@ export interface IJoinedRoom {
// One of `state` or `state_after` is required.
"state"?: IState;
"org.matrix.msc4222.state_after"?: IState; // https://github.com/matrix-org/matrix-spec-proposals/pull/4222
"msc4354_sticky"?: ISticky; // https://github.com/matrix-org/matrix-spec-proposals/pull/4354
[STICKY_EVENT_FIELD.name]: ISticky; // https://github.com/matrix-org/matrix-spec-proposals/pull/4354
"timeline": ITimeline;
"ephemeral": IEphemeral;
"account_data": IAccountData;
@@ -570,18 +570,23 @@ export class SyncAccumulator {
// We want this to be fast, so don't worry about duplicate events here. The RoomStickyEventsStore will
// process these events into the correct mapped order.
if (data.msc4354_sticky?.events) {
const stickyEventData = (data.sticky ?? data['msc4354_sticky']) as ISticky;
if (stickyEventData?.events.length) {
currentData._stickyEvents = currentData._stickyEvents.concat(
data.msc4354_sticky.events.map((event) => {
stickyEventData.events.map((event) => {
// If `duration_ms` exceeds the spec limit of a hour, we cap it.
const cappedDuration = Math.min(event.msc4354_sticky.duration_ms, MAX_STICKY_DURATION_MS);
const duration = event['sticky_event']?.duration_ms ?? event['msc4354_sticky']?.duration_ms;
if (typeof duration !== "number") {
return null;
}
const cappedDuration = Math.min(duration, MAX_STICKY_DURATION_MS);
// If `origin_server_ts` claims to have been from the future, we still bound it to now.
const createdTs = Math.min(event.origin_server_ts, now);
return {
event,
expiresTs: cappedDuration + createdTs,
};
}),
}).filter(e => e !== null),
);
}
@@ -659,7 +664,7 @@ export class SyncAccumulator {
"msc4354_sticky": roomData._stickyEvents?.length
? {
events: roomData._stickyEvents.map((e) => e.event),
}
} satisfies ISticky
: undefined,
};
// Add account data

View File

@@ -40,6 +40,7 @@ import {
type ResetTimelineCallback,
} from "./client.ts";
import {
ISticky,
type IEphemeral,
type IInvitedRoom,
type IInviteState,
@@ -58,7 +59,7 @@ import {
import { MatrixEvent } from "./models/event.ts";
import { type MatrixError, Method } from "./http-api/index.ts";
import { type ISavedSync } from "./store/index.ts";
import { EventType } from "./@types/event.ts";
import { EventType, STICKY_EVENT_FIELD } from "./@types/event.ts";
import { type IPushRules } from "./@types/PushRules.ts";
import { type IMarkerFoundOptions, RoomStateEvent } from "./models/room-state.ts";
import { RoomMemberEvent } from "./models/room-member.ts";
@@ -1221,7 +1222,7 @@ export class SyncApi {
const timelineEvents = this.mapSyncEventsFormat(joinObj.timeline, room, false);
const ephemeralEvents = this.mapSyncEventsFormat(joinObj.ephemeral);
const accountDataEvents = this.mapSyncEventsFormat(joinObj.account_data);
const stickyEvents = this.mapSyncEventsFormat(joinObj.msc4354_sticky);
const stickyEvents = this.mapSyncEventsFormat((joinObj[STICKY_EVENT_FIELD.name] ?? joinObj[STICKY_EVENT_FIELD.unstable!]) as ISticky);
// If state_after is present, this is the events that form the state at the end of the timeline block and
// regular timeline events do *not* count towards state. If it's not present, then the state is formed by