You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-09 10:22:46 +03:00
Merge branch 'robertlong/group-call' into dbkr/gcmerge_oct22_3
This commit is contained in:
@@ -30,7 +30,7 @@ import {
|
||||
ITurnServer,
|
||||
} from "matrix-widget-api";
|
||||
|
||||
import { createRoomWidgetClient } from "../../src/matrix";
|
||||
import { createRoomWidgetClient, MsgType } from "../../src/matrix";
|
||||
import { MatrixClient, ClientEvent, ITurnServer as IClientTurnServer } from "../../src/client";
|
||||
import { SyncState } from "../../src/sync";
|
||||
import { ICapabilities } from "../../src/embedded";
|
||||
@@ -43,10 +43,15 @@ class MockWidgetApi extends EventEmitter {
|
||||
public requestCapability = jest.fn();
|
||||
public requestCapabilities = jest.fn();
|
||||
public requestCapabilityForRoomTimeline = jest.fn();
|
||||
public requestCapabilityToSendEvent = jest.fn();
|
||||
public requestCapabilityToReceiveEvent = jest.fn();
|
||||
public requestCapabilityToSendMessage = jest.fn();
|
||||
public requestCapabilityToReceiveMessage = jest.fn();
|
||||
public requestCapabilityToSendState = jest.fn();
|
||||
public requestCapabilityToReceiveState = jest.fn();
|
||||
public requestCapabilityToSendToDevice = jest.fn();
|
||||
public requestCapabilityToReceiveToDevice = jest.fn();
|
||||
public sendRoomEvent = jest.fn(() => ({ event_id: `$${Math.random()}` }));
|
||||
public sendStateEvent = jest.fn();
|
||||
public sendToDevice = jest.fn();
|
||||
public readStateEvents = jest.fn(() => []);
|
||||
@@ -75,6 +80,66 @@ describe("RoomWidgetClient", () => {
|
||||
await client.startClient();
|
||||
};
|
||||
|
||||
describe("events", () => {
|
||||
it("sends", async () => {
|
||||
await makeClient({ sendEvent: ["org.matrix.rageshake_request"] });
|
||||
expect(widgetApi.requestCapabilityForRoomTimeline).toHaveBeenCalledWith("!1:example.org");
|
||||
expect(widgetApi.requestCapabilityToSendEvent).toHaveBeenCalledWith("org.matrix.rageshake_request");
|
||||
await client.sendEvent("!1:example.org", "org.matrix.rageshake_request", { request_id: 123 });
|
||||
expect(widgetApi.sendRoomEvent).toHaveBeenCalledWith(
|
||||
"org.matrix.rageshake_request", { request_id: 123 }, "!1:example.org",
|
||||
);
|
||||
});
|
||||
|
||||
it("receives", async () => {
|
||||
const event = new MatrixEvent({
|
||||
type: "org.matrix.rageshake_request",
|
||||
event_id: "$pduhfiidph",
|
||||
room_id: "!1:example.org",
|
||||
sender: "@alice:example.org",
|
||||
content: { request_id: 123 },
|
||||
}).getEffectiveEvent();
|
||||
|
||||
await makeClient({ receiveEvent: ["org.matrix.rageshake_request"] });
|
||||
expect(widgetApi.requestCapabilityForRoomTimeline).toHaveBeenCalledWith("!1:example.org");
|
||||
expect(widgetApi.requestCapabilityToReceiveEvent).toHaveBeenCalledWith("org.matrix.rageshake_request");
|
||||
|
||||
const emittedEvent = new Promise<MatrixEvent>(resolve => client.once(ClientEvent.Event, resolve));
|
||||
const emittedSync = new Promise<SyncState>(resolve => client.once(ClientEvent.Sync, resolve));
|
||||
widgetApi.emit(
|
||||
`action:${WidgetApiToWidgetAction.SendEvent}`,
|
||||
new CustomEvent(`action:${WidgetApiToWidgetAction.SendEvent}`, { detail: { data: event } }),
|
||||
);
|
||||
|
||||
// The client should've emitted about the received event
|
||||
expect((await emittedEvent).getEffectiveEvent()).toEqual(event);
|
||||
expect(await emittedSync).toEqual(SyncState.Syncing);
|
||||
// It should've also inserted the event into the room object
|
||||
const room = client.getRoom("!1:example.org");
|
||||
expect(room).not.toBeNull();
|
||||
expect(room!.getLiveTimeline().getEvents().map(e => e.getEffectiveEvent())).toEqual([event]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("messages", () => {
|
||||
it("requests permissions for specific message types", async () => {
|
||||
await makeClient({ sendMessage: [MsgType.Text], receiveMessage: [MsgType.Text] });
|
||||
expect(widgetApi.requestCapabilityForRoomTimeline).toHaveBeenCalledWith("!1:example.org");
|
||||
expect(widgetApi.requestCapabilityToSendMessage).toHaveBeenCalledWith(MsgType.Text);
|
||||
expect(widgetApi.requestCapabilityToReceiveMessage).toHaveBeenCalledWith(MsgType.Text);
|
||||
});
|
||||
|
||||
it("requests permissions for all message types", async () => {
|
||||
await makeClient({ sendMessage: true, receiveMessage: true });
|
||||
expect(widgetApi.requestCapabilityForRoomTimeline).toHaveBeenCalledWith("!1:example.org");
|
||||
expect(widgetApi.requestCapabilityToSendMessage).toHaveBeenCalledWith();
|
||||
expect(widgetApi.requestCapabilityToReceiveMessage).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
// No point in testing sending and receiving since it's done exactly the
|
||||
// same way as non-message events
|
||||
});
|
||||
|
||||
describe("state events", () => {
|
||||
const event = new MatrixEvent({
|
||||
type: "org.example.foo",
|
||||
|
@@ -3972,9 +3972,8 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
* @param room
|
||||
* @param event
|
||||
* @returns {Promise} returns a promise which resolves with the result of the send request
|
||||
* @private
|
||||
*/
|
||||
private encryptAndSendEvent(room: Room | null, event: MatrixEvent): Promise<ISendEventResponse> {
|
||||
protected encryptAndSendEvent(room: Room | null, event: MatrixEvent): Promise<ISendEventResponse> {
|
||||
let cancelled = false;
|
||||
// Add an extra Promise.resolve() to turn synchronous exceptions into promise rejections,
|
||||
// so that we can handle synchronous and asynchronous exceptions with the
|
||||
@@ -4099,7 +4098,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
||||
return this.isRoomEncrypted(roomId) ? EventType.RoomMessageEncrypted : eventType;
|
||||
}
|
||||
|
||||
private updatePendingEventStatus(room: Room | null, event: MatrixEvent, newStatus: EventStatus) {
|
||||
protected updatePendingEventStatus(room: Room | null, event: MatrixEvent, newStatus: EventStatus) {
|
||||
if (room) {
|
||||
room.updatePendingEvent(event, newStatus);
|
||||
} else {
|
||||
|
@@ -22,9 +22,10 @@ import {
|
||||
IWidgetApiAcknowledgeResponseData,
|
||||
ISendEventToWidgetActionRequest,
|
||||
ISendToDeviceToWidgetActionRequest,
|
||||
ISendEventFromWidgetResponseData,
|
||||
} from "matrix-widget-api";
|
||||
|
||||
import type { IEvent, IContent } from "./models/event";
|
||||
import { IEvent, IContent, EventStatus } from "./models/event";
|
||||
import { ISendEventResponse } from "./@types/requests";
|
||||
import { EventType } from "./@types/event";
|
||||
import { logger } from "./logger";
|
||||
@@ -44,17 +45,56 @@ interface IStateEventRequest {
|
||||
}
|
||||
|
||||
export interface ICapabilities {
|
||||
// TODO: Add fields for messages and other non-state events
|
||||
/**
|
||||
* Event types that this client expects to send.
|
||||
*/
|
||||
sendEvent?: string[];
|
||||
/**
|
||||
* Event types that this client expects to receive.
|
||||
*/
|
||||
receiveEvent?: string[];
|
||||
|
||||
/**
|
||||
* Message types that this client expects to send, or true for all message
|
||||
* types.
|
||||
*/
|
||||
sendMessage?: string[] | true;
|
||||
/**
|
||||
* Message types that this client expects to receive, or true for all
|
||||
* message types.
|
||||
*/
|
||||
receiveMessage?: string[] | true;
|
||||
|
||||
/**
|
||||
* Types of state events that this client expects to send.
|
||||
*/
|
||||
sendState?: IStateEventRequest[];
|
||||
/**
|
||||
* Types of state events that this client expects to receive.
|
||||
*/
|
||||
receiveState?: IStateEventRequest[];
|
||||
|
||||
/**
|
||||
* To-device event types that this client expects to send.
|
||||
*/
|
||||
sendToDevice?: string[];
|
||||
/**
|
||||
* To-device event types that this client expects to receive.
|
||||
*/
|
||||
receiveToDevice?: string[];
|
||||
|
||||
/**
|
||||
* Whether this client needs access to TURN servers.
|
||||
* @default false
|
||||
*/
|
||||
turnServers?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A MatrixClient that routes its requests through the widget API instead of the
|
||||
* real CS API.
|
||||
* @experimental This class is considered unstable!
|
||||
*/
|
||||
export class RoomWidgetClient extends MatrixClient {
|
||||
private room: Room;
|
||||
private widgetApiReady = new Promise<void>(resolve => this.widgetApi.once("ready", resolve));
|
||||
@@ -70,9 +110,38 @@ export class RoomWidgetClient extends MatrixClient {
|
||||
super(opts);
|
||||
|
||||
// Request capabilities for the functionality this client needs to support
|
||||
if (capabilities.sendState?.length || capabilities.receiveState?.length) {
|
||||
if (
|
||||
capabilities.sendEvent?.length
|
||||
|| capabilities.receiveEvent?.length
|
||||
|| capabilities.sendMessage === true
|
||||
|| (Array.isArray(capabilities.sendMessage) && capabilities.sendMessage.length)
|
||||
|| capabilities.receiveMessage === true
|
||||
|| (Array.isArray(capabilities.receiveMessage) && capabilities.receiveMessage.length)
|
||||
|| capabilities.sendState?.length
|
||||
|| capabilities.receiveState?.length
|
||||
) {
|
||||
widgetApi.requestCapabilityForRoomTimeline(roomId);
|
||||
}
|
||||
capabilities.sendEvent?.forEach(eventType =>
|
||||
widgetApi.requestCapabilityToSendEvent(eventType),
|
||||
);
|
||||
capabilities.receiveEvent?.forEach(eventType =>
|
||||
widgetApi.requestCapabilityToReceiveEvent(eventType),
|
||||
);
|
||||
if (capabilities.sendMessage === true) {
|
||||
widgetApi.requestCapabilityToSendMessage();
|
||||
} else if (Array.isArray(capabilities.sendMessage)) {
|
||||
capabilities.sendMessage.forEach(msgType =>
|
||||
widgetApi.requestCapabilityToSendMessage(msgType),
|
||||
);
|
||||
}
|
||||
if (capabilities.receiveMessage === true) {
|
||||
widgetApi.requestCapabilityToReceiveMessage();
|
||||
} else if (Array.isArray(capabilities.receiveMessage)) {
|
||||
capabilities.receiveMessage.forEach(msgType =>
|
||||
widgetApi.requestCapabilityToReceiveMessage(msgType),
|
||||
);
|
||||
}
|
||||
capabilities.sendState?.forEach(({ eventType, stateKey }) =>
|
||||
widgetApi.requestCapabilityToSendState(eventType, stateKey),
|
||||
);
|
||||
@@ -155,6 +224,19 @@ export class RoomWidgetClient extends MatrixClient {
|
||||
throw new Error(`Unknown room: ${roomIdOrAlias}`);
|
||||
}
|
||||
|
||||
protected async encryptAndSendEvent(room: Room, event: MatrixEvent): Promise<ISendEventResponse> {
|
||||
let response: ISendEventFromWidgetResponseData;
|
||||
try {
|
||||
response = await this.widgetApi.sendRoomEvent(event.getType(), event.getContent(), room.roomId);
|
||||
} catch (e) {
|
||||
this.updatePendingEventStatus(room, event, EventStatus.NOT_SENT);
|
||||
throw e;
|
||||
}
|
||||
|
||||
room.updatePendingEvent(event, EventStatus.SENT, response.event_id);
|
||||
return { event_id: response.event_id };
|
||||
}
|
||||
|
||||
public async sendStateEvent(
|
||||
roomId: string,
|
||||
eventType: string,
|
||||
|
Reference in New Issue
Block a user