tutanota/src/api/main/EventController.ts

71 lines
2.6 KiB
TypeScript
Raw Normal View History

import {downcast, identity, isSameTypeRefByAttr, noOp, remove, TypeRef} from "@tutao/tutanota-utils"
import type {LoginController} from "./LoginController"
2021-12-23 14:03:23 +01:00
import type {OperationType} from "../common/TutanotaConstants"
import stream from "mithril/stream"
import Stream from "mithril/stream"
import {assertMainOrNode} from "../common/Env"
import {EntityUpdate, WebsocketCounterData} from "../entities/sys/TypeRefs"
import {SomeEntity} from "../common/EntityTypes.js"
import {isSameId} from "../common/utils/EntityUtils.js"
2017-08-15 13:54:22 +02:00
assertMainOrNode()
2018-10-19 18:13:58 +02:00
export type EntityUpdateData = {
application: string
type: string
instanceListId: string
instanceId: string
operation: OperationType
2018-10-19 18:13:58 +02:00
}
2021-12-23 14:03:23 +01:00
export type EntityEventsListener = (updates: ReadonlyArray<EntityUpdateData>, eventOwnerGroupId: Id) => Promise<any>
2018-10-24 16:39:21 +02:00
export const isUpdateForTypeRef = <T>(typeRef: TypeRef<T>, update: EntityUpdateData): boolean => isSameTypeRefByAttr(typeRef, update.application, update.type)
export function isUpdateFor<T extends SomeEntity>(entity: T, update: EntityUpdateData): boolean {
const typeRef = entity._type as TypeRef<T>
return isUpdateForTypeRef(typeRef, update)
&& (update.instanceListId === "" ? isSameId(update.instanceId, entity._id) : isSameId([update.instanceListId, update.instanceId], entity._id))
}
2019-01-21 10:48:07 +01:00
export class EventController {
private countersStream: Stream<WebsocketCounterData> = stream()
private entityListeners: Array<EntityEventsListener> = []
2017-08-15 13:54:22 +02:00
constructor(
private readonly logins: LoginController
) {
}
2017-08-15 13:54:22 +02:00
addEntityListener(listener: EntityEventsListener) {
this.entityListeners.push(listener)
}
2019-01-21 10:48:07 +01:00
removeEntityListener(listener: EntityEventsListener) {
remove(this.entityListeners, listener)
}
2017-08-15 13:54:22 +02:00
getCountersStream(): Stream<WebsocketCounterData> {
// Create copy so it's never ended
return this.countersStream.map(identity)
}
2017-08-15 13:54:22 +02:00
notificationReceived(entityUpdates: ReadonlyArray<EntityUpdate>, eventOwnerGroupId: Id): Promise<void> {
let loginsUpdates = Promise.resolve()
2018-10-19 18:13:58 +02:00
if (this.logins.isUserLoggedIn()) {
// the UserController must be notified first as other event receivers depend on it to be up-to-date
loginsUpdates = this.logins.getUserController().entityEventsReceived(entityUpdates as ReadonlyArray<EntityUpdateData>, eventOwnerGroupId)
}
2019-01-21 10:48:07 +01:00
return loginsUpdates
.then(async () => {
// sequentially to prevent parallel loading of instances
for (const listener of this.entityListeners) {
let entityUpdatesData: Array<EntityUpdateData> = downcast(entityUpdates)
await listener(entityUpdatesData, eventOwnerGroupId)
}
})
.then(noOp)
}
2021-12-23 14:03:23 +01:00
counterUpdateReceived(update: WebsocketCounterData) {
this.countersStream(update)
}
2021-12-23 14:03:23 +01:00
}