Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
"matrix-encrypt-attachment": "^1.0.3",
"matrix-events-sdk": "0.0.1",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
"matrix-widget-api": "^1.14.0",
"matrix-widget-api": "^1.15.0",
"memoize-one": "^6.0.0",
"mime": "^4.0.4",
"oidc-client-ts": "^3.0.1",
Expand Down
6 changes: 2 additions & 4 deletions src/stores/widgets/StopGapWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,10 +522,8 @@ export class StopGapWidget extends EventEmitter {
});
};

private onToDeviceMessage = async (payload: ReceivedToDeviceMessage): Promise<void> => {
const { message, encryptionInfo } = payload;
// TODO: Update the widget API to use a proper IToDeviceMessage instead of a IRoomEvent
await this.messaging?.feedToDevice(message as IRoomEvent, encryptionInfo != null);
private onToDeviceMessage = async ({ message, encryptionInfo }: ReceivedToDeviceMessage): Promise<void> => {
await this.messaging?.feedToDevice(message, encryptionInfo != null);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drive-by update since we fixed the types upstream in the latest release.

};

/**
Expand Down
102 changes: 77 additions & 25 deletions src/stores/widgets/StopGapWidgetDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
type ISearchUserDirectoryResult,
type IGetMediaConfigResult,
} from "matrix-widget-api";
import {

Check failure on line 30 in src/stores/widgets/StopGapWidgetDriver.ts

View workflow job for this annotation

GitHub Actions / ESLint

Imports "SendDelayedEventRequestOpts" are only used as type
ClientEvent,
type ITurnServer as IClientTurnServer,
EventType,
Expand All @@ -39,6 +39,7 @@
type SendDelayedEventResponse,
type StateEvents,
type TimelineEvents,
SendDelayedEventRequestOpts,
} from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import {
Expand Down Expand Up @@ -121,6 +122,7 @@
this.allowedCapabilities.add(`org.matrix.msc2762.timeline:${inRoomId}`);
this.allowedCapabilities.add(MatrixCapabilities.MSC4157SendDelayedEvent);
this.allowedCapabilities.add(MatrixCapabilities.MSC4157UpdateDelayedEvent);
this.allowedCapabilities.add(MatrixCapabilities.MSC4354SendStickyEvent);

this.allowedCapabilities.add(
WidgetEventCapability.forStateEvent(EventDirection.Receive, EventType.RoomName).raw,
Expand Down Expand Up @@ -284,6 +286,13 @@
return allAllowed;
}

private getSendEventTarget(roomId: string | null = null) {

Check failure on line 289 in src/stores/widgets/StopGapWidgetDriver.ts

View workflow job for this annotation

GitHub Actions / ESLint

Missing return type on function
const client = MatrixClientPeg.safeGet();
roomId = roomId || SdkContextClass.instance.roomViewStore.getRoomId() || null;
if (!roomId) throw new Error("No room specified and no room in RoomViewStore focus.");
return { client, roomId };
}

public async sendEvent<K extends keyof StateEvents>(
eventType: K,
content: StateEvents[K],
Expand All @@ -302,10 +311,7 @@
stateKey: string | null = null,
targetRoomId: string | null = null,
): Promise<ISendEventDetails> {
const client = MatrixClientPeg.get();
const roomId = targetRoomId || SdkContextClass.instance.roomViewStore.getRoomId();

if (!client || !roomId) throw new Error("Not in a room or not attached to a client");
const { client, roomId } = this.getSendEventTarget(targetRoomId);

let r: { event_id: string } | null;
if (stateKey !== null) {
Expand Down Expand Up @@ -344,6 +350,42 @@
return { roomId, eventId: r.event_id };
}

/**
* @experimental Part of MSC4354
* @see {@link WidgetDriver#sendStickyEvent}
*/
public async sendStickyEvent(
stickyDurationMs: number,
eventType: string,
content: unknown,
targetRoomId?: string | null,
): Promise<ISendEventDetails> {
const { client, roomId } = this.getSendEventTarget(targetRoomId);

const r = await client._unstable_sendStickyEvent(
roomId,
stickyDurationMs,
null,
eventType as keyof TimelineEvents,
content as TimelineEvents[keyof TimelineEvents] & { msc4354_sticky_key: string },
);
return { roomId, eventId: r.event_id };
}

private getSendDelayedEventOpts(delay: number | null, parentDelayId: string | null): SendDelayedEventRequestOpts {
if (delay !== null) {
return {
delay,
...(parentDelayId !== null && { parent_delay_id: parentDelayId }),
};
} else if (parentDelayId !== null) {
return {
parent_delay_id: parentDelayId,
};
}
throw new Error("Must provide at least one of delay or parentDelayId");
}

/**
* @experimental Part of MSC4140 & MSC4157
* @see {@link WidgetDriver#sendDelayedEvent}
Expand Down Expand Up @@ -375,24 +417,8 @@
stateKey: string | null = null,
targetRoomId: string | null = null,
): Promise<ISendDelayedEventDetails> {
const client = MatrixClientPeg.get();
const roomId = targetRoomId || SdkContextClass.instance.roomViewStore.getRoomId();

if (!client || !roomId) throw new Error("Not in a room or not attached to a client");

let delayOpts;
if (delay !== null) {
delayOpts = {
delay,
...(parentDelayId !== null && { parent_delay_id: parentDelayId }),
};
} else if (parentDelayId !== null) {
delayOpts = {
parent_delay_id: parentDelayId,
};
} else {
throw new Error("Must provide at least one of delay or parentDelayId");
}
const { client, roomId } = this.getSendEventTarget(targetRoomId);
let delayOpts = this.getSendDelayedEventOpts(delay, parentDelayId);

Check failure on line 421 in src/stores/widgets/StopGapWidgetDriver.ts

View workflow job for this annotation

GitHub Actions / ESLint

'delayOpts' is never reassigned. Use 'const' instead

let r: SendDelayedEventResponse | null;
if (stateKey !== null) {
Expand Down Expand Up @@ -421,13 +447,39 @@
};
}

/**
* @experimental Part of MSC4354
* @see {@link WidgetDriver#sendStickyEvent}
*/
public async sendDelayedStickyEvent(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need more parameters :p

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's awful yes :D.

delay: number | null,
parentDelayId: string | null,
stickyDurationMs: number,
eventType: string,
content: unknown,
targetRoomId?: string | null,
): Promise<ISendDelayedEventDetails> {
const { client, roomId } = this.getSendEventTarget(targetRoomId);
let delayOpts = this.getSendDelayedEventOpts(delay, parentDelayId);

Check failure on line 463 in src/stores/widgets/StopGapWidgetDriver.ts

View workflow job for this annotation

GitHub Actions / ESLint

'delayOpts' is never reassigned. Use 'const' instead

const r = await client._unstable_sendStickyDelayedEvent(
roomId,
stickyDurationMs,
delayOpts,
null,
eventType as keyof TimelineEvents,
content as TimelineEvents[keyof TimelineEvents] & { msc4354_sticky_key: string },
);
return { roomId, delayId: r.delay_id };
}

/**
* @experimental Part of MSC4140 & MSC4157
*/
public async cancelScheduledDelayedEvent(delayId: string): Promise<void> {
const client = MatrixClientPeg.get();

if (!client) throw new Error("Not in a room or not attached to a client");
if (!client) throw new Error("Not attached to a client");

await client._unstable_cancelScheduledDelayedEvent(delayId);
}
Expand All @@ -438,7 +490,7 @@
public async restartScheduledDelayedEvent(delayId: string): Promise<void> {
const client = MatrixClientPeg.get();

if (!client) throw new Error("Not in a room or not attached to a client");
if (!client) throw new Error("Not attached to a client");

await client._unstable_restartScheduledDelayedEvent(delayId);
}
Expand All @@ -449,7 +501,7 @@
public async sendScheduledDelayedEvent(delayId: string): Promise<void> {
const client = MatrixClientPeg.get();

if (!client) throw new Error("Not in a room or not attached to a client");
if (!client) throw new Error("Not attached to a client");

await client._unstable_sendScheduledDelayedEvent(delayId);
}
Expand Down
2 changes: 2 additions & 0 deletions test/test-utils/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ export function createTestClient(): MatrixClient {
_unstable_cancelScheduledDelayedEvent: jest.fn(),
_unstable_restartScheduledDelayedEvent: jest.fn(),
_unstable_sendScheduledDelayedEvent: jest.fn(),
_unstable_sendStickyEvent: jest.fn(),
_unstable_sendStickyDelayedEvent: jest.fn(),

searchUserDirectory: jest.fn().mockResolvedValue({ limited: false, results: [] }),
setDeviceVerified: jest.fn(),
Expand Down
79 changes: 79 additions & 0 deletions test/unit-tests/stores/widgets/StopGapWidgetDriver-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ describe("StopGapWidgetDriver", () => {
"org.matrix.msc3819.receive.to_device:m.call.replaces",
"org.matrix.msc4157.send.delayed_event",
"org.matrix.msc4157.update_delayed_event",
"org.matrix.msc4354.send_sticky_event",
// RTC decline events
"org.matrix.msc2762.send.event:org.matrix.msc4310.rtc.decline",
"org.matrix.msc2762.receive.event:org.matrix.msc4310.rtc.decline",
Expand Down Expand Up @@ -590,6 +591,84 @@ describe("StopGapWidgetDriver", () => {
});
});

describe("sendStickyEvent", () => {
let driver: WidgetDriver;
const roomId = "!this-room-id";

beforeEach(() => {
driver = mkDefaultDriver();
});

it("sends sticky message events", async () => {
client._unstable_sendStickyEvent.mockResolvedValue({
event_id: "id",
});

await expect(driver.sendStickyEvent(2000, EventType.RoomMessage, {})).resolves.toEqual({
roomId,
eventId: "id",
});

expect(client._unstable_sendStickyEvent).toHaveBeenCalledWith(
roomId,
2000,
null,
EventType.RoomMessage,
{},
);
});
});

describe("sendDelayedStickyEvent", () => {
let driver: WidgetDriver;
const roomId = "!this-room-id";

beforeEach(() => {
driver = mkDefaultDriver();
});

it("sends delayed sticky message events", async () => {
client._unstable_sendStickyDelayedEvent.mockResolvedValue({
delay_id: "id",
});

await expect(driver.sendDelayedStickyEvent(1000, null, 2000, EventType.RoomMessage, {})).resolves.toEqual({
roomId,
delayId: "id",
});

expect(client._unstable_sendStickyDelayedEvent).toHaveBeenCalledWith(
roomId,
2000,
{ delay: 1000 },
null,
EventType.RoomMessage,
{},
);
});
it("sends child action delayed sticky message events", async () => {
client._unstable_sendStickyDelayedEvent.mockResolvedValue({
delay_id: "id-child",
});

await expect(
driver.sendDelayedStickyEvent(null, "id-parent", 2000, EventType.RoomMessage, {}),
).resolves.toEqual({
roomId,
delayId: "id-child",
});

expect(client._unstable_sendStickyDelayedEvent).toHaveBeenCalledWith(
roomId,
2000,
{ parent_delay_id: "id-parent" },
null,
EventType.RoomMessage,
{},
);
});
});

describe("If the feature_dynamic_room_predecessors feature is not enabled", () => {
beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false);
Expand Down
13 changes: 7 additions & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4220,13 +4220,14 @@

"@vector-im/matrix-wysiwyg-wasm@link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.40.0-53c9ca5ea907d91e4515da64f20a82e5586b882c-integrity/node_modules/bindings/wysiwyg-wasm":
version "0.0.0"
uid ""

"@vector-im/[email protected]":
version "2.40.0"
resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.40.0.tgz#53c9ca5ea907d91e4515da64f20a82e5586b882c"
integrity sha512-8LRFLs5PEKYs4lOL7aJ4lL/hGCrvEvOYkCR3JggXYXDVMtX4LmfdlKYucSAe98pCmqAAbLRvlRcR1bTOYvM8ug==
dependencies:
"@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.40.0-53c9ca5ea907d91e4515da64f20a82e5586b882c-integrity/node_modules/bindings/wysiwyg-wasm"
"@vector-im/matrix-wysiwyg-wasm" "link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.40.0-53c9ca5ea907d91e4515da64f20a82e5586b882c-integrity/node_modules/bindings/wysiwyg-wasm"

"@vitest/[email protected]":
version "3.2.4"
Expand Down Expand Up @@ -9669,7 +9670,7 @@ [email protected]:
jwt-decode "^4.0.0"
loglevel "^1.9.2"
matrix-events-sdk "0.0.1"
matrix-widget-api "^1.14.0"
matrix-widget-api "^1.10.0"
oidc-client-ts "^3.0.1"
p-retry "7"
sdp-transform "^3.0.0"
Expand All @@ -9695,10 +9696,10 @@ matrix-widget-api@^1.14.0:
"@types/events" "^3.0.0"
events "^3.2.0"

matrix-widget-api@^1.14.0:
version "1.14.0"
resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-1.14.0.tgz#aa90c40ace27d3165299f7dbc760a53001ce1446"
integrity sha512-DDvZGOQhI/rilPWg5VlLN7pHIsPt0Jt14lsuHDP+KU+fmpAQNITJ6aIld1ZoXWsrVGv2PS3x6K/MHtfruIOQJQ==
matrix-widget-api@^1.15.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-1.15.0.tgz#a508f72a5993a95382bdf890bd9e54525295b321"
integrity sha512-Yu9rX9wyF3A1sqviKgiYHz8aGgL3HhJe9OXKi/lccr1eZnNb6y+ELdbshTjs+VLKM4rkTWt6CE3THsw3f/CZhg==
dependencies:
"@types/events" "^3.0.0"
events "^3.2.0"
Expand Down
Loading