You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2026-01-03 23:22:30 +03:00
Merge branch 'develop' into toger5/sticky-events
Signed-off-by: Timo K <toger5@hotmail.de>
This commit is contained in:
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,3 +1,15 @@
|
||||
Changes in [38.4.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v38.4.0) (2025-10-07)
|
||||
==================================================================================================
|
||||
## ✨ Features
|
||||
|
||||
* Add call intent to RTC call notifications ([#5010](https://github.com/matrix-org/matrix-js-sdk/pull/5010)). Contributed by @Half-Shot.
|
||||
* Implement experimental encrypted state events. ([#4994](https://github.com/matrix-org/matrix-js-sdk/pull/4994)). Contributed by @kaylendog.
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
* Exclude cancelled requests from in-progress lists ([#5016](https://github.com/matrix-org/matrix-js-sdk/pull/5016)). Contributed by @andybalaam.
|
||||
|
||||
|
||||
Changes in [38.3.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v38.3.0) (2025-09-23)
|
||||
==================================================================================================
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "matrix-js-sdk",
|
||||
"version": "38.3.0",
|
||||
"version": "38.4.0",
|
||||
"description": "Matrix Client-Server SDK for Javascript",
|
||||
"engines": {
|
||||
"node": ">=22.0.0"
|
||||
|
||||
@@ -1116,6 +1116,18 @@ describe("SyncAccumulator", function () {
|
||||
sa.accumulate(syncSkeleton({}));
|
||||
expect(sa.getJSON().roomsData[Category.Join]["!foo:bar"].msc4354_sticky?.events).toBeUndefined();
|
||||
});
|
||||
|
||||
it("clears stale sticky events that pretend to be from the distant future", () => {
|
||||
jest.setSystemTime(0);
|
||||
const eventFarInTheFuture = stickyEvent(999999999999);
|
||||
sa.accumulate(syncSkeleton({ msc4354_sticky: { events: [eventFarInTheFuture] } }));
|
||||
expect(sa.getJSON().roomsData[Category.Join]["!foo:bar"].msc4354_sticky?.events).toEqual([
|
||||
eventFarInTheFuture,
|
||||
]);
|
||||
jest.setSystemTime(1000); // Expire the event
|
||||
sa.accumulate(syncSkeleton({}));
|
||||
expect(sa.getJSON().roomsData[Category.Join]["!foo:bar"].msc4354_sticky?.events).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ export interface IJoinRoomOpts {
|
||||
|
||||
/**
|
||||
* The server names to try and join through in addition to those that are automatically chosen.
|
||||
* Only the first 3 are actually used in the request, to avoid HTTP 414 Request-URI Too Long responses.
|
||||
*/
|
||||
viaServers?: string[];
|
||||
|
||||
@@ -71,6 +72,7 @@ export interface KnockRoomOpts {
|
||||
|
||||
/**
|
||||
* The server names to try and knock through in addition to those that are automatically chosen.
|
||||
* Only the first 3 are actually used in the request, to avoid HTTP 414 Request-URI Too Long responses.
|
||||
*/
|
||||
viaServers?: string | string[];
|
||||
}
|
||||
|
||||
@@ -2393,8 +2393,8 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
const queryParams: QueryDict = {};
|
||||
if (opts.viaServers) {
|
||||
// server_name has been deprecated in favour of via with Matrix >1.11 (MSC4156)
|
||||
queryParams.server_name = opts.viaServers;
|
||||
queryParams.via = opts.viaServers;
|
||||
// We only use the first 3 servers, to avoid URI length issues.
|
||||
queryParams.via = queryParams.server_name = opts.viaServers.slice(0, 3);
|
||||
}
|
||||
|
||||
const data: IJoinRequestBody = {};
|
||||
@@ -2438,9 +2438,11 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
|
||||
const queryParams: QueryDict = {};
|
||||
if (opts.viaServers) {
|
||||
// We only use the first 3 servers, to avoid URI length issues.
|
||||
const viaServers = Array.isArray(opts.viaServers) ? opts.viaServers.slice(0, 3) : [opts.viaServers];
|
||||
// server_name has been deprecated in favour of via with Matrix >1.11 (MSC4156)
|
||||
queryParams.server_name = opts.viaServers;
|
||||
queryParams.via = opts.viaServers;
|
||||
queryParams.server_name = viaServers;
|
||||
queryParams.via = viaServers;
|
||||
}
|
||||
|
||||
const body: Record<string, string> = {};
|
||||
|
||||
@@ -32,7 +32,7 @@ export class RoomStickyEventsStore extends TypedEventEmitter<RoomStickyEventsEve
|
||||
private readonly stickyEventsMap = new Map<string, Map<string, StickyMatrixEvent>>(); // (type -> stickyKey+userId) -> event
|
||||
private readonly unkeyedStickyEvents = new Set<StickyMatrixEvent>();
|
||||
|
||||
private stickyEventTimer?: NodeJS.Timeout;
|
||||
private stickyEventTimer?: ReturnType<typeof setTimeout>;
|
||||
private nextStickyEventExpiryTs: number = Number.MAX_SAFE_INTEGER;
|
||||
|
||||
/**
|
||||
|
||||
@@ -215,7 +215,14 @@ interface IRoom {
|
||||
_unreadNotifications: Partial<UnreadNotificationCounts>;
|
||||
_unreadThreadNotifications?: Record<string, Partial<UnreadNotificationCounts>>;
|
||||
_receipts: ReceiptAccumulator;
|
||||
_stickyEvents: (IStickyEvent | IStickyStateEvent)[];
|
||||
_stickyEvents: {
|
||||
readonly event: IStickyEvent | IStickyStateEvent;
|
||||
/**
|
||||
* This is the timestamp at which point it is safe to remove this event from the store.
|
||||
* This value is immutable
|
||||
*/
|
||||
readonly expiresTs: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface ISyncData {
|
||||
@@ -426,6 +433,7 @@ export class SyncAccumulator {
|
||||
|
||||
// Accumulate timeline and state events in a room.
|
||||
private accumulateJoinState(roomId: string, data: IJoinedRoom, fromDatabase = false): void {
|
||||
const now = Date.now();
|
||||
// We expect this function to be called a lot (every /sync) so we want
|
||||
// this to be fast. /sync stores events in an array but we often want
|
||||
// to clobber based on type/state_key. Rather than convert arrays to
|
||||
@@ -558,20 +566,23 @@ export class SyncAccumulator {
|
||||
|
||||
// Prune out any events in our stores that have since expired, do this before we
|
||||
// insert new events.
|
||||
const now = Date.now();
|
||||
currentData._stickyEvents = currentData._stickyEvents.filter((ev) => {
|
||||
// If `duration_ms` exceeds the spec limit of a hour, we cap it.
|
||||
const cappedDuration = Math.min(ev.msc4354_sticky.duration_ms, MAX_STICKY_DURATION_MS);
|
||||
// If `origin_server_ts` claims to have been from the future, we still bound it to now.
|
||||
const sanitisedOriginTs = Math.min(now, ev.origin_server_ts);
|
||||
const expiresAt = cappedDuration + sanitisedOriginTs;
|
||||
return expiresAt > now;
|
||||
});
|
||||
currentData._stickyEvents = currentData._stickyEvents.filter(({ expiresTs }) => expiresTs > now);
|
||||
|
||||
// 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) {
|
||||
currentData._stickyEvents = currentData._stickyEvents.concat(data.msc4354_sticky.events);
|
||||
currentData._stickyEvents = currentData._stickyEvents.concat(
|
||||
data.msc4354_sticky.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);
|
||||
// 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,
|
||||
};
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// attempt to prune the timeline by jumping between events which have
|
||||
@@ -647,7 +658,7 @@ export class SyncAccumulator {
|
||||
"summary": roomData._summary as IRoomSummary,
|
||||
"msc4354_sticky": roomData._stickyEvents?.length
|
||||
? {
|
||||
events: roomData._stickyEvents,
|
||||
events: roomData._stickyEvents.map((e) => e.event),
|
||||
}
|
||||
: undefined,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user