You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-28 05:03:59 +03:00
Improve typing around event emitter handlers (#2180)
This commit is contained in:
committed by
GitHub
parent
1ac4cc4b11
commit
12e525b664
188
src/client.ts
188
src/client.ts
@@ -19,15 +19,22 @@ limitations under the License.
|
||||
* @module client
|
||||
*/
|
||||
|
||||
import { EventEmitter } from "events";
|
||||
import { EmoteEvent, IPartialEvent, MessageEvent, NoticeEvent } from "matrix-events-sdk";
|
||||
|
||||
import { ISyncStateData, SyncApi, SyncState } from "./sync";
|
||||
import { EventStatus, IContent, IDecryptOptions, IEvent, MatrixEvent } from "./models/event";
|
||||
import {
|
||||
EventStatus,
|
||||
IContent,
|
||||
IDecryptOptions,
|
||||
IEvent,
|
||||
MatrixEvent,
|
||||
MatrixEventEvent,
|
||||
MatrixEventHandlerMap,
|
||||
} from "./models/event";
|
||||
import { StubStore } from "./store/stub";
|
||||
import { createNewMatrixCall, MatrixCall } from "./webrtc/call";
|
||||
import { CallEvent, CallEventHandlerMap, createNewMatrixCall, MatrixCall } from "./webrtc/call";
|
||||
import { Filter, IFilterDefinition } from "./filter";
|
||||
import { CallEventHandler } from './webrtc/callEventHandler';
|
||||
import { CallEventHandlerEvent, CallEventHandler, CallEventHandlerEventHandlerMap } from './webrtc/callEventHandler';
|
||||
import * as utils from './utils';
|
||||
import { sleep } from './utils';
|
||||
import { Group } from "./models/group";
|
||||
@@ -37,12 +44,12 @@ import { AutoDiscovery, AutoDiscoveryAction } from "./autodiscovery";
|
||||
import * as olmlib from "./crypto/olmlib";
|
||||
import { decodeBase64, encodeBase64 } from "./crypto/olmlib";
|
||||
import { IExportedDevice as IOlmDevice } from "./crypto/OlmDevice";
|
||||
import { ReEmitter } from './ReEmitter';
|
||||
import { TypedReEmitter } from './ReEmitter';
|
||||
import { IRoomEncryption, RoomList } from './crypto/RoomList';
|
||||
import { logger } from './logger';
|
||||
import { SERVICE_TYPES } from './service-types';
|
||||
import {
|
||||
FileType,
|
||||
FileType, HttpApiEvent, HttpApiEventHandlerMap,
|
||||
IHttpOpts,
|
||||
IUpload,
|
||||
MatrixError,
|
||||
@@ -58,6 +65,8 @@ import {
|
||||
} from "./http-api";
|
||||
import {
|
||||
Crypto,
|
||||
CryptoEvent,
|
||||
CryptoEventHandlerMap,
|
||||
fixBackupKey,
|
||||
IBootstrapCrossSigningOpts,
|
||||
ICheckOwnCrossSigningTrustOpts,
|
||||
@@ -68,7 +77,7 @@ import {
|
||||
import { DeviceInfo, IDevice } from "./crypto/deviceinfo";
|
||||
import { decodeRecoveryKey } from './crypto/recoverykey';
|
||||
import { keyFromAuthData } from './crypto/key_passphrase';
|
||||
import { User } from "./models/user";
|
||||
import { User, UserEvent, UserEventHandlerMap } from "./models/user";
|
||||
import { getHttpUriForMxc } from "./content-repo";
|
||||
import { SearchResult } from "./models/search-result";
|
||||
import {
|
||||
@@ -88,7 +97,20 @@ import {
|
||||
} from "./crypto/keybackup";
|
||||
import { IIdentityServerProvider } from "./@types/IIdentityServerProvider";
|
||||
import { MatrixScheduler } from "./scheduler";
|
||||
import { IAuthData, ICryptoCallbacks, IMinimalEvent, IRoomEvent, IStateEvent, NotificationCountType } from "./matrix";
|
||||
import {
|
||||
IAuthData,
|
||||
ICryptoCallbacks,
|
||||
IMinimalEvent,
|
||||
IRoomEvent,
|
||||
IStateEvent,
|
||||
NotificationCountType,
|
||||
RoomEvent,
|
||||
RoomEventHandlerMap,
|
||||
RoomMemberEvent,
|
||||
RoomMemberEventHandlerMap,
|
||||
RoomStateEvent,
|
||||
RoomStateEventHandlerMap,
|
||||
} from "./matrix";
|
||||
import {
|
||||
CrossSigningKey,
|
||||
IAddSecretStorageKeyOpts,
|
||||
@@ -155,6 +177,7 @@ import { IThreepid } from "./@types/threepids";
|
||||
import { CryptoStore } from "./crypto/store/base";
|
||||
import { MediaHandler } from "./webrtc/mediaHandler";
|
||||
import { IRefreshTokenResponse } from "./@types/auth";
|
||||
import { TypedEventEmitter } from "./models/typed-event-emitter";
|
||||
|
||||
export type Store = IStore;
|
||||
export type SessionStore = WebStorageSessionStore;
|
||||
@@ -453,7 +476,7 @@ export interface ISignedKey {
|
||||
}
|
||||
|
||||
export type KeySignatures = Record<string, Record<string, ICrossSigningKey | ISignedKey>>;
|
||||
interface IUploadKeySignaturesResponse {
|
||||
export interface IUploadKeySignaturesResponse {
|
||||
failures: Record<string, Record<string, {
|
||||
errcode: string;
|
||||
error: string;
|
||||
@@ -747,15 +770,107 @@ interface ITimestampToEventResponse {
|
||||
// Probably not the most graceful solution but does a good enough job for now
|
||||
const EVENT_ID_PREFIX = "$";
|
||||
|
||||
export enum ClientEvent {
|
||||
Sync = "sync",
|
||||
Event = "event",
|
||||
ToDeviceEvent = "toDeviceEvent",
|
||||
AccountData = "accountData",
|
||||
Room = "Room",
|
||||
DeleteRoom = "deleteRoom",
|
||||
SyncUnexpectedError = "sync.unexpectedError",
|
||||
ClientWellKnown = "WellKnown.client",
|
||||
/* @deprecated */
|
||||
Group = "Group",
|
||||
// The following enum members are both deprecated and in the wrong place, Groups haven't been TSified
|
||||
GroupProfile = "Group.profile",
|
||||
GroupMyMembership = "Group.myMembership",
|
||||
}
|
||||
|
||||
type RoomEvents = RoomEvent.Name
|
||||
| RoomEvent.Redaction
|
||||
| RoomEvent.RedactionCancelled
|
||||
| RoomEvent.Receipt
|
||||
| RoomEvent.Tags
|
||||
| RoomEvent.LocalEchoUpdated
|
||||
| RoomEvent.AccountData
|
||||
| RoomEvent.MyMembership
|
||||
| RoomEvent.Timeline
|
||||
| RoomEvent.TimelineReset;
|
||||
|
||||
type RoomStateEvents = RoomStateEvent.Events
|
||||
| RoomStateEvent.Members
|
||||
| RoomStateEvent.NewMember;
|
||||
|
||||
type CryptoEvents = CryptoEvent.KeySignatureUploadFailure
|
||||
| CryptoEvent.KeyBackupStatus
|
||||
| CryptoEvent.KeyBackupFailed
|
||||
| CryptoEvent.KeyBackupSessionsRemaining
|
||||
| CryptoEvent.RoomKeyRequest
|
||||
| CryptoEvent.RoomKeyRequestCancellation
|
||||
| CryptoEvent.VerificationRequest
|
||||
| CryptoEvent.DeviceVerificationChanged
|
||||
| CryptoEvent.UserTrustStatusChanged
|
||||
| CryptoEvent.KeysChanged
|
||||
| CryptoEvent.Warning
|
||||
| CryptoEvent.DevicesUpdated
|
||||
| CryptoEvent.WillUpdateDevices;
|
||||
|
||||
type MatrixEventEvents = MatrixEventEvent.Decrypted | MatrixEventEvent.Replaced | MatrixEventEvent.VisibilityChange;
|
||||
|
||||
type RoomMemberEvents = RoomMemberEvent.Name
|
||||
| RoomMemberEvent.Typing
|
||||
| RoomMemberEvent.PowerLevel
|
||||
| RoomMemberEvent.Membership;
|
||||
|
||||
type UserEvents = UserEvent.AvatarUrl
|
||||
| UserEvent.DisplayName
|
||||
| UserEvent.Presence
|
||||
| UserEvent.CurrentlyActive
|
||||
| UserEvent.LastPresenceTs;
|
||||
|
||||
type EmittedEvents = ClientEvent
|
||||
| RoomEvents
|
||||
| RoomStateEvents
|
||||
| CryptoEvents
|
||||
| MatrixEventEvents
|
||||
| RoomMemberEvents
|
||||
| UserEvents
|
||||
| CallEvent // re-emitted by call.ts using Object.values
|
||||
| CallEventHandlerEvent.Incoming
|
||||
| HttpApiEvent.SessionLoggedOut
|
||||
| HttpApiEvent.NoConsent;
|
||||
|
||||
export type ClientEventHandlerMap = {
|
||||
[ClientEvent.Sync]: (state: SyncState, lastState?: SyncState, data?: ISyncStateData) => void;
|
||||
[ClientEvent.Event]: (event: MatrixEvent) => void;
|
||||
[ClientEvent.ToDeviceEvent]: (event: MatrixEvent) => void;
|
||||
[ClientEvent.AccountData]: (event: MatrixEvent, lastEvent?: MatrixEvent) => void;
|
||||
[ClientEvent.Room]: (room: Room) => void;
|
||||
[ClientEvent.DeleteRoom]: (roomId: string) => void;
|
||||
[ClientEvent.SyncUnexpectedError]: (error: Error) => void;
|
||||
[ClientEvent.ClientWellKnown]: (data: IClientWellKnown) => void;
|
||||
[ClientEvent.Group]: (group: Group) => void;
|
||||
[ClientEvent.GroupProfile]: (group: Group) => void;
|
||||
[ClientEvent.GroupMyMembership]: (group: Group) => void;
|
||||
} & RoomEventHandlerMap
|
||||
& RoomStateEventHandlerMap
|
||||
& CryptoEventHandlerMap
|
||||
& MatrixEventHandlerMap
|
||||
& RoomMemberEventHandlerMap
|
||||
& UserEventHandlerMap
|
||||
& CallEventHandlerEventHandlerMap
|
||||
& CallEventHandlerMap
|
||||
& HttpApiEventHandlerMap;
|
||||
|
||||
/**
|
||||
* Represents a Matrix Client. Only directly construct this if you want to use
|
||||
* custom modules. Normally, {@link createClient} should be used
|
||||
* as it specifies 'sensible' defaults for these modules.
|
||||
*/
|
||||
export class MatrixClient extends EventEmitter {
|
||||
export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHandlerMap> {
|
||||
public static readonly RESTORE_BACKUP_ERROR_BAD_KEY = 'RESTORE_BACKUP_ERROR_BAD_KEY';
|
||||
|
||||
public reEmitter = new ReEmitter(this);
|
||||
public reEmitter = new TypedReEmitter<EmittedEvents, ClientEventHandlerMap>(this);
|
||||
public olmVersion: [number, number, number] = null; // populated after initCrypto
|
||||
public usingExternalCrypto = false;
|
||||
public store: Store;
|
||||
@@ -836,7 +951,7 @@ export class MatrixClient extends EventEmitter {
|
||||
const userId = opts.userId || null;
|
||||
this.credentials = { userId };
|
||||
|
||||
this.http = new MatrixHttpApi(this, {
|
||||
this.http = new MatrixHttpApi(this as ConstructorParameters<typeof MatrixHttpApi>[0], {
|
||||
baseUrl: opts.baseUrl,
|
||||
idBaseUrl: opts.idBaseUrl,
|
||||
accessToken: opts.accessToken,
|
||||
@@ -897,7 +1012,7 @@ export class MatrixClient extends EventEmitter {
|
||||
// Start listening for calls after the initial sync is done
|
||||
// We do not need to backfill the call event buffer
|
||||
// with encrypted events that might never get decrypted
|
||||
this.on("sync", this.startCallEventHandler);
|
||||
this.on(ClientEvent.Sync, this.startCallEventHandler);
|
||||
}
|
||||
|
||||
this.timelineSupport = Boolean(opts.timelineSupport);
|
||||
@@ -922,7 +1037,7 @@ export class MatrixClient extends EventEmitter {
|
||||
// actions for themselves, so we have to kinda help them out when they are encrypted.
|
||||
// We do this so that push rules are correctly executed on events in their decrypted
|
||||
// state, such as highlights when the user's name is mentioned.
|
||||
this.on("Event.decrypted", (event) => {
|
||||
this.on(MatrixEventEvent.Decrypted, (event) => {
|
||||
const oldActions = event.getPushActions();
|
||||
const actions = this.getPushActionsForEvent(event, true);
|
||||
|
||||
@@ -957,7 +1072,7 @@ export class MatrixClient extends EventEmitter {
|
||||
// Like above, we have to listen for read receipts from ourselves in order to
|
||||
// correctly handle notification counts on encrypted rooms.
|
||||
// This fixes https://github.com/vector-im/element-web/issues/9421
|
||||
this.on("Room.receipt", (event, room) => {
|
||||
this.on(RoomEvent.Receipt, (event, room) => {
|
||||
if (room && this.isRoomEncrypted(room.roomId)) {
|
||||
// Figure out if we've read something or if it's just informational
|
||||
const content = event.getContent();
|
||||
@@ -992,7 +1107,7 @@ export class MatrixClient extends EventEmitter {
|
||||
|
||||
// Note: we don't need to handle 'total' notifications because the counts
|
||||
// will come from the server.
|
||||
room.setUnreadNotificationCount("highlight", highlightCount);
|
||||
room.setUnreadNotificationCount(NotificationCountType.Highlight, highlightCount);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1557,16 +1672,16 @@ export class MatrixClient extends EventEmitter {
|
||||
);
|
||||
|
||||
this.reEmitter.reEmit(crypto, [
|
||||
"crypto.keyBackupFailed",
|
||||
"crypto.keyBackupSessionsRemaining",
|
||||
"crypto.roomKeyRequest",
|
||||
"crypto.roomKeyRequestCancellation",
|
||||
"crypto.warning",
|
||||
"crypto.devicesUpdated",
|
||||
"crypto.willUpdateDevices",
|
||||
"deviceVerificationChanged",
|
||||
"userTrustStatusChanged",
|
||||
"crossSigning.keysChanged",
|
||||
CryptoEvent.KeyBackupFailed,
|
||||
CryptoEvent.KeyBackupSessionsRemaining,
|
||||
CryptoEvent.RoomKeyRequest,
|
||||
CryptoEvent.RoomKeyRequestCancellation,
|
||||
CryptoEvent.Warning,
|
||||
CryptoEvent.DevicesUpdated,
|
||||
CryptoEvent.WillUpdateDevices,
|
||||
CryptoEvent.DeviceVerificationChanged,
|
||||
CryptoEvent.UserTrustStatusChanged,
|
||||
CryptoEvent.KeysChanged,
|
||||
]);
|
||||
|
||||
logger.log("Crypto: initialising crypto object...");
|
||||
@@ -1578,9 +1693,8 @@ export class MatrixClient extends EventEmitter {
|
||||
|
||||
this.olmVersion = Crypto.getOlmVersion();
|
||||
|
||||
// if crypto initialisation was successful, tell it to attach its event
|
||||
// handlers.
|
||||
crypto.registerEventHandlers(this);
|
||||
// if crypto initialisation was successful, tell it to attach its event handlers.
|
||||
crypto.registerEventHandlers(this as Parameters<Crypto["registerEventHandlers"]>[0]);
|
||||
this.crypto = crypto;
|
||||
}
|
||||
|
||||
@@ -1820,7 +1934,7 @@ export class MatrixClient extends EventEmitter {
|
||||
* @returns {Verification} a verification object
|
||||
* @deprecated Use `requestVerification` instead.
|
||||
*/
|
||||
public beginKeyVerification(method: string, userId: string, deviceId: string): Verification {
|
||||
public beginKeyVerification(method: string, userId: string, deviceId: string): Verification<any, any> {
|
||||
if (!this.crypto) {
|
||||
throw new Error("End-to-end encryption disabled");
|
||||
}
|
||||
@@ -3660,7 +3774,7 @@ export class MatrixClient extends EventEmitter {
|
||||
const targetId = localEvent.getAssociatedId();
|
||||
if (targetId && targetId.startsWith("~")) {
|
||||
const target = room.getPendingEvents().find(e => e.getId() === targetId);
|
||||
target.once("Event.localEventIdReplaced", () => {
|
||||
target.once(MatrixEventEvent.LocalEventIdReplaced, () => {
|
||||
localEvent.updateAssociatedId(target.getId());
|
||||
});
|
||||
}
|
||||
@@ -4758,7 +4872,7 @@ export class MatrixClient extends EventEmitter {
|
||||
}
|
||||
return promise.then((response) => {
|
||||
this.store.removeRoom(roomId);
|
||||
this.emit("deleteRoom", roomId);
|
||||
this.emit(ClientEvent.DeleteRoom, roomId);
|
||||
return response;
|
||||
});
|
||||
}
|
||||
@@ -4911,7 +5025,7 @@ export class MatrixClient extends EventEmitter {
|
||||
const user = this.getUser(this.getUserId());
|
||||
if (user) {
|
||||
user.displayName = name;
|
||||
user.emit("User.displayName", user.events.presence, user);
|
||||
user.emit(UserEvent.DisplayName, user.events.presence, user);
|
||||
}
|
||||
return prom;
|
||||
}
|
||||
@@ -4928,7 +5042,7 @@ export class MatrixClient extends EventEmitter {
|
||||
const user = this.getUser(this.getUserId());
|
||||
if (user) {
|
||||
user.avatarUrl = url;
|
||||
user.emit("User.avatarUrl", user.events.presence, user);
|
||||
user.emit(UserEvent.AvatarUrl, user.events.presence, user);
|
||||
}
|
||||
return prom;
|
||||
}
|
||||
@@ -6098,7 +6212,7 @@ export class MatrixClient extends EventEmitter {
|
||||
private startCallEventHandler = (): void => {
|
||||
if (this.isInitialSyncComplete()) {
|
||||
this.callEventHandler.start();
|
||||
this.off("sync", this.startCallEventHandler);
|
||||
this.off(ClientEvent.Sync, this.startCallEventHandler);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6246,7 +6360,7 @@ export class MatrixClient extends EventEmitter {
|
||||
// it absorbs errors and returns `{}`.
|
||||
this.clientWellKnownPromise = AutoDiscovery.getRawClientConfig(this.getDomain());
|
||||
this.clientWellKnown = await this.clientWellKnownPromise;
|
||||
this.emit("WellKnown.client", this.clientWellKnown);
|
||||
this.emit(ClientEvent.ClientWellKnown, this.clientWellKnown);
|
||||
}
|
||||
|
||||
public getClientWellKnown(): IClientWellKnown {
|
||||
@@ -6510,7 +6624,7 @@ export class MatrixClient extends EventEmitter {
|
||||
const allEvents = originalEvent ? events.concat(originalEvent) : events;
|
||||
await Promise.all(allEvents.map(e => {
|
||||
if (e.isEncrypted()) {
|
||||
return new Promise(resolve => e.once("Event.decrypted", resolve));
|
||||
return new Promise(resolve => e.once(MatrixEventEvent.Decrypted, resolve));
|
||||
}
|
||||
}));
|
||||
events = events.filter(e => e.getType() === eventType);
|
||||
|
||||
Reference in New Issue
Block a user