matrix-js-sdk 41.5.0 → 41.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/lib/ReEmitter.js +1 -1
  3. package/lib/ReEmitter.js.map +1 -1
  4. package/lib/ToDeviceMessageQueue.js +2 -2
  5. package/lib/ToDeviceMessageQueue.js.map +1 -1
  6. package/lib/autodiscovery.js +0 -1
  7. package/lib/autodiscovery.js.map +1 -1
  8. package/lib/client.js +112 -165
  9. package/lib/client.js.map +1 -1
  10. package/lib/common-crypto/CryptoBackend.js +0 -2
  11. package/lib/common-crypto/CryptoBackend.js.map +1 -1
  12. package/lib/content-helpers.js +3 -5
  13. package/lib/content-helpers.js.map +1 -1
  14. package/lib/content-repo.js +7 -1
  15. package/lib/content-repo.js.map +1 -1
  16. package/lib/crypto/store/indexeddb-crypto-store-backend.js +9 -11
  17. package/lib/crypto/store/indexeddb-crypto-store-backend.js.map +1 -1
  18. package/lib/crypto/store/indexeddb-crypto-store.js +0 -2
  19. package/lib/crypto/store/indexeddb-crypto-store.js.map +1 -1
  20. package/lib/crypto/store/localStorage-crypto-store.js +11 -9
  21. package/lib/crypto/store/localStorage-crypto-store.js.map +1 -1
  22. package/lib/crypto/store/memory-crypto-store.js +11 -9
  23. package/lib/crypto/store/memory-crypto-store.js.map +1 -1
  24. package/lib/crypto-api/index.js +58 -58
  25. package/lib/crypto-api/index.js.map +1 -1
  26. package/lib/embedded.js +29 -45
  27. package/lib/embedded.js.map +1 -1
  28. package/lib/extensible_events_v1/MessageEvent.js +15 -15
  29. package/lib/extensible_events_v1/MessageEvent.js.map +1 -1
  30. package/lib/extensible_events_v1/PollEndEvent.js +8 -8
  31. package/lib/extensible_events_v1/PollEndEvent.js.map +1 -1
  32. package/lib/extensible_events_v1/PollResponseEvent.js +0 -1
  33. package/lib/extensible_events_v1/PollResponseEvent.js.map +1 -1
  34. package/lib/extensible_events_v1/PollStartEvent.js +28 -28
  35. package/lib/extensible_events_v1/PollStartEvent.js.map +1 -1
  36. package/lib/feature.js +5 -1
  37. package/lib/feature.js.map +1 -1
  38. package/lib/filter-component.js +4 -1
  39. package/lib/filter-component.js.map +1 -1
  40. package/lib/filter.js +1 -3
  41. package/lib/filter.js.map +1 -1
  42. package/lib/http-api/errors.js +20 -16
  43. package/lib/http-api/errors.js.map +1 -1
  44. package/lib/http-api/fetch.js +4 -6
  45. package/lib/http-api/fetch.js.map +1 -1
  46. package/lib/http-api/refresh.js +10 -12
  47. package/lib/http-api/refresh.js.map +1 -1
  48. package/lib/interactive-auth.js +1 -11
  49. package/lib/interactive-auth.js.map +1 -1
  50. package/lib/logger.js +0 -2
  51. package/lib/logger.js.map +1 -1
  52. package/lib/matrixrtc/CallMembership.js +43 -57
  53. package/lib/matrixrtc/CallMembership.js.map +1 -1
  54. package/lib/matrixrtc/MatrixRTCSession.js +19 -24
  55. package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
  56. package/lib/matrixrtc/MatrixRTCSessionManager.js +2 -3
  57. package/lib/matrixrtc/MatrixRTCSessionManager.js.map +1 -1
  58. package/lib/matrixrtc/MembershipManager.js +23 -30
  59. package/lib/matrixrtc/MembershipManager.js.map +1 -1
  60. package/lib/matrixrtc/MembershipManagerActionScheduler.js +1 -2
  61. package/lib/matrixrtc/MembershipManagerActionScheduler.js.map +1 -1
  62. package/lib/matrixrtc/RTCEncryptionManager.js +8 -11
  63. package/lib/matrixrtc/RTCEncryptionManager.js.map +1 -1
  64. package/lib/matrixrtc/ToDeviceKeyTransport.js +4 -4
  65. package/lib/matrixrtc/ToDeviceKeyTransport.js.map +1 -1
  66. package/lib/matrixrtc/utils.js +7 -1
  67. package/lib/matrixrtc/utils.js.map +1 -1
  68. package/lib/models/MSC3089TreeSpace.js +5 -7
  69. package/lib/models/MSC3089TreeSpace.js.map +1 -1
  70. package/lib/models/beacon.js +5 -11
  71. package/lib/models/beacon.js.map +1 -1
  72. package/lib/models/device.js +0 -7
  73. package/lib/models/device.js.map +1 -1
  74. package/lib/models/event-context.js +1 -2
  75. package/lib/models/event-context.js.map +1 -1
  76. package/lib/models/event-timeline-set.js +16 -26
  77. package/lib/models/event-timeline-set.js.map +1 -1
  78. package/lib/models/event-timeline.js +8 -15
  79. package/lib/models/event-timeline.js.map +1 -1
  80. package/lib/models/event.js +20 -37
  81. package/lib/models/event.js.map +1 -1
  82. package/lib/models/invites-ignorer.js +8 -12
  83. package/lib/models/invites-ignorer.js.map +1 -1
  84. package/lib/models/poll.js +7 -13
  85. package/lib/models/poll.js.map +1 -1
  86. package/lib/models/read-receipt.js +8 -4
  87. package/lib/models/read-receipt.js.map +1 -1
  88. package/lib/models/related-relations.js +0 -2
  89. package/lib/models/related-relations.js.map +1 -1
  90. package/lib/models/relations-container.js +4 -6
  91. package/lib/models/relations-container.js.map +1 -1
  92. package/lib/models/relations.js +7 -10
  93. package/lib/models/relations.js.map +1 -1
  94. package/lib/models/room-member.js +2 -24
  95. package/lib/models/room-member.js.map +1 -1
  96. package/lib/models/room-receipts.js +25 -22
  97. package/lib/models/room-receipts.js.map +1 -1
  98. package/lib/models/room-state.js +2 -2
  99. package/lib/models/room-state.js.map +1 -1
  100. package/lib/models/room-sticky-events.js +20 -5
  101. package/lib/models/room-sticky-events.js.map +1 -1
  102. package/lib/models/room.js +82 -105
  103. package/lib/models/room.js.map +1 -1
  104. package/lib/models/thread.js +12 -57
  105. package/lib/models/thread.js.map +1 -1
  106. package/lib/models/user.js +1 -20
  107. package/lib/models/user.js.map +1 -1
  108. package/lib/oidc/authorize.js +23 -32
  109. package/lib/oidc/authorize.js.map +1 -1
  110. package/lib/oidc/tokenRefresher.js +8 -11
  111. package/lib/oidc/tokenRefresher.js.map +1 -1
  112. package/lib/pushprocessor.js +8 -5
  113. package/lib/pushprocessor.js.map +1 -1
  114. package/lib/receipt-accumulator.js +12 -3
  115. package/lib/receipt-accumulator.js.map +1 -1
  116. package/lib/rendezvous/MSC4108SignInWithQR.d.ts.map +1 -1
  117. package/lib/rendezvous/MSC4108SignInWithQR.js +10 -23
  118. package/lib/rendezvous/MSC4108SignInWithQR.js.map +1 -1
  119. package/lib/rendezvous/channels/MSC4108SecureChannel.js +5 -10
  120. package/lib/rendezvous/channels/MSC4108SecureChannel.js.map +1 -1
  121. package/lib/rendezvous/transports/MSC4108RendezvousSession.js +5 -15
  122. package/lib/rendezvous/transports/MSC4108RendezvousSession.js.map +1 -1
  123. package/lib/room-hierarchy.js +7 -12
  124. package/lib/room-hierarchy.js.map +1 -1
  125. package/lib/rust-crypto/DehydratedDeviceManager.js +2 -3
  126. package/lib/rust-crypto/DehydratedDeviceManager.js.map +1 -1
  127. package/lib/rust-crypto/KeyClaimManager.js +1 -2
  128. package/lib/rust-crypto/KeyClaimManager.js.map +1 -1
  129. package/lib/rust-crypto/OutgoingRequestProcessor.js +11 -4
  130. package/lib/rust-crypto/OutgoingRequestProcessor.js.map +1 -1
  131. package/lib/rust-crypto/OutgoingRequestsManager.js +12 -12
  132. package/lib/rust-crypto/OutgoingRequestsManager.js.map +1 -1
  133. package/lib/rust-crypto/PerSessionKeyBackupDownloader.js +3 -5
  134. package/lib/rust-crypto/PerSessionKeyBackupDownloader.js.map +1 -1
  135. package/lib/rust-crypto/RoomEncryptor.js +6 -6
  136. package/lib/rust-crypto/RoomEncryptor.js.map +1 -1
  137. package/lib/rust-crypto/backup.js +22 -16
  138. package/lib/rust-crypto/backup.js.map +1 -1
  139. package/lib/rust-crypto/device-converter.js +13 -4
  140. package/lib/rust-crypto/device-converter.js.map +1 -1
  141. package/lib/rust-crypto/index.js +1 -3
  142. package/lib/rust-crypto/index.js.map +1 -1
  143. package/lib/rust-crypto/libolm_migration.js +13 -15
  144. package/lib/rust-crypto/libolm_migration.js.map +1 -1
  145. package/lib/rust-crypto/rust-crypto.js +52 -59
  146. package/lib/rust-crypto/rust-crypto.js.map +1 -1
  147. package/lib/rust-crypto/verification.js +10 -10
  148. package/lib/rust-crypto/verification.js.map +1 -1
  149. package/lib/scheduler.js +2 -2
  150. package/lib/scheduler.js.map +1 -1
  151. package/lib/secret-storage.js +16 -10
  152. package/lib/secret-storage.js.map +1 -1
  153. package/lib/serverCapabilities.js +2 -5
  154. package/lib/serverCapabilities.js.map +1 -1
  155. package/lib/sliding-sync-sdk.js +4 -9
  156. package/lib/sliding-sync-sdk.js.map +1 -1
  157. package/lib/sliding-sync.js +4 -9
  158. package/lib/sliding-sync.js.map +1 -1
  159. package/lib/store/indexeddb-local-backend.js +13 -8
  160. package/lib/store/indexeddb-local-backend.js.map +1 -1
  161. package/lib/store/indexeddb-remote-backend.js +6 -7
  162. package/lib/store/indexeddb-remote-backend.js.map +1 -1
  163. package/lib/store/indexeddb-store-worker.js +1 -2
  164. package/lib/store/indexeddb-store-worker.js.map +1 -1
  165. package/lib/store/indexeddb.js +4 -2
  166. package/lib/store/indexeddb.js.map +1 -1
  167. package/lib/store/memory.js +0 -4
  168. package/lib/store/memory.js.map +1 -1
  169. package/lib/sync-accumulator.js +2 -4
  170. package/lib/sync-accumulator.js.map +1 -1
  171. package/lib/sync.js +36 -43
  172. package/lib/sync.js.map +1 -1
  173. package/lib/timeline-window.js +2 -6
  174. package/lib/timeline-window.js.map +1 -1
  175. package/lib/utils/decryptAESSecretStorageItem.js +5 -1
  176. package/lib/utils/decryptAESSecretStorageItem.js.map +1 -1
  177. package/lib/utils/encryptAESSecretStorageItem.js +5 -1
  178. package/lib/utils/encryptAESSecretStorageItem.js.map +1 -1
  179. package/lib/utils.js +35 -20
  180. package/lib/utils.js.map +1 -1
  181. package/lib/webrtc/call.js +13 -45
  182. package/lib/webrtc/call.js.map +1 -1
  183. package/lib/webrtc/callEventHandler.js +0 -5
  184. package/lib/webrtc/callEventHandler.js.map +1 -1
  185. package/lib/webrtc/callFeed.js +0 -15
  186. package/lib/webrtc/callFeed.js.map +1 -1
  187. package/lib/webrtc/groupCall.js +82 -89
  188. package/lib/webrtc/groupCall.js.map +1 -1
  189. package/lib/webrtc/groupCallEventHandler.js +6 -7
  190. package/lib/webrtc/groupCallEventHandler.js.map +1 -1
  191. package/lib/webrtc/mediaHandler.js +8 -15
  192. package/lib/webrtc/mediaHandler.js.map +1 -1
  193. package/lib/webrtc/stats/callStatsReportGatherer.js +2 -5
  194. package/lib/webrtc/stats/callStatsReportGatherer.js.map +1 -1
  195. package/lib/webrtc/stats/connectionStatsReportBuilder.js +5 -1
  196. package/lib/webrtc/stats/connectionStatsReportBuilder.js.map +1 -1
  197. package/lib/webrtc/stats/groupCallStats.js +3 -4
  198. package/lib/webrtc/stats/groupCallStats.js.map +1 -1
  199. package/lib/webrtc/stats/media/mediaTrackStats.js +3 -3
  200. package/lib/webrtc/stats/media/mediaTrackStats.js.map +1 -1
  201. package/lib/webrtc/stats/media/mediaTrackStatsHandler.js +1 -1
  202. package/lib/webrtc/stats/media/mediaTrackStatsHandler.js.map +1 -1
  203. package/package.json +3 -3
  204. package/src/rendezvous/MSC4108SignInWithQR.ts +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"relations.js","names":["EventStatus","MatrixEventEvent","logger","RelationType","TypedEventEmitter","Room","RelationsEvent","matchesEventType","eventType","targetEventType","altTargetEventTypes","arguments","length","undefined","includes","Relations","constructor","relationType","client","altEventTypes","_this","this","_defineProperty","Set","event","status","isSending","removeListener","Status","onEventStatus","CANCELLED","removeEvent","_ref","_asyncToGenerator","redactedEvent","relations","has","delete","Annotation","removeAnnotationFromAggregation","Replace","updateTargetEventReplacement","BeforeRedaction","onBeforeRedaction","emit","Redaction","_x","apply","addEvent","_this2","relationEventIds","getId","relation","getRelation","error","rel_type","getType","on","add","addAnnotationToAggregation","Add","maybeEmitCreated","_this3","Remove","getRelations","_event$getRelation","key","eventsForKey","annotationsByKey","sortedAnnotationsByKey","push","sort","a","b","aEvents","bEvents","size","sender","getSender","eventsFromSender","annotationsBySender","_event$getRelation2","getSortedAnnotationsByKey","getAnnotationsBySender","getLastReplacement","_this4","targetEvent","replaceRelation","getServerAggregatedRelation","minTs","origin_server_ts","lastReplacement","reduce","last","getTs","shouldAttemptDecryption","getCrypto","attemptDecryption","isBeingDecrypted","getDecryptionPromise","setTargetEvent","_this5","_this6","isState","updateId","replacementUpdateId","replacingEvent","makeReplaced","creationEmitted","RelationsCreated"],"sources":["../../src/models/relations.ts"],"sourcesContent":["/*\nCopyright 2019, 2021, 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { EventStatus, type IAggregatedRelation, type MatrixEvent, MatrixEventEvent } from \"./event.ts\";\nimport { logger } from \"../logger.ts\";\nimport { RelationType } from \"../@types/event.ts\";\nimport { TypedEventEmitter } from \"./typed-event-emitter.ts\";\nimport { type MatrixClient } from \"../client.ts\";\nimport { Room } from \"./room.ts\";\nimport { type CryptoBackend } from \"../common-crypto/CryptoBackend.ts\";\n\nexport enum RelationsEvent {\n Add = \"Relations.add\",\n Remove = \"Relations.remove\",\n Redaction = \"Relations.redaction\",\n}\n\nexport type EventHandlerMap = {\n [RelationsEvent.Add]: (event: MatrixEvent) => void;\n [RelationsEvent.Remove]: (event: MatrixEvent) => void;\n [RelationsEvent.Redaction]: (event: MatrixEvent) => void;\n};\n\nconst matchesEventType = (eventType: string, targetEventType: string, altTargetEventTypes: string[] = []): boolean =>\n [targetEventType, ...altTargetEventTypes].includes(eventType);\n\n/**\n * A container for relation events that supports easy access to common ways of\n * aggregating such events. Each instance holds events that of a single relation\n * type and event type. All of the events also relate to the same original event.\n *\n * The typical way to get one of these containers is via\n * EventTimelineSet#getRelationsForEvent.\n */\nexport class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap> {\n private relationEventIds = new Set<string>();\n private relations = new Set<MatrixEvent>();\n private annotationsByKey: Record<string, Set<MatrixEvent>> = {};\n private annotationsBySender: Record<string, Set<MatrixEvent>> = {};\n private sortedAnnotationsByKey: [string, Set<MatrixEvent>][] = [];\n private targetEvent: MatrixEvent | null = null;\n private creationEmitted = false;\n private replacementUpdateId = 0;\n private readonly client: MatrixClient;\n\n /**\n * @param relationType - The type of relation involved, such as \"m.annotation\", \"m.reference\", \"m.replace\", etc.\n * @param eventType - The relation event's type, such as \"m.reaction\", etc.\n * @param client - The client which created this instance. For backwards compatibility also accepts a Room.\n * @param altEventTypes - alt event types for relation events, for example to support unstable prefixed event types\n */\n public constructor(\n public readonly relationType: RelationType | string,\n public readonly eventType: string,\n client: MatrixClient | Room,\n public readonly altEventTypes?: string[],\n ) {\n super();\n this.client = client instanceof Room ? client.client : client;\n }\n\n /**\n * Add relation events to this collection.\n *\n * @param event - The new relation event to be added.\n */\n public async addEvent(event: MatrixEvent): Promise<void> {\n if (this.relationEventIds.has(event.getId()!)) {\n return;\n }\n\n const relation = event.getRelation();\n if (!relation) {\n logger.error(\"Event must have relation info\");\n return;\n }\n\n const relationType = relation.rel_type;\n const eventType = event.getType();\n\n if (this.relationType !== relationType || !matchesEventType(eventType, this.eventType, this.altEventTypes)) {\n logger.error(\"Event relation info doesn't match this container\");\n return;\n }\n\n // If the event is in the process of being sent, listen for cancellation\n // so we can remove the event from the collection.\n if (event.isSending()) {\n event.on(MatrixEventEvent.Status, this.onEventStatus);\n }\n\n this.relations.add(event);\n this.relationEventIds.add(event.getId()!);\n\n if (this.relationType === RelationType.Annotation) {\n this.addAnnotationToAggregation(event);\n } else if (this.relationType === RelationType.Replace) {\n await this.updateTargetEventReplacement();\n }\n\n event.on(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);\n\n this.emit(RelationsEvent.Add, event);\n\n this.maybeEmitCreated();\n }\n\n /**\n * Remove relation event from this collection.\n *\n * @param event - The relation event to remove.\n */\n public async removeEvent(event: MatrixEvent): Promise<void> {\n if (!this.relations.has(event)) {\n return;\n }\n\n this.relations.delete(event);\n\n if (this.relationType === RelationType.Annotation) {\n this.removeAnnotationFromAggregation(event);\n } else if (this.relationType === RelationType.Replace) {\n await this.updateTargetEventReplacement();\n }\n\n this.emit(RelationsEvent.Remove, event);\n }\n\n /**\n * Listens for event status changes to remove cancelled events.\n *\n * @param event - The event whose status has changed\n * @param status - The new status\n */\n private onEventStatus = (event: MatrixEvent, status: EventStatus | null): void => {\n if (!event.isSending()) {\n // Sending is done, so we don't need to listen anymore\n event.removeListener(MatrixEventEvent.Status, this.onEventStatus);\n return;\n }\n if (status !== EventStatus.CANCELLED) {\n return;\n }\n // Event was cancelled, remove from the collection\n event.removeListener(MatrixEventEvent.Status, this.onEventStatus);\n this.removeEvent(event);\n };\n\n /**\n * Get all relation events in this collection.\n *\n * These are currently in the order of insertion to this collection, which\n * won't match timeline order in the case of scrollback.\n * TODO: Tweak `addEvent` to insert correctly for scrollback.\n *\n * Relation events in insertion order.\n */\n public getRelations(): MatrixEvent[] {\n return [...this.relations];\n }\n\n private addAnnotationToAggregation(event: MatrixEvent): void {\n const { key } = event.getRelation() ?? {};\n if (!key) return;\n\n let eventsForKey = this.annotationsByKey[key];\n if (!eventsForKey) {\n eventsForKey = this.annotationsByKey[key] = new Set();\n this.sortedAnnotationsByKey.push([key, eventsForKey]);\n }\n // Add the new event to the set for this key\n eventsForKey.add(event);\n // Re-sort the [key, events] pairs in descending order of event count\n this.sortedAnnotationsByKey.sort((a, b) => {\n const aEvents = a[1];\n const bEvents = b[1];\n return bEvents.size - aEvents.size;\n });\n\n const sender = event.getSender()!;\n let eventsFromSender = this.annotationsBySender[sender];\n if (!eventsFromSender) {\n eventsFromSender = this.annotationsBySender[sender] = new Set();\n }\n // Add the new event to the set for this sender\n eventsFromSender.add(event);\n }\n\n private removeAnnotationFromAggregation(event: MatrixEvent): void {\n const { key } = event.getRelation() ?? {};\n if (!key) return;\n\n const eventsForKey = this.annotationsByKey[key];\n if (eventsForKey) {\n eventsForKey.delete(event);\n\n // Re-sort the [key, events] pairs in descending order of event count\n this.sortedAnnotationsByKey.sort((a, b) => {\n const aEvents = a[1];\n const bEvents = b[1];\n return bEvents.size - aEvents.size;\n });\n }\n\n const sender = event.getSender()!;\n const eventsFromSender = this.annotationsBySender[sender];\n if (eventsFromSender) {\n eventsFromSender.delete(event);\n }\n }\n\n /**\n * For relations that have been redacted, we want to remove them from\n * aggregation data sets and emit an update event.\n *\n * To do so, we listen for `Event.beforeRedaction`, which happens:\n * - after the server accepted the redaction and remote echoed back to us\n * - before the original event has been marked redacted in the client\n *\n * @param redactedEvent - The original relation event that is about to be redacted.\n */\n private onBeforeRedaction = async (redactedEvent: MatrixEvent): Promise<void> => {\n if (!this.relations.has(redactedEvent)) {\n return;\n }\n\n this.relations.delete(redactedEvent);\n\n if (this.relationType === RelationType.Annotation) {\n // Remove the redacted annotation from aggregation by key\n this.removeAnnotationFromAggregation(redactedEvent);\n } else if (this.relationType === RelationType.Replace) {\n await this.updateTargetEventReplacement();\n }\n\n redactedEvent.removeListener(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);\n\n this.emit(RelationsEvent.Redaction, redactedEvent);\n };\n\n /**\n * Get all events in this collection grouped by key and sorted by descending\n * event count in each group.\n *\n * This is currently only supported for the annotation relation type.\n *\n * An array of [key, events] pairs sorted by descending event count.\n * The events are stored in a Set (which preserves insertion order).\n */\n public getSortedAnnotationsByKey(): [string, Set<MatrixEvent>][] | null {\n if (this.relationType !== RelationType.Annotation) {\n // Other relation types are not grouped currently.\n return null;\n }\n\n return this.sortedAnnotationsByKey;\n }\n\n /**\n * Get all events in this collection grouped by sender.\n *\n * This is currently only supported for the annotation relation type.\n *\n * An object with each relation sender as a key and the matching Set of\n * events for that sender as a value.\n */\n public getAnnotationsBySender(): Record<string, Set<MatrixEvent>> | null {\n if (this.relationType !== RelationType.Annotation) {\n // Other relation types are not grouped currently.\n return null;\n }\n\n return this.annotationsBySender;\n }\n\n /**\n * Returns the most recent (and allowed) m.replace relation, if any.\n *\n * This is currently only supported for the m.replace relation type,\n * once the target event is known, see `addEvent`.\n */\n public async getLastReplacement(): Promise<MatrixEvent | null> {\n if (this.relationType !== RelationType.Replace) {\n // Aggregating on last only makes sense for this relation type\n return null;\n }\n if (!this.targetEvent) {\n // Don't know which replacements to accept yet.\n // This method shouldn't be called before the original\n // event is known anyway.\n return null;\n }\n\n // the all-knowning server tells us that the event at some point had\n // this timestamp for its replacement, so any following replacement should definitely not be less\n const replaceRelation = this.targetEvent.getServerAggregatedRelation<IAggregatedRelation>(RelationType.Replace);\n const minTs = replaceRelation?.origin_server_ts;\n\n const lastReplacement = this.getRelations().reduce<MatrixEvent | null>((last, event) => {\n if (event.getSender() !== this.targetEvent!.getSender()) {\n return last;\n }\n if (minTs && minTs > event.getTs()) {\n return last;\n }\n if (last && last.getTs() > event.getTs()) {\n return last;\n }\n return event;\n }, null);\n\n if (lastReplacement?.shouldAttemptDecryption() && this.client.getCrypto()) {\n // Dirty but we are expecting to pass the cryptoBackend which is not accessible here\n await lastReplacement.attemptDecryption(this.client.getCrypto() as CryptoBackend);\n } else if (lastReplacement?.isBeingDecrypted()) {\n await lastReplacement.getDecryptionPromise();\n }\n\n return lastReplacement;\n }\n\n /*\n * @param targetEvent - the event the relations are related to.\n */\n public async setTargetEvent(event: MatrixEvent): Promise<void> {\n if (this.targetEvent) {\n return;\n }\n this.targetEvent = event;\n\n if (this.relationType === RelationType.Replace) {\n await this.updateTargetEventReplacement();\n }\n\n this.maybeEmitCreated();\n }\n\n /**\n * Updates the target event with the latest replacement.\n *\n * Multiple replacement updates can be triggered concurrently (for example\n * while edits are still being decrypted). A monotonic update counter guards\n * against older async resolutions overriding newer replacement selections.\n */\n private async updateTargetEventReplacement(): Promise<void> {\n if (!this.targetEvent || this.targetEvent.isState()) {\n return;\n }\n\n const targetEvent = this.targetEvent;\n const updateId = ++this.replacementUpdateId;\n const lastReplacement = await this.getLastReplacement();\n\n // If a newer update started while we were awaiting, discard this stale result.\n if (updateId !== this.replacementUpdateId || this.targetEvent !== targetEvent) {\n return;\n }\n\n // Avoid emitting Event.replaced when there is no replacement and none currently set.\n if (!lastReplacement && !targetEvent.replacingEvent()) {\n return;\n }\n\n targetEvent.makeReplaced(lastReplacement ?? undefined);\n }\n\n private maybeEmitCreated(): void {\n if (this.creationEmitted) {\n return;\n }\n // Only emit we're \"created\" once we have a target event instance _and_\n // at least one related event.\n if (!this.targetEvent || !this.relations.size) {\n return;\n }\n this.creationEmitted = true;\n this.targetEvent.emit(MatrixEventEvent.RelationsCreated, this.relationType, this.eventType);\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"relations.js","names":["EventStatus","MatrixEventEvent","logger","RelationType","TypedEventEmitter","Room","RelationsEvent","matchesEventType","eventType","targetEventType","altTargetEventTypes","arguments","length","undefined","includes","Relations","constructor","relationType","client","altEventTypes","_this","this","_defineProperty","Set","event","status","isSending","removeListener","Status","onEventStatus","CANCELLED","removeEvent","_ref","_asyncToGenerator","redactedEvent","relations","has","delete","Annotation","removeAnnotationFromAggregation","Replace","updateTargetEventReplacement","BeforeRedaction","onBeforeRedaction","emit","Redaction","_x","apply","addEvent","_this2","relationEventIds","getId","relation","getRelation","error","rel_type","getType","on","add","addAnnotationToAggregation","Add","maybeEmitCreated","_this3","Remove","getRelations","_event$getRelation","_ref2","key","eventsForKey","annotationsByKey","sortedAnnotationsByKey","push","sort","a","b","aEvents","bEvents","size","sender","getSender","eventsFromSender","annotationsBySender","_event$getRelation2","_ref3","getSortedAnnotationsByKey","getAnnotationsBySender","getLastReplacement","_this4","targetEvent","replaceRelation","getServerAggregatedRelation","minTs","origin_server_ts","lastReplacement","reduce","last","getTs","shouldAttemptDecryption","getCrypto","attemptDecryption","isBeingDecrypted","getDecryptionPromise","setTargetEvent","_this5","_this6","isState","updateId","replacementUpdateId","replacingEvent","makeReplaced","creationEmitted","RelationsCreated"],"sources":["../../src/models/relations.ts"],"sourcesContent":["/*\nCopyright 2019, 2021, 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { EventStatus, type IAggregatedRelation, type MatrixEvent, MatrixEventEvent } from \"./event.ts\";\nimport { logger } from \"../logger.ts\";\nimport { RelationType } from \"../@types/event.ts\";\nimport { TypedEventEmitter } from \"./typed-event-emitter.ts\";\nimport { type MatrixClient } from \"../client.ts\";\nimport { Room } from \"./room.ts\";\nimport { type CryptoBackend } from \"../common-crypto/CryptoBackend.ts\";\n\nexport enum RelationsEvent {\n Add = \"Relations.add\",\n Remove = \"Relations.remove\",\n Redaction = \"Relations.redaction\",\n}\n\nexport type EventHandlerMap = {\n [RelationsEvent.Add]: (event: MatrixEvent) => void;\n [RelationsEvent.Remove]: (event: MatrixEvent) => void;\n [RelationsEvent.Redaction]: (event: MatrixEvent) => void;\n};\n\nconst matchesEventType = (eventType: string, targetEventType: string, altTargetEventTypes: string[] = []): boolean =>\n [targetEventType, ...altTargetEventTypes].includes(eventType);\n\n/**\n * A container for relation events that supports easy access to common ways of\n * aggregating such events. Each instance holds events that of a single relation\n * type and event type. All of the events also relate to the same original event.\n *\n * The typical way to get one of these containers is via\n * EventTimelineSet#getRelationsForEvent.\n */\nexport class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap> {\n private relationEventIds = new Set<string>();\n private relations = new Set<MatrixEvent>();\n private annotationsByKey: Record<string, Set<MatrixEvent>> = {};\n private annotationsBySender: Record<string, Set<MatrixEvent>> = {};\n private sortedAnnotationsByKey: [string, Set<MatrixEvent>][] = [];\n private targetEvent: MatrixEvent | null = null;\n private creationEmitted = false;\n private replacementUpdateId = 0;\n private readonly client: MatrixClient;\n\n /**\n * @param relationType - The type of relation involved, such as \"m.annotation\", \"m.reference\", \"m.replace\", etc.\n * @param eventType - The relation event's type, such as \"m.reaction\", etc.\n * @param client - The client which created this instance. For backwards compatibility also accepts a Room.\n * @param altEventTypes - alt event types for relation events, for example to support unstable prefixed event types\n */\n public constructor(\n public readonly relationType: RelationType | string,\n public readonly eventType: string,\n client: MatrixClient | Room,\n public readonly altEventTypes?: string[],\n ) {\n super();\n this.client = client instanceof Room ? client.client : client;\n }\n\n /**\n * Add relation events to this collection.\n *\n * @param event - The new relation event to be added.\n */\n public async addEvent(event: MatrixEvent): Promise<void> {\n if (this.relationEventIds.has(event.getId()!)) {\n return;\n }\n\n const relation = event.getRelation();\n if (!relation) {\n logger.error(\"Event must have relation info\");\n return;\n }\n\n const relationType = relation.rel_type;\n const eventType = event.getType();\n\n if (this.relationType !== relationType || !matchesEventType(eventType, this.eventType, this.altEventTypes)) {\n logger.error(\"Event relation info doesn't match this container\");\n return;\n }\n\n // If the event is in the process of being sent, listen for cancellation\n // so we can remove the event from the collection.\n if (event.isSending()) {\n event.on(MatrixEventEvent.Status, this.onEventStatus);\n }\n\n this.relations.add(event);\n this.relationEventIds.add(event.getId()!);\n\n if (this.relationType === RelationType.Annotation) {\n this.addAnnotationToAggregation(event);\n } else if (this.relationType === RelationType.Replace) {\n await this.updateTargetEventReplacement();\n }\n\n event.on(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);\n\n this.emit(RelationsEvent.Add, event);\n\n this.maybeEmitCreated();\n }\n\n /**\n * Remove relation event from this collection.\n *\n * @param event - The relation event to remove.\n */\n public async removeEvent(event: MatrixEvent): Promise<void> {\n if (!this.relations.has(event)) {\n return;\n }\n\n this.relations.delete(event);\n\n if (this.relationType === RelationType.Annotation) {\n this.removeAnnotationFromAggregation(event);\n } else if (this.relationType === RelationType.Replace) {\n await this.updateTargetEventReplacement();\n }\n\n this.emit(RelationsEvent.Remove, event);\n }\n\n /**\n * Listens for event status changes to remove cancelled events.\n *\n * @param event - The event whose status has changed\n * @param status - The new status\n */\n private onEventStatus = (event: MatrixEvent, status: EventStatus | null): void => {\n if (!event.isSending()) {\n // Sending is done, so we don't need to listen anymore\n event.removeListener(MatrixEventEvent.Status, this.onEventStatus);\n return;\n }\n if (status !== EventStatus.CANCELLED) {\n return;\n }\n // Event was cancelled, remove from the collection\n event.removeListener(MatrixEventEvent.Status, this.onEventStatus);\n this.removeEvent(event);\n };\n\n /**\n * Get all relation events in this collection.\n *\n * These are currently in the order of insertion to this collection, which\n * won't match timeline order in the case of scrollback.\n * TODO: Tweak `addEvent` to insert correctly for scrollback.\n *\n * Relation events in insertion order.\n */\n public getRelations(): MatrixEvent[] {\n return [...this.relations];\n }\n\n private addAnnotationToAggregation(event: MatrixEvent): void {\n const { key } = event.getRelation() ?? {};\n if (!key) return;\n\n let eventsForKey = this.annotationsByKey[key];\n if (!eventsForKey) {\n eventsForKey = this.annotationsByKey[key] = new Set();\n this.sortedAnnotationsByKey.push([key, eventsForKey]);\n }\n // Add the new event to the set for this key\n eventsForKey.add(event);\n // Re-sort the [key, events] pairs in descending order of event count\n this.sortedAnnotationsByKey.sort((a, b) => {\n const aEvents = a[1];\n const bEvents = b[1];\n return bEvents.size - aEvents.size;\n });\n\n const sender = event.getSender()!;\n let eventsFromSender = this.annotationsBySender[sender];\n if (!eventsFromSender) {\n eventsFromSender = this.annotationsBySender[sender] = new Set();\n }\n // Add the new event to the set for this sender\n eventsFromSender.add(event);\n }\n\n private removeAnnotationFromAggregation(event: MatrixEvent): void {\n const { key } = event.getRelation() ?? {};\n if (!key) return;\n\n const eventsForKey = this.annotationsByKey[key];\n if (eventsForKey) {\n eventsForKey.delete(event);\n\n // Re-sort the [key, events] pairs in descending order of event count\n this.sortedAnnotationsByKey.sort((a, b) => {\n const aEvents = a[1];\n const bEvents = b[1];\n return bEvents.size - aEvents.size;\n });\n }\n\n const sender = event.getSender()!;\n const eventsFromSender = this.annotationsBySender[sender];\n if (eventsFromSender) {\n eventsFromSender.delete(event);\n }\n }\n\n /**\n * For relations that have been redacted, we want to remove them from\n * aggregation data sets and emit an update event.\n *\n * To do so, we listen for `Event.beforeRedaction`, which happens:\n * - after the server accepted the redaction and remote echoed back to us\n * - before the original event has been marked redacted in the client\n *\n * @param redactedEvent - The original relation event that is about to be redacted.\n */\n private onBeforeRedaction = async (redactedEvent: MatrixEvent): Promise<void> => {\n if (!this.relations.has(redactedEvent)) {\n return;\n }\n\n this.relations.delete(redactedEvent);\n\n if (this.relationType === RelationType.Annotation) {\n // Remove the redacted annotation from aggregation by key\n this.removeAnnotationFromAggregation(redactedEvent);\n } else if (this.relationType === RelationType.Replace) {\n await this.updateTargetEventReplacement();\n }\n\n redactedEvent.removeListener(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);\n\n this.emit(RelationsEvent.Redaction, redactedEvent);\n };\n\n /**\n * Get all events in this collection grouped by key and sorted by descending\n * event count in each group.\n *\n * This is currently only supported for the annotation relation type.\n *\n * An array of [key, events] pairs sorted by descending event count.\n * The events are stored in a Set (which preserves insertion order).\n */\n public getSortedAnnotationsByKey(): [string, Set<MatrixEvent>][] | null {\n if (this.relationType !== RelationType.Annotation) {\n // Other relation types are not grouped currently.\n return null;\n }\n\n return this.sortedAnnotationsByKey;\n }\n\n /**\n * Get all events in this collection grouped by sender.\n *\n * This is currently only supported for the annotation relation type.\n *\n * An object with each relation sender as a key and the matching Set of\n * events for that sender as a value.\n */\n public getAnnotationsBySender(): Record<string, Set<MatrixEvent>> | null {\n if (this.relationType !== RelationType.Annotation) {\n // Other relation types are not grouped currently.\n return null;\n }\n\n return this.annotationsBySender;\n }\n\n /**\n * Returns the most recent (and allowed) m.replace relation, if any.\n *\n * This is currently only supported for the m.replace relation type,\n * once the target event is known, see `addEvent`.\n */\n public async getLastReplacement(): Promise<MatrixEvent | null> {\n if (this.relationType !== RelationType.Replace) {\n // Aggregating on last only makes sense for this relation type\n return null;\n }\n if (!this.targetEvent) {\n // Don't know which replacements to accept yet.\n // This method shouldn't be called before the original\n // event is known anyway.\n return null;\n }\n\n // the all-knowning server tells us that the event at some point had\n // this timestamp for its replacement, so any following replacement should definitely not be less\n const replaceRelation = this.targetEvent.getServerAggregatedRelation<IAggregatedRelation>(RelationType.Replace);\n const minTs = replaceRelation?.origin_server_ts;\n\n const lastReplacement = this.getRelations().reduce<MatrixEvent | null>((last, event) => {\n if (event.getSender() !== this.targetEvent!.getSender()) {\n return last;\n }\n if (minTs && minTs > event.getTs()) {\n return last;\n }\n if (last && last.getTs() > event.getTs()) {\n return last;\n }\n return event;\n }, null);\n\n if (lastReplacement?.shouldAttemptDecryption() && this.client.getCrypto()) {\n // Dirty but we are expecting to pass the cryptoBackend which is not accessible here\n await lastReplacement.attemptDecryption(this.client.getCrypto() as CryptoBackend);\n } else if (lastReplacement?.isBeingDecrypted()) {\n await lastReplacement.getDecryptionPromise();\n }\n\n return lastReplacement;\n }\n\n /*\n * @param targetEvent - the event the relations are related to.\n */\n public async setTargetEvent(event: MatrixEvent): Promise<void> {\n if (this.targetEvent) {\n return;\n }\n this.targetEvent = event;\n\n if (this.relationType === RelationType.Replace) {\n await this.updateTargetEventReplacement();\n }\n\n this.maybeEmitCreated();\n }\n\n /**\n * Updates the target event with the latest replacement.\n *\n * Multiple replacement updates can be triggered concurrently (for example\n * while edits are still being decrypted). A monotonic update counter guards\n * against older async resolutions overriding newer replacement selections.\n */\n private async updateTargetEventReplacement(): Promise<void> {\n if (!this.targetEvent || this.targetEvent.isState()) {\n return;\n }\n\n const targetEvent = this.targetEvent;\n const updateId = ++this.replacementUpdateId;\n const lastReplacement = await this.getLastReplacement();\n\n // If a newer update started while we were awaiting, discard this stale result.\n if (updateId !== this.replacementUpdateId || this.targetEvent !== targetEvent) {\n return;\n }\n\n // Avoid emitting Event.replaced when there is no replacement and none currently set.\n if (!lastReplacement && !targetEvent.replacingEvent()) {\n return;\n }\n\n targetEvent.makeReplaced(lastReplacement ?? undefined);\n }\n\n private maybeEmitCreated(): void {\n if (this.creationEmitted) {\n return;\n }\n // Only emit we're \"created\" once we have a target event instance _and_\n // at least one related event.\n if (!this.targetEvent || !this.relations.size) {\n return;\n }\n this.creationEmitted = true;\n this.targetEvent.emit(MatrixEventEvent.RelationsCreated, this.relationType, this.eventType);\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -37,8 +37,6 @@ export class RoomMember extends TypedEventEmitter {
37
37
  */
38
38
  constructor(roomId, userId) {
39
39
  super();
40
- this.roomId = roomId;
41
- this.userId = userId;
42
40
  _defineProperty(this, "_isOutOfBand", false);
43
41
  _defineProperty(this, "modified", -1);
44
42
  _defineProperty(this, "requestedProfileInfo", false);
@@ -48,32 +46,10 @@ export class RoomMember extends TypedEventEmitter {
48
46
  * True if the room member is currently typing.
49
47
  */
50
48
  _defineProperty(this, "typing", false);
51
- /**
52
- * The human-readable name for this room member. Similar to {@link rawDisplayName}, but
53
- * disambiguated with a suffix of " (\@user_id:matrix.org)" if another member shares the
54
- * same displayname.
55
- */
56
- _defineProperty(this, "name", void 0);
57
- /**
58
- * The ambiguous displayname of this room member, with some preprocessing:
59
- *
60
- * * Direction override characters (RTO and LRO) are removed.
61
- * * If the displayname is empty, or contains only blank, non-printing, or diacritcic characters, it is
62
- * replaced with the user ID.
63
- */
64
- _defineProperty(this, "rawDisplayName", void 0);
65
49
  /**
66
50
  * The power level for this room member.
67
51
  */
68
52
  _defineProperty(this, "powerLevel", 0);
69
- /**
70
- * The User object for this room member, if one exists.
71
- */
72
- _defineProperty(this, "user", void 0);
73
- /**
74
- * The membership state for this room member e.g. 'join'.
75
- */
76
- _defineProperty(this, "membership", void 0);
77
53
  /**
78
54
  * True if the member's name is disambiguated.
79
55
  */
@@ -82,6 +58,8 @@ export class RoomMember extends TypedEventEmitter {
82
58
  * The events describing this RoomMember.
83
59
  */
84
60
  _defineProperty(this, "events", {});
61
+ this.roomId = roomId;
62
+ this.userId = userId;
85
63
  this.name = userId;
86
64
  this.rawDisplayName = userId;
87
65
  this.updateModifiedTime();
@@ -1 +1 @@
1
- {"version":3,"file":"room-member.js","names":["getHttpUriForMxc","removeDirectionOverrideChars","removeHiddenChars","logger","TypedEventEmitter","EventType","KnownMembership","RoomMemberEvent","RoomMember","constructor","roomId","userId","_defineProperty","name","rawDisplayName","updateModifiedTime","markOutOfBand","_isOutOfBand","isOutOfBand","setMembershipEvent","event","roomState","_event$getDirectional","_event$getDirectional2","displayName","getDirectionalContent","displayname","getType","events","member","oldMembership","membership","undefined","trace","concat","forwardLooking","getContent","getPrevContent","disambiguate","shouldDisambiguate","oldName","calculateDisplayName","emit","Membership","Name","recalculateDisambiguatedName","_this$events$member$g","newDisambiguate","setPowerLevel","powerLevel","powerLevelEvent","oldPowerLevel","PowerLevel","setTypingEvent","oldTyping","typing","typingList","user_ids","Array","isArray","indexOf","Typing","modified","Date","now","getLastModifiedTime","isKicked","Leave","getSender","getStateKey","getDMInviter","memberEvent","memberContent","inviteSender","Join","getUnsigned","prev_sender","Invite","is_direct","getAvatarUrl","baseUrl","width","height","resizeMethod","allowDefault","arguments","length","allowDirectLinks","useAuthentication","rawUrl","getMxcAvatarUrl","httpUrl","avatar_url","user","avatarUrl","MXID_PATTERN","LTR_RTL_PATTERN","selfUserId","strippedDisplayName","test","userIds","getUserIdsWithDisplayName","some","u"],"sources":["../../src/models/room-member.ts"],"sourcesContent":["/*\nCopyright 2015 - 2021 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { getHttpUriForMxc } from \"../content-repo.ts\";\nimport { removeDirectionOverrideChars, removeHiddenChars } from \"../utils.ts\";\nimport { type User } from \"./user.ts\";\nimport { type MatrixEvent } from \"./event.ts\";\nimport { type RoomState } from \"./room-state.ts\";\nimport { logger } from \"../logger.ts\";\nimport { TypedEventEmitter } from \"./typed-event-emitter.ts\";\nimport { EventType } from \"../@types/event.ts\";\nimport { KnownMembership, type Membership } from \"../@types/membership.ts\";\n\nexport enum RoomMemberEvent {\n Membership = \"RoomMember.membership\",\n Name = \"RoomMember.name\",\n PowerLevel = \"RoomMember.powerLevel\",\n Typing = \"RoomMember.typing\",\n}\n\nexport type RoomMemberEventHandlerMap = {\n /**\n * Fires whenever any room member's membership state changes.\n * @param event - The matrix event which caused this event to fire.\n * @param member - The member whose RoomMember.membership changed.\n * @param oldMembership - The previous membership state. Null if it's a new member.\n * @example\n * ```\n * matrixClient.on(\"RoomMember.membership\", function(event, member, oldMembership){\n * var newState = member.membership;\n * });\n * ```\n */\n [RoomMemberEvent.Membership]: (event: MatrixEvent, member: RoomMember, oldMembership?: string) => void;\n /**\n * Fires whenever any room member's name changes.\n * @param event - The matrix event which caused this event to fire.\n * @param member - The member whose RoomMember.name changed.\n * @param oldName - The previous name. Null if the member didn't have a name previously.\n * @example\n * ```\n * matrixClient.on(\"RoomMember.name\", function(event, member){\n * var newName = member.name;\n * });\n * ```\n */\n [RoomMemberEvent.Name]: (event: MatrixEvent, member: RoomMember, oldName: string | null) => void;\n /**\n * Fires whenever any room member's power level changes.\n * @param event - The matrix event which caused this event to fire.\n * @param member - The member whose RoomMember.powerLevel changed.\n * @example\n * ```\n * matrixClient.on(\"RoomMember.powerLevel\", function(event, member){\n * var newPowerLevel = member.powerLevel;\n * });\n * ```\n */\n [RoomMemberEvent.PowerLevel]: (event: MatrixEvent, member: RoomMember) => void;\n /**\n * Fires whenever any room member's typing state changes.\n * @param event - The matrix event which caused this event to fire.\n * @param member - The member whose RoomMember.typing changed.\n * @example\n * ```\n * matrixClient.on(\"RoomMember.typing\", function(event, member){\n * var isTyping = member.typing;\n * });\n * ```\n */\n [RoomMemberEvent.Typing]: (event: MatrixEvent, member: RoomMember) => void;\n};\n\nexport class RoomMember extends TypedEventEmitter<RoomMemberEvent, RoomMemberEventHandlerMap> {\n private _isOutOfBand = false;\n private modified = -1;\n public requestedProfileInfo = false; // used by sync.ts\n\n // XXX these should be read-only\n /**\n * True if the room member is currently typing.\n */\n public typing = false;\n\n /**\n * The human-readable name for this room member. Similar to {@link rawDisplayName}, but\n * disambiguated with a suffix of \" (\\@user_id:matrix.org)\" if another member shares the\n * same displayname.\n */\n public name: string;\n\n /**\n * The ambiguous displayname of this room member, with some preprocessing:\n *\n * * Direction override characters (RTO and LRO) are removed.\n * * If the displayname is empty, or contains only blank, non-printing, or diacritcic characters, it is\n * replaced with the user ID.\n */\n public rawDisplayName: string;\n\n /**\n * The power level for this room member.\n */\n public powerLevel = 0;\n /**\n * The User object for this room member, if one exists.\n */\n public user?: User;\n /**\n * The membership state for this room member e.g. 'join'.\n */\n public membership?: Membership;\n /**\n * True if the member's name is disambiguated.\n */\n public disambiguate = false;\n /**\n * The events describing this RoomMember.\n */\n public events: {\n /**\n * The m.room.member event for this RoomMember.\n */\n member?: MatrixEvent;\n } = {};\n\n /**\n * Construct a new room member.\n *\n * @param roomId - The room ID of the member.\n * @param userId - The user ID of the member.\n */\n public constructor(\n public readonly roomId: string,\n public readonly userId: string,\n ) {\n super();\n\n this.name = userId;\n this.rawDisplayName = userId;\n this.updateModifiedTime();\n }\n\n /**\n * Mark the member as coming from a channel that is not sync\n */\n public markOutOfBand(): void {\n this._isOutOfBand = true;\n }\n\n /**\n * @returns does the member come from a channel that is not sync?\n * This is used to store the member seperately\n * from the sync state so it available across browser sessions.\n */\n public isOutOfBand(): boolean {\n return this._isOutOfBand;\n }\n\n /**\n * Update this room member's membership event. May fire \"RoomMember.name\" if\n * this event updates this member's name.\n * @param event - The `m.room.member` event\n * @param roomState - Optional. The room state to take into account\n * when calculating (e.g. for disambiguating users with the same name).\n *\n * @remarks\n * Fires {@link RoomMemberEvent.Name}\n * Fires {@link RoomMemberEvent.Membership}\n */\n public setMembershipEvent(event: MatrixEvent, roomState?: RoomState): void {\n const displayName = event.getDirectionalContent().displayname ?? \"\";\n\n if (event.getType() !== EventType.RoomMember) {\n return;\n }\n\n this._isOutOfBand = false;\n\n this.events.member = event;\n\n const oldMembership = this.membership;\n this.membership = event.getDirectionalContent().membership;\n if (this.membership === undefined) {\n // logging to diagnose https://github.com/vector-im/element-web/issues/20962\n // (logs event content, although only of membership events)\n logger.trace(\n `membership event with membership undefined (forwardLooking: ${event.forwardLooking})!`,\n event.getContent(),\n `prevcontent is `,\n event.getPrevContent(),\n );\n }\n\n this.disambiguate = shouldDisambiguate(this.userId, displayName, roomState);\n\n const oldName = this.name;\n this.name = calculateDisplayName(this.userId, displayName, this.disambiguate);\n\n // not quite raw: we strip direction override chars so it can safely be inserted into\n // blocks of text without breaking the text direction\n this.rawDisplayName = removeDirectionOverrideChars(event.getDirectionalContent().displayname ?? \"\");\n if (!this.rawDisplayName || !removeHiddenChars(this.rawDisplayName)) {\n this.rawDisplayName = this.userId;\n }\n\n if (oldMembership !== this.membership) {\n this.updateModifiedTime();\n this.emit(RoomMemberEvent.Membership, event, this, oldMembership);\n }\n if (oldName !== this.name) {\n this.updateModifiedTime();\n this.emit(RoomMemberEvent.Name, event, this, oldName);\n }\n }\n\n /**\n * Recalculate the disambiguation flag for this member based on current room state.\n * This should be called when another member's display name changes and may affect\n * whether this member needs disambiguation.\n *\n * @param roomState - The current room state to use for disambiguation check\n * @returns true if the member's name changed as a result of the disambiguation update\n *\n * @remarks\n * Fires {@link RoomMemberEvent.Name}\n */\n public recalculateDisambiguatedName(roomState: RoomState): boolean {\n if (!this.events.member) {\n return false;\n }\n\n const displayName = this.events.member.getDirectionalContent().displayname ?? \"\";\n const newDisambiguate = shouldDisambiguate(this.userId, displayName, roomState);\n\n if (newDisambiguate === this.disambiguate) {\n return false;\n }\n\n this.disambiguate = newDisambiguate;\n const oldName = this.name;\n this.name = calculateDisplayName(this.userId, displayName, this.disambiguate);\n\n if (oldName !== this.name) {\n this.updateModifiedTime();\n this.emit(RoomMemberEvent.Name, this.events.member, this, oldName);\n return true;\n }\n\n return false;\n }\n\n /**\n * Update this room member's power level event. Will fire\n * \"RoomMember.powerLevel\" if the new power level is different\n * @param powerLevel - The power level of the room member.\n *\n * @remarks\n * Fires {@link RoomMemberEvent.PowerLevel}\n */\n public setPowerLevel(powerLevel: number, powerLevelEvent: MatrixEvent): void {\n const oldPowerLevel = this.powerLevel;\n this.powerLevel = powerLevel;\n\n if (oldPowerLevel !== this.powerLevel) {\n this.updateModifiedTime();\n this.emit(RoomMemberEvent.PowerLevel, powerLevelEvent, this);\n }\n }\n\n /**\n * Update this room member's typing event. May fire \"RoomMember.typing\" if\n * this event changes this member's typing state.\n * @param event - The typing event\n *\n * @remarks\n * Fires {@link RoomMemberEvent.Typing}\n */\n public setTypingEvent(event: MatrixEvent): void {\n if (event.getType() !== \"m.typing\") {\n return;\n }\n const oldTyping = this.typing;\n this.typing = false;\n const typingList = event.getContent().user_ids;\n if (!Array.isArray(typingList)) {\n // malformed event :/ bail early. TODO: whine?\n return;\n }\n if (typingList.indexOf(this.userId) !== -1) {\n this.typing = true;\n }\n if (oldTyping !== this.typing) {\n this.updateModifiedTime();\n this.emit(RoomMemberEvent.Typing, event, this);\n }\n }\n\n /**\n * Update the last modified time to the current time.\n */\n private updateModifiedTime(): void {\n this.modified = Date.now();\n }\n\n /**\n * Get the timestamp when this RoomMember was last updated. This timestamp is\n * updated when properties on this RoomMember are updated.\n * It is updated <i>before</i> firing events.\n * @returns The timestamp\n */\n public getLastModifiedTime(): number {\n return this.modified;\n }\n\n public isKicked(): boolean {\n return (\n this.membership === KnownMembership.Leave &&\n this.events.member !== undefined &&\n this.events.member.getSender() !== this.events.member.getStateKey()\n );\n }\n\n /**\n * If this member was invited with the is_direct flag set, return\n * the user that invited this member\n * @returns user id of the inviter\n */\n public getDMInviter(): string | undefined {\n // when not available because that room state hasn't been loaded in,\n // we don't really know, but more likely to not be a direct chat\n if (this.events.member) {\n // TODO: persist the is_direct flag on the member as more member events\n // come in caused by displayName changes.\n\n // the is_direct flag is set on the invite member event.\n // This is copied on the prev_content section of the join member event\n // when the invite is accepted.\n\n const memberEvent = this.events.member;\n let memberContent = memberEvent.getContent();\n let inviteSender: string | undefined = memberEvent.getSender();\n\n if (memberContent.membership === KnownMembership.Join) {\n memberContent = memberEvent.getPrevContent();\n inviteSender = memberEvent.getUnsigned().prev_sender;\n }\n\n if (memberContent.membership === KnownMembership.Invite && memberContent.is_direct) {\n return inviteSender;\n }\n }\n }\n\n /**\n * Get the avatar URL for a room member.\n * @param baseUrl - The base homeserver URL See\n * {@link MatrixClient#getHomeserverUrl}.\n * @param width - The desired width of the thumbnail.\n * @param height - The desired height of the thumbnail.\n * @param resizeMethod - The thumbnail resize method to use, either\n * \"crop\" or \"scale\".\n * @param allowDefault - (optional) Passing false causes this method to\n * return null if the user has no avatar image. Otherwise, a default image URL\n * will be returned. Default: true. (Deprecated)\n * @param allowDirectLinks - (optional) If true, the avatar URL will be\n * returned even if it is a direct hyperlink rather than a matrix content URL.\n * If false, any non-matrix content URLs will be ignored. Setting this option to\n * true will expose URLs that, if fetched, will leak information about the user\n * to anyone who they share a room with.\n * @param useAuthentication - (optional) If true, the caller supports authenticated\n * media and wants an authentication-required URL. Note that server support for\n * authenticated media will not be checked - it is the caller's responsibility\n * to do so before calling this function. Note also that useAuthentication\n * implies allowRedirects. Defaults to false (unauthenticated endpoints).\n * @returns the avatar URL or null.\n */\n public getAvatarUrl(\n baseUrl: string,\n width: number,\n height: number,\n resizeMethod: string,\n allowDefault = true,\n allowDirectLinks: boolean,\n useAuthentication: boolean = false,\n ): string | null {\n const rawUrl = this.getMxcAvatarUrl();\n\n if (!rawUrl && !allowDefault) {\n return null;\n }\n const httpUrl = getHttpUriForMxc(\n baseUrl,\n rawUrl,\n width,\n height,\n resizeMethod,\n allowDirectLinks,\n undefined,\n useAuthentication,\n );\n if (httpUrl) {\n return httpUrl;\n }\n return null;\n }\n\n /**\n * get the mxc avatar url, either from a state event, or from a lazily loaded member\n * @returns the mxc avatar url\n */\n public getMxcAvatarUrl(): string | undefined {\n if (this.events.member) {\n return this.events.member.getDirectionalContent().avatar_url;\n } else if (this.user) {\n return this.user.avatarUrl;\n }\n }\n}\n\nexport const MXID_PATTERN = /@.+:.+/;\nconst LTR_RTL_PATTERN = /[\\u200E\\u200F\\u202A-\\u202F]/;\n\nfunction shouldDisambiguate(selfUserId: string, displayName?: string, roomState?: RoomState): boolean {\n if (!displayName || displayName === selfUserId) return false;\n if (!roomState) return false;\n\n const strippedDisplayName = removeHiddenChars(displayName);\n\n // First check if the displayname is something we consider truthy\n // after stripping it of zero width characters and padding spaces\n if (!strippedDisplayName) return false;\n\n // Next check if the name contains something that look like a mxid\n // If it does, it may be someone trying to impersonate someone else\n // Show full mxid in this case\n if (MXID_PATTERN.test(strippedDisplayName)) return true;\n\n // Also show mxid if the display name contains any LTR/RTL characters as these\n // make it very difficult for us to find similar *looking* display names\n // E.g \"Mark\" could be cloned by writing \"kraM\" but in RTL.\n if (LTR_RTL_PATTERN.test(displayName)) return true;\n\n // Also show mxid if there are other people with the same or similar\n // displayname, after hidden character removal.\n const userIds = roomState.getUserIdsWithDisplayName(displayName);\n if (userIds.some((u) => u !== selfUserId)) return true;\n\n return false;\n}\n\nfunction calculateDisplayName(selfUserId: string, displayName: string | undefined, disambiguate: boolean): string {\n if (!displayName || displayName === selfUserId) return selfUserId;\n\n if (disambiguate) return removeDirectionOverrideChars(displayName) + \" (\" + selfUserId + \")\";\n\n // First check if the displayname is something we consider truthy\n // after stripping it of zero width characters and padding spaces\n if (!removeHiddenChars(displayName)) return selfUserId;\n\n // We always strip the direction override characters (LRO and RLO).\n // These override the text direction for all subsequent characters\n // in the paragraph so if display names contained these, they'd\n // need to be wrapped in something to prevent this from leaking out\n // (which we can do in HTML but not text) or we'd need to add\n // control characters to the string to reset any overrides (eg.\n // adding PDF characters at the end). As far as we can see,\n // there should be no reason these would be necessary - rtl display\n // names should flip into the correct direction automatically based on\n // the characters, and you can still embed rtl in ltr or vice versa\n // with the embed chars or marker chars.\n return removeDirectionOverrideChars(displayName);\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"room-member.js","names":["getHttpUriForMxc","removeDirectionOverrideChars","removeHiddenChars","logger","TypedEventEmitter","EventType","KnownMembership","RoomMemberEvent","RoomMember","constructor","roomId","userId","_defineProperty","name","rawDisplayName","updateModifiedTime","markOutOfBand","_isOutOfBand","isOutOfBand","setMembershipEvent","event","roomState","_event$getDirectional","_event$getDirectional2","displayName","getDirectionalContent","displayname","getType","events","member","oldMembership","membership","undefined","trace","concat","forwardLooking","getContent","getPrevContent","disambiguate","shouldDisambiguate","oldName","calculateDisplayName","emit","Membership","Name","recalculateDisambiguatedName","_this$events$member$g","newDisambiguate","setPowerLevel","powerLevel","powerLevelEvent","oldPowerLevel","PowerLevel","setTypingEvent","oldTyping","typing","typingList","user_ids","Array","isArray","indexOf","Typing","modified","Date","now","getLastModifiedTime","isKicked","Leave","getSender","getStateKey","getDMInviter","memberEvent","memberContent","inviteSender","Join","getUnsigned","prev_sender","Invite","is_direct","getAvatarUrl","baseUrl","width","height","resizeMethod","allowDefault","arguments","length","allowDirectLinks","useAuthentication","rawUrl","getMxcAvatarUrl","httpUrl","avatar_url","user","avatarUrl","MXID_PATTERN","LTR_RTL_PATTERN","selfUserId","strippedDisplayName","test","userIds","getUserIdsWithDisplayName","some","u"],"sources":["../../src/models/room-member.ts"],"sourcesContent":["/*\nCopyright 2015 - 2021 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { getHttpUriForMxc } from \"../content-repo.ts\";\nimport { removeDirectionOverrideChars, removeHiddenChars } from \"../utils.ts\";\nimport { type User } from \"./user.ts\";\nimport { type MatrixEvent } from \"./event.ts\";\nimport { type RoomState } from \"./room-state.ts\";\nimport { logger } from \"../logger.ts\";\nimport { TypedEventEmitter } from \"./typed-event-emitter.ts\";\nimport { EventType } from \"../@types/event.ts\";\nimport { KnownMembership, type Membership } from \"../@types/membership.ts\";\n\nexport enum RoomMemberEvent {\n Membership = \"RoomMember.membership\",\n Name = \"RoomMember.name\",\n PowerLevel = \"RoomMember.powerLevel\",\n Typing = \"RoomMember.typing\",\n}\n\nexport type RoomMemberEventHandlerMap = {\n /**\n * Fires whenever any room member's membership state changes.\n * @param event - The matrix event which caused this event to fire.\n * @param member - The member whose RoomMember.membership changed.\n * @param oldMembership - The previous membership state. Null if it's a new member.\n * @example\n * ```\n * matrixClient.on(\"RoomMember.membership\", function(event, member, oldMembership){\n * var newState = member.membership;\n * });\n * ```\n */\n [RoomMemberEvent.Membership]: (event: MatrixEvent, member: RoomMember, oldMembership?: string) => void;\n /**\n * Fires whenever any room member's name changes.\n * @param event - The matrix event which caused this event to fire.\n * @param member - The member whose RoomMember.name changed.\n * @param oldName - The previous name. Null if the member didn't have a name previously.\n * @example\n * ```\n * matrixClient.on(\"RoomMember.name\", function(event, member){\n * var newName = member.name;\n * });\n * ```\n */\n [RoomMemberEvent.Name]: (event: MatrixEvent, member: RoomMember, oldName: string | null) => void;\n /**\n * Fires whenever any room member's power level changes.\n * @param event - The matrix event which caused this event to fire.\n * @param member - The member whose RoomMember.powerLevel changed.\n * @example\n * ```\n * matrixClient.on(\"RoomMember.powerLevel\", function(event, member){\n * var newPowerLevel = member.powerLevel;\n * });\n * ```\n */\n [RoomMemberEvent.PowerLevel]: (event: MatrixEvent, member: RoomMember) => void;\n /**\n * Fires whenever any room member's typing state changes.\n * @param event - The matrix event which caused this event to fire.\n * @param member - The member whose RoomMember.typing changed.\n * @example\n * ```\n * matrixClient.on(\"RoomMember.typing\", function(event, member){\n * var isTyping = member.typing;\n * });\n * ```\n */\n [RoomMemberEvent.Typing]: (event: MatrixEvent, member: RoomMember) => void;\n};\n\nexport class RoomMember extends TypedEventEmitter<RoomMemberEvent, RoomMemberEventHandlerMap> {\n private _isOutOfBand = false;\n private modified = -1;\n public requestedProfileInfo = false; // used by sync.ts\n\n // XXX these should be read-only\n /**\n * True if the room member is currently typing.\n */\n public typing = false;\n\n /**\n * The human-readable name for this room member. Similar to {@link rawDisplayName}, but\n * disambiguated with a suffix of \" (\\@user_id:matrix.org)\" if another member shares the\n * same displayname.\n */\n public name: string;\n\n /**\n * The ambiguous displayname of this room member, with some preprocessing:\n *\n * * Direction override characters (RTO and LRO) are removed.\n * * If the displayname is empty, or contains only blank, non-printing, or diacritcic characters, it is\n * replaced with the user ID.\n */\n public rawDisplayName: string;\n\n /**\n * The power level for this room member.\n */\n public powerLevel = 0;\n /**\n * The User object for this room member, if one exists.\n */\n public user?: User;\n /**\n * The membership state for this room member e.g. 'join'.\n */\n public membership?: Membership;\n /**\n * True if the member's name is disambiguated.\n */\n public disambiguate = false;\n /**\n * The events describing this RoomMember.\n */\n public events: {\n /**\n * The m.room.member event for this RoomMember.\n */\n member?: MatrixEvent;\n } = {};\n\n /**\n * Construct a new room member.\n *\n * @param roomId - The room ID of the member.\n * @param userId - The user ID of the member.\n */\n public constructor(\n public readonly roomId: string,\n public readonly userId: string,\n ) {\n super();\n\n this.name = userId;\n this.rawDisplayName = userId;\n this.updateModifiedTime();\n }\n\n /**\n * Mark the member as coming from a channel that is not sync\n */\n public markOutOfBand(): void {\n this._isOutOfBand = true;\n }\n\n /**\n * @returns does the member come from a channel that is not sync?\n * This is used to store the member seperately\n * from the sync state so it available across browser sessions.\n */\n public isOutOfBand(): boolean {\n return this._isOutOfBand;\n }\n\n /**\n * Update this room member's membership event. May fire \"RoomMember.name\" if\n * this event updates this member's name.\n * @param event - The `m.room.member` event\n * @param roomState - Optional. The room state to take into account\n * when calculating (e.g. for disambiguating users with the same name).\n *\n * @remarks\n * Fires {@link RoomMemberEvent.Name}\n * Fires {@link RoomMemberEvent.Membership}\n */\n public setMembershipEvent(event: MatrixEvent, roomState?: RoomState): void {\n const displayName = event.getDirectionalContent().displayname ?? \"\";\n\n if (event.getType() !== EventType.RoomMember) {\n return;\n }\n\n this._isOutOfBand = false;\n\n this.events.member = event;\n\n const oldMembership = this.membership;\n this.membership = event.getDirectionalContent().membership;\n if (this.membership === undefined) {\n // logging to diagnose https://github.com/vector-im/element-web/issues/20962\n // (logs event content, although only of membership events)\n logger.trace(\n `membership event with membership undefined (forwardLooking: ${event.forwardLooking})!`,\n event.getContent(),\n `prevcontent is `,\n event.getPrevContent(),\n );\n }\n\n this.disambiguate = shouldDisambiguate(this.userId, displayName, roomState);\n\n const oldName = this.name;\n this.name = calculateDisplayName(this.userId, displayName, this.disambiguate);\n\n // not quite raw: we strip direction override chars so it can safely be inserted into\n // blocks of text without breaking the text direction\n this.rawDisplayName = removeDirectionOverrideChars(event.getDirectionalContent().displayname ?? \"\");\n if (!this.rawDisplayName || !removeHiddenChars(this.rawDisplayName)) {\n this.rawDisplayName = this.userId;\n }\n\n if (oldMembership !== this.membership) {\n this.updateModifiedTime();\n this.emit(RoomMemberEvent.Membership, event, this, oldMembership);\n }\n if (oldName !== this.name) {\n this.updateModifiedTime();\n this.emit(RoomMemberEvent.Name, event, this, oldName);\n }\n }\n\n /**\n * Recalculate the disambiguation flag for this member based on current room state.\n * This should be called when another member's display name changes and may affect\n * whether this member needs disambiguation.\n *\n * @param roomState - The current room state to use for disambiguation check\n * @returns true if the member's name changed as a result of the disambiguation update\n *\n * @remarks\n * Fires {@link RoomMemberEvent.Name}\n */\n public recalculateDisambiguatedName(roomState: RoomState): boolean {\n if (!this.events.member) {\n return false;\n }\n\n const displayName = this.events.member.getDirectionalContent().displayname ?? \"\";\n const newDisambiguate = shouldDisambiguate(this.userId, displayName, roomState);\n\n if (newDisambiguate === this.disambiguate) {\n return false;\n }\n\n this.disambiguate = newDisambiguate;\n const oldName = this.name;\n this.name = calculateDisplayName(this.userId, displayName, this.disambiguate);\n\n if (oldName !== this.name) {\n this.updateModifiedTime();\n this.emit(RoomMemberEvent.Name, this.events.member, this, oldName);\n return true;\n }\n\n return false;\n }\n\n /**\n * Update this room member's power level event. Will fire\n * \"RoomMember.powerLevel\" if the new power level is different\n * @param powerLevel - The power level of the room member.\n *\n * @remarks\n * Fires {@link RoomMemberEvent.PowerLevel}\n */\n public setPowerLevel(powerLevel: number, powerLevelEvent: MatrixEvent): void {\n const oldPowerLevel = this.powerLevel;\n this.powerLevel = powerLevel;\n\n if (oldPowerLevel !== this.powerLevel) {\n this.updateModifiedTime();\n this.emit(RoomMemberEvent.PowerLevel, powerLevelEvent, this);\n }\n }\n\n /**\n * Update this room member's typing event. May fire \"RoomMember.typing\" if\n * this event changes this member's typing state.\n * @param event - The typing event\n *\n * @remarks\n * Fires {@link RoomMemberEvent.Typing}\n */\n public setTypingEvent(event: MatrixEvent): void {\n if (event.getType() !== \"m.typing\") {\n return;\n }\n const oldTyping = this.typing;\n this.typing = false;\n const typingList = event.getContent().user_ids;\n if (!Array.isArray(typingList)) {\n // malformed event :/ bail early. TODO: whine?\n return;\n }\n if (typingList.indexOf(this.userId) !== -1) {\n this.typing = true;\n }\n if (oldTyping !== this.typing) {\n this.updateModifiedTime();\n this.emit(RoomMemberEvent.Typing, event, this);\n }\n }\n\n /**\n * Update the last modified time to the current time.\n */\n private updateModifiedTime(): void {\n this.modified = Date.now();\n }\n\n /**\n * Get the timestamp when this RoomMember was last updated. This timestamp is\n * updated when properties on this RoomMember are updated.\n * It is updated <i>before</i> firing events.\n * @returns The timestamp\n */\n public getLastModifiedTime(): number {\n return this.modified;\n }\n\n public isKicked(): boolean {\n return (\n this.membership === KnownMembership.Leave &&\n this.events.member !== undefined &&\n this.events.member.getSender() !== this.events.member.getStateKey()\n );\n }\n\n /**\n * If this member was invited with the is_direct flag set, return\n * the user that invited this member\n * @returns user id of the inviter\n */\n public getDMInviter(): string | undefined {\n // when not available because that room state hasn't been loaded in,\n // we don't really know, but more likely to not be a direct chat\n if (this.events.member) {\n // TODO: persist the is_direct flag on the member as more member events\n // come in caused by displayName changes.\n\n // the is_direct flag is set on the invite member event.\n // This is copied on the prev_content section of the join member event\n // when the invite is accepted.\n\n const memberEvent = this.events.member;\n let memberContent = memberEvent.getContent();\n let inviteSender: string | undefined = memberEvent.getSender();\n\n if (memberContent.membership === KnownMembership.Join) {\n memberContent = memberEvent.getPrevContent();\n inviteSender = memberEvent.getUnsigned().prev_sender;\n }\n\n if (memberContent.membership === KnownMembership.Invite && memberContent.is_direct) {\n return inviteSender;\n }\n }\n }\n\n /**\n * Get the avatar URL for a room member.\n * @param baseUrl - The base homeserver URL See\n * {@link MatrixClient#getHomeserverUrl}.\n * @param width - The desired width of the thumbnail.\n * @param height - The desired height of the thumbnail.\n * @param resizeMethod - The thumbnail resize method to use, either\n * \"crop\" or \"scale\".\n * @param allowDefault - (optional) Passing false causes this method to\n * return null if the user has no avatar image. Otherwise, a default image URL\n * will be returned. Default: true. (Deprecated)\n * @param allowDirectLinks - (optional) If true, the avatar URL will be\n * returned even if it is a direct hyperlink rather than a matrix content URL.\n * If false, any non-matrix content URLs will be ignored. Setting this option to\n * true will expose URLs that, if fetched, will leak information about the user\n * to anyone who they share a room with.\n * @param useAuthentication - (optional) If true, the caller supports authenticated\n * media and wants an authentication-required URL. Note that server support for\n * authenticated media will not be checked - it is the caller's responsibility\n * to do so before calling this function. Note also that useAuthentication\n * implies allowRedirects. Defaults to false (unauthenticated endpoints).\n * @returns the avatar URL or null.\n */\n public getAvatarUrl(\n baseUrl: string,\n width: number,\n height: number,\n resizeMethod: string,\n allowDefault = true,\n allowDirectLinks: boolean,\n useAuthentication: boolean = false,\n ): string | null {\n const rawUrl = this.getMxcAvatarUrl();\n\n if (!rawUrl && !allowDefault) {\n return null;\n }\n const httpUrl = getHttpUriForMxc(\n baseUrl,\n rawUrl,\n width,\n height,\n resizeMethod,\n allowDirectLinks,\n undefined,\n useAuthentication,\n );\n if (httpUrl) {\n return httpUrl;\n }\n return null;\n }\n\n /**\n * get the mxc avatar url, either from a state event, or from a lazily loaded member\n * @returns the mxc avatar url\n */\n public getMxcAvatarUrl(): string | undefined {\n if (this.events.member) {\n return this.events.member.getDirectionalContent().avatar_url;\n } else if (this.user) {\n return this.user.avatarUrl;\n }\n }\n}\n\nexport const MXID_PATTERN = /@.+:.+/;\nconst LTR_RTL_PATTERN = /[\\u200E\\u200F\\u202A-\\u202F]/;\n\nfunction shouldDisambiguate(selfUserId: string, displayName?: string, roomState?: RoomState): boolean {\n if (!displayName || displayName === selfUserId) return false;\n if (!roomState) return false;\n\n const strippedDisplayName = removeHiddenChars(displayName);\n\n // First check if the displayname is something we consider truthy\n // after stripping it of zero width characters and padding spaces\n if (!strippedDisplayName) return false;\n\n // Next check if the name contains something that look like a mxid\n // If it does, it may be someone trying to impersonate someone else\n // Show full mxid in this case\n if (MXID_PATTERN.test(strippedDisplayName)) return true;\n\n // Also show mxid if the display name contains any LTR/RTL characters as these\n // make it very difficult for us to find similar *looking* display names\n // E.g \"Mark\" could be cloned by writing \"kraM\" but in RTL.\n if (LTR_RTL_PATTERN.test(displayName)) return true;\n\n // Also show mxid if there are other people with the same or similar\n // displayname, after hidden character removal.\n const userIds = roomState.getUserIdsWithDisplayName(displayName);\n if (userIds.some((u) => u !== selfUserId)) return true;\n\n return false;\n}\n\nfunction calculateDisplayName(selfUserId: string, displayName: string | undefined, disambiguate: boolean): string {\n if (!displayName || displayName === selfUserId) return selfUserId;\n\n if (disambiguate) return removeDirectionOverrideChars(displayName) + \" (\" + selfUserId + \")\";\n\n // First check if the displayname is something we consider truthy\n // after stripping it of zero width characters and padding spaces\n if (!removeHiddenChars(displayName)) return selfUserId;\n\n // We always strip the direction override characters (LRO and RLO).\n // These override the text direction for all subsequent characters\n // in the paragraph so if display names contained these, they'd\n // need to be wrapped in something to prevent this from leaking out\n // (which we can do in HTML but not text) or we'd need to add\n // control characters to the string to reset any overrides (eg.\n // adding PDF characters at the end). As far as we can see,\n // there should be no reason these would be necessary - rtl display\n // names should flip into the correct direction automatically based on\n // the characters, and you can still embed rtl in ltr or vice versa\n // with the embed chars or marker chars.\n return removeDirectionOverrideChars(displayName);\n}\n"],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,gBAAgB,QAAQ,oBAAoB;AACrD,SAASC,4BAA4B,EAAEC,iBAAiB,QAAQ,aAAa;AAI7E,SAASC,MAAM,QAAQ,cAAc;AACrC,SAASC,iBAAiB,QAAQ,0BAA0B;AAC5D,SAASC,SAAS,QAAQ,oBAAoB;AAC9C,SAASC,eAAe,QAAyB,yBAAyB;AAE1E,WAAYC,eAAe,0BAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAA,OAAfA,eAAe;AAAA;AA4D3B,OAAO,MAAMC,UAAU,SAASJ,iBAAiB,CAA6C;EAqD1F;AACJ;AACA;AACA;AACA;AACA;EACWK,WAAWA,CACEC,MAAc,EACdC,MAAc,EAChC;IACE,KAAK,CAAC,CAAC;IAACC,eAAA,uBA9DW,KAAK;IAAAA,eAAA,mBACT,CAAC,CAAC;IAAAA,eAAA,+BACS,KAAK;IAAE;IAErC;IACA;AACJ;AACA;IAFIA,eAAA,iBAGgB,KAAK;IAkBrB;AACJ;AACA;IAFIA,eAAA,qBAGoB,CAAC;IASrB;AACJ;AACA;IAFIA,eAAA,uBAGsB,KAAK;IAC3B;AACJ;AACA;IAFIA,eAAA,iBAQI,CAAC,CAAC;IAAA,KAScF,MAAc,GAAdA,MAAc;IAAA,KACdC,MAAc,GAAdA,MAAc;IAI9B,IAAI,CAACE,IAAI,GAAGF,MAAM;IAClB,IAAI,CAACG,cAAc,GAAGH,MAAM;IAC5B,IAAI,CAACI,kBAAkB,CAAC,CAAC;EAC7B;;EAEA;AACJ;AACA;EACWC,aAAaA,CAAA,EAAS;IACzB,IAAI,CAACC,YAAY,GAAG,IAAI;EAC5B;;EAEA;AACJ;AACA;AACA;AACA;EACWC,WAAWA,CAAA,EAAY;IAC1B,OAAO,IAAI,CAACD,YAAY;EAC5B;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACWE,kBAAkBA,CAACC,KAAkB,EAAEC,SAAqB,EAAQ;IAAA,IAAAC,qBAAA,EAAAC,sBAAA;IACvE,IAAMC,WAAW,IAAAF,qBAAA,GAAGF,KAAK,CAACK,qBAAqB,CAAC,CAAC,CAACC,WAAW,cAAAJ,qBAAA,cAAAA,qBAAA,GAAI,EAAE;IAEnE,IAAIF,KAAK,CAACO,OAAO,CAAC,CAAC,KAAKtB,SAAS,CAACG,UAAU,EAAE;MAC1C;IACJ;IAEA,IAAI,CAACS,YAAY,GAAG,KAAK;IAEzB,IAAI,CAACW,MAAM,CAACC,MAAM,GAAGT,KAAK;IAE1B,IAAMU,aAAa,GAAG,IAAI,CAACC,UAAU;IACrC,IAAI,CAACA,UAAU,GAAGX,KAAK,CAACK,qBAAqB,CAAC,CAAC,CAACM,UAAU;IAC1D,IAAI,IAAI,CAACA,UAAU,KAAKC,SAAS,EAAE;MAC/B;MACA;MACA7B,MAAM,CAAC8B,KAAK,gEAAAC,MAAA,CACuDd,KAAK,CAACe,cAAc,SACnFf,KAAK,CAACgB,UAAU,CAAC,CAAC,qBAElBhB,KAAK,CAACiB,cAAc,CAAC,CACzB,CAAC;IACL;IAEA,IAAI,CAACC,YAAY,GAAGC,kBAAkB,CAAC,IAAI,CAAC5B,MAAM,EAAEa,WAAW,EAAEH,SAAS,CAAC;IAE3E,IAAMmB,OAAO,GAAG,IAAI,CAAC3B,IAAI;IACzB,IAAI,CAACA,IAAI,GAAG4B,oBAAoB,CAAC,IAAI,CAAC9B,MAAM,EAAEa,WAAW,EAAE,IAAI,CAACc,YAAY,CAAC;;IAE7E;IACA;IACA,IAAI,CAACxB,cAAc,GAAGb,4BAA4B,EAAAsB,sBAAA,GAACH,KAAK,CAACK,qBAAqB,CAAC,CAAC,CAACC,WAAW,cAAAH,sBAAA,cAAAA,sBAAA,GAAI,EAAE,CAAC;IACnG,IAAI,CAAC,IAAI,CAACT,cAAc,IAAI,CAACZ,iBAAiB,CAAC,IAAI,CAACY,cAAc,CAAC,EAAE;MACjE,IAAI,CAACA,cAAc,GAAG,IAAI,CAACH,MAAM;IACrC;IAEA,IAAImB,aAAa,KAAK,IAAI,CAACC,UAAU,EAAE;MACnC,IAAI,CAAChB,kBAAkB,CAAC,CAAC;MACzB,IAAI,CAAC2B,IAAI,CAACnC,eAAe,CAACoC,UAAU,EAAEvB,KAAK,EAAE,IAAI,EAAEU,aAAa,CAAC;IACrE;IACA,IAAIU,OAAO,KAAK,IAAI,CAAC3B,IAAI,EAAE;MACvB,IAAI,CAACE,kBAAkB,CAAC,CAAC;MACzB,IAAI,CAAC2B,IAAI,CAACnC,eAAe,CAACqC,IAAI,EAAExB,KAAK,EAAE,IAAI,EAAEoB,OAAO,CAAC;IACzD;EACJ;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACWK,4BAA4BA,CAACxB,SAAoB,EAAW;IAAA,IAAAyB,qBAAA;IAC/D,IAAI,CAAC,IAAI,CAAClB,MAAM,CAACC,MAAM,EAAE;MACrB,OAAO,KAAK;IAChB;IAEA,IAAML,WAAW,IAAAsB,qBAAA,GAAG,IAAI,CAAClB,MAAM,CAACC,MAAM,CAACJ,qBAAqB,CAAC,CAAC,CAACC,WAAW,cAAAoB,qBAAA,cAAAA,qBAAA,GAAI,EAAE;IAChF,IAAMC,eAAe,GAAGR,kBAAkB,CAAC,IAAI,CAAC5B,MAAM,EAAEa,WAAW,EAAEH,SAAS,CAAC;IAE/E,IAAI0B,eAAe,KAAK,IAAI,CAACT,YAAY,EAAE;MACvC,OAAO,KAAK;IAChB;IAEA,IAAI,CAACA,YAAY,GAAGS,eAAe;IACnC,IAAMP,OAAO,GAAG,IAAI,CAAC3B,IAAI;IACzB,IAAI,CAACA,IAAI,GAAG4B,oBAAoB,CAAC,IAAI,CAAC9B,MAAM,EAAEa,WAAW,EAAE,IAAI,CAACc,YAAY,CAAC;IAE7E,IAAIE,OAAO,KAAK,IAAI,CAAC3B,IAAI,EAAE;MACvB,IAAI,CAACE,kBAAkB,CAAC,CAAC;MACzB,IAAI,CAAC2B,IAAI,CAACnC,eAAe,CAACqC,IAAI,EAAE,IAAI,CAAChB,MAAM,CAACC,MAAM,EAAE,IAAI,EAAEW,OAAO,CAAC;MAClE,OAAO,IAAI;IACf;IAEA,OAAO,KAAK;EAChB;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;EACWQ,aAAaA,CAACC,UAAkB,EAAEC,eAA4B,EAAQ;IACzE,IAAMC,aAAa,GAAG,IAAI,CAACF,UAAU;IACrC,IAAI,CAACA,UAAU,GAAGA,UAAU;IAE5B,IAAIE,aAAa,KAAK,IAAI,CAACF,UAAU,EAAE;MACnC,IAAI,CAAClC,kBAAkB,CAAC,CAAC;MACzB,IAAI,CAAC2B,IAAI,CAACnC,eAAe,CAAC6C,UAAU,EAAEF,eAAe,EAAE,IAAI,CAAC;IAChE;EACJ;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;EACWG,cAAcA,CAACjC,KAAkB,EAAQ;IAC5C,IAAIA,KAAK,CAACO,OAAO,CAAC,CAAC,KAAK,UAAU,EAAE;MAChC;IACJ;IACA,IAAM2B,SAAS,GAAG,IAAI,CAACC,MAAM;IAC7B,IAAI,CAACA,MAAM,GAAG,KAAK;IACnB,IAAMC,UAAU,GAAGpC,KAAK,CAACgB,UAAU,CAAC,CAAC,CAACqB,QAAQ;IAC9C,IAAI,CAACC,KAAK,CAACC,OAAO,CAACH,UAAU,CAAC,EAAE;MAC5B;MACA;IACJ;IACA,IAAIA,UAAU,CAACI,OAAO,CAAC,IAAI,CAACjD,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE;MACxC,IAAI,CAAC4C,MAAM,GAAG,IAAI;IACtB;IACA,IAAID,SAAS,KAAK,IAAI,CAACC,MAAM,EAAE;MAC3B,IAAI,CAACxC,kBAAkB,CAAC,CAAC;MACzB,IAAI,CAAC2B,IAAI,CAACnC,eAAe,CAACsD,MAAM,EAAEzC,KAAK,EAAE,IAAI,CAAC;IAClD;EACJ;;EAEA;AACJ;AACA;EACYL,kBAAkBA,CAAA,EAAS;IAC/B,IAAI,CAAC+C,QAAQ,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC;EAC9B;;EAEA;AACJ;AACA;AACA;AACA;AACA;EACWC,mBAAmBA,CAAA,EAAW;IACjC,OAAO,IAAI,CAACH,QAAQ;EACxB;EAEOI,QAAQA,CAAA,EAAY;IACvB,OACI,IAAI,CAACnC,UAAU,KAAKzB,eAAe,CAAC6D,KAAK,IACzC,IAAI,CAACvC,MAAM,CAACC,MAAM,KAAKG,SAAS,IAChC,IAAI,CAACJ,MAAM,CAACC,MAAM,CAACuC,SAAS,CAAC,CAAC,KAAK,IAAI,CAACxC,MAAM,CAACC,MAAM,CAACwC,WAAW,CAAC,CAAC;EAE3E;;EAEA;AACJ;AACA;AACA;AACA;EACWC,YAAYA,CAAA,EAAuB;IACtC;IACA;IACA,IAAI,IAAI,CAAC1C,MAAM,CAACC,MAAM,EAAE;MACpB;MACA;;MAEA;MACA;MACA;;MAEA,IAAM0C,WAAW,GAAG,IAAI,CAAC3C,MAAM,CAACC,MAAM;MACtC,IAAI2C,aAAa,GAAGD,WAAW,CAACnC,UAAU,CAAC,CAAC;MAC5C,IAAIqC,YAAgC,GAAGF,WAAW,CAACH,SAAS,CAAC,CAAC;MAE9D,IAAII,aAAa,CAACzC,UAAU,KAAKzB,eAAe,CAACoE,IAAI,EAAE;QACnDF,aAAa,GAAGD,WAAW,CAAClC,cAAc,CAAC,CAAC;QAC5CoC,YAAY,GAAGF,WAAW,CAACI,WAAW,CAAC,CAAC,CAACC,WAAW;MACxD;MAEA,IAAIJ,aAAa,CAACzC,UAAU,KAAKzB,eAAe,CAACuE,MAAM,IAAIL,aAAa,CAACM,SAAS,EAAE;QAChF,OAAOL,YAAY;MACvB;IACJ;EACJ;;EAEA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACWM,YAAYA,CACfC,OAAe,EACfC,KAAa,EACbC,MAAc,EACdC,YAAoB,EAIP;IAAA,IAHbC,YAAY,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAArD,SAAA,GAAAqD,SAAA,MAAG,IAAI;IAAA,IACnBE,gBAAyB,GAAAF,SAAA,CAAAC,MAAA,OAAAD,SAAA,MAAArD,SAAA;IAAA,IACzBwD,iBAA0B,GAAAH,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAArD,SAAA,GAAAqD,SAAA,MAAG,KAAK;IAElC,IAAMI,MAAM,GAAG,IAAI,CAACC,eAAe,CAAC,CAAC;IAErC,IAAI,CAACD,MAAM,IAAI,CAACL,YAAY,EAAE;MAC1B,OAAO,IAAI;IACf;IACA,IAAMO,OAAO,GAAG3F,gBAAgB,CAC5BgF,OAAO,EACPS,MAAM,EACNR,KAAK,EACLC,MAAM,EACNC,YAAY,EACZI,gBAAgB,EAChBvD,SAAS,EACTwD,iBACJ,CAAC;IACD,IAAIG,OAAO,EAAE;MACT,OAAOA,OAAO;IAClB;IACA,OAAO,IAAI;EACf;;EAEA;AACJ;AACA;AACA;EACWD,eAAeA,CAAA,EAAuB;IACzC,IAAI,IAAI,CAAC9D,MAAM,CAACC,MAAM,EAAE;MACpB,OAAO,IAAI,CAACD,MAAM,CAACC,MAAM,CAACJ,qBAAqB,CAAC,CAAC,CAACmE,UAAU;IAChE,CAAC,MAAM,IAAI,IAAI,CAACC,IAAI,EAAE;MAClB,OAAO,IAAI,CAACA,IAAI,CAACC,SAAS;IAC9B;EACJ;AACJ;AAEA,OAAO,IAAMC,YAAY,GAAG,QAAQ;AACpC,IAAMC,eAAe,GAAG,6BAA6B;AAErD,SAASzD,kBAAkBA,CAAC0D,UAAkB,EAAEzE,WAAoB,EAAEH,SAAqB,EAAW;EAClG,IAAI,CAACG,WAAW,IAAIA,WAAW,KAAKyE,UAAU,EAAE,OAAO,KAAK;EAC5D,IAAI,CAAC5E,SAAS,EAAE,OAAO,KAAK;EAE5B,IAAM6E,mBAAmB,GAAGhG,iBAAiB,CAACsB,WAAW,CAAC;;EAE1D;EACA;EACA,IAAI,CAAC0E,mBAAmB,EAAE,OAAO,KAAK;;EAEtC;EACA;EACA;EACA,IAAIH,YAAY,CAACI,IAAI,CAACD,mBAAmB,CAAC,EAAE,OAAO,IAAI;;EAEvD;EACA;EACA;EACA,IAAIF,eAAe,CAACG,IAAI,CAAC3E,WAAW,CAAC,EAAE,OAAO,IAAI;;EAElD;EACA;EACA,IAAM4E,OAAO,GAAG/E,SAAS,CAACgF,yBAAyB,CAAC7E,WAAW,CAAC;EAChE,IAAI4E,OAAO,CAACE,IAAI,CAAEC,CAAC,IAAKA,CAAC,KAAKN,UAAU,CAAC,EAAE,OAAO,IAAI;EAEtD,OAAO,KAAK;AAChB;AAEA,SAASxD,oBAAoBA,CAACwD,UAAkB,EAAEzE,WAA+B,EAAEc,YAAqB,EAAU;EAC9G,IAAI,CAACd,WAAW,IAAIA,WAAW,KAAKyE,UAAU,EAAE,OAAOA,UAAU;EAEjE,IAAI3D,YAAY,EAAE,OAAOrC,4BAA4B,CAACuB,WAAW,CAAC,GAAG,IAAI,GAAGyE,UAAU,GAAG,GAAG;;EAE5F;EACA;EACA,IAAI,CAAC/F,iBAAiB,CAACsB,WAAW,CAAC,EAAE,OAAOyE,UAAU;;EAEtD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAAOhG,4BAA4B,CAACuB,WAAW,CAAC;AACpD","ignoreList":[]}
@@ -1,3 +1,4 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
1
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
3
  /*
3
4
  Copyright 2023 The Matrix.org Foundation C.I.C.
@@ -25,10 +26,6 @@ import { logger } from "../logger.js";
25
26
  */
26
27
  export class RoomReceipts {
27
28
  constructor(room) {
28
- _defineProperty(this, "room", void 0);
29
- _defineProperty(this, "threadedReceipts", void 0);
30
- _defineProperty(this, "unthreadedReceipts", void 0);
31
- _defineProperty(this, "danglingReceipts", void 0);
32
29
  /**
33
30
  * Look for dangling receipts for the given event ID,
34
31
  * and add them to the thread of unthread receipts if found.
@@ -87,9 +84,18 @@ export class RoomReceipts {
87
84
  unthreaded :: userId :: ReceiptInfo
88
85
  dangling :: eventId :: DanglingReceipt
89
86
  */
90
- for (var [_eventId, eventReceipt] of Object.entries(receiptContent)) {
91
- for (var [_receiptType, receiptsByUser] of Object.entries(eventReceipt)) {
92
- for (var [_userId, _receipt] of Object.entries(receiptsByUser)) {
87
+ for (var _ref3 of Object.entries(receiptContent)) {
88
+ var _ref2 = _slicedToArray(_ref3, 2);
89
+ var _eventId = _ref2[0];
90
+ var eventReceipt = _ref2[1];
91
+ for (var _ref6 of Object.entries(eventReceipt)) {
92
+ var _ref5 = _slicedToArray(_ref6, 2);
93
+ var _receiptType = _ref5[0];
94
+ var receiptsByUser = _ref5[1];
95
+ for (var _ref9 of Object.entries(receiptsByUser)) {
96
+ var _ref8 = _slicedToArray(_ref9, 2);
97
+ var _userId = _ref8[0];
98
+ var _receipt = _ref8[1];
93
99
  var referencedEvent = this.room.findEventById(_eventId);
94
100
  if (!referencedEvent) {
95
101
  this.danglingReceipts.add(new DanglingReceipt(_eventId, _receiptType, _userId, _receipt, synthetic));
@@ -183,16 +189,15 @@ class DanglingReceipt {
183
189
  }
184
190
  }
185
191
  class UserReceipts {
192
+ /**
193
+ * The real receipt for this user.
194
+ */
195
+
196
+ /**
197
+ * The synthetic receipt for this user. If this is defined, it is later than real.
198
+ */
199
+
186
200
  constructor(room) {
187
- _defineProperty(this, "room", void 0);
188
- /**
189
- * The real receipt for this user.
190
- */
191
- _defineProperty(this, "real", void 0);
192
- /**
193
- * The synthetic receipt for this user. If this is defined, it is later than real.
194
- */
195
- _defineProperty(this, "synthetic", void 0);
196
201
  this.room = room;
197
202
  this.real = undefined;
198
203
  this.synthetic = undefined;
@@ -237,10 +242,9 @@ class UserReceipts {
237
242
  * userId: ReceiptInfo
238
243
  */
239
244
  class ReceiptsByUser {
245
+ /** map of userId: UserReceipts */
246
+
240
247
  constructor(room) {
241
- _defineProperty(this, "room", void 0);
242
- /** map of userId: UserReceipts */
243
- _defineProperty(this, "data", void 0);
244
248
  this.room = room;
245
249
  this.data = new Map();
246
250
  }
@@ -294,10 +298,9 @@ class ReceiptsByUser {
294
298
  * The latest threaded receipts we have for a room.
295
299
  */
296
300
  class ThreadedReceipts {
301
+ /** map of threadId: ReceiptsByUser */
302
+
297
303
  constructor(room) {
298
- _defineProperty(this, "room", void 0);
299
- /** map of threadId: ReceiptsByUser */
300
- _defineProperty(this, "data", void 0);
301
304
  this.room = room;
302
305
  this.data = new Map();
303
306
  }
@@ -1 +1 @@
1
- {"version":3,"file":"room-receipts.js","names":["MAIN_ROOM_TIMELINE","threadIdForReceipt","RoomEvent","logger","RoomReceipts","constructor","room","_defineProperty","event","eventId","getId","danglingReceipts","remove","forEach","danglingReceipt","receipt","thread_id","threadedReceipts","set","receiptType","userId","ts","synthetic","unthreadedReceipts","ThreadedReceipts","ReceiptsByUser","DanglingReceipts","on","Timeline","onTimelineEvent","add","receiptContent","eventReceipt","Object","entries","receiptsByUser","referencedEvent","findEventById","DanglingReceipt","hasUserReadEvent","unthreaded","get","isAfterOrSame","warn","concat","roomId","threadId","threaded","userSentLatestEventInThread","_this$room$getThread","timeline","getLiveTimeline","getEvents","getThread","length","getSender","ReceiptInfo","UserReceipts","real","undefined","receiptInfo","_this$synthetic","getByType","data","Map","userReceipts","getOrCreate","existingReceipt","isAfter","_this$data$get","_this$data$get2","push","delete","m","key","createFn","found","created","leftEventId","rightEventId","comparison","compareEventOrdering"],"sources":["../../src/models/room-receipts.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { MAIN_ROOM_TIMELINE, type Receipt, type ReceiptContent } from \"../@types/read_receipts.ts\";\nimport { threadIdForReceipt } from \"../client.ts\";\nimport { type Room, RoomEvent } from \"./room.ts\";\nimport { type MatrixEvent } from \"./event.ts\";\nimport { logger } from \"../logger.ts\";\n\n/**\n * The latest receipts we have for a room.\n */\nexport class RoomReceipts {\n private room: Room;\n private threadedReceipts: ThreadedReceipts;\n private unthreadedReceipts: ReceiptsByUser;\n private danglingReceipts: DanglingReceipts;\n\n public constructor(room: Room) {\n this.room = room;\n this.threadedReceipts = new ThreadedReceipts(room);\n this.unthreadedReceipts = new ReceiptsByUser(room);\n this.danglingReceipts = new DanglingReceipts();\n // We listen for timeline events so we can process dangling receipts\n room.on(RoomEvent.Timeline, this.onTimelineEvent);\n }\n\n /**\n * Remember the receipt information supplied. For each receipt:\n *\n * If we don't have the event for this receipt, store it as \"dangling\" so we\n * can process it later.\n *\n * Otherwise store it per-user in either the threaded store for its\n * thread_id, or the unthreaded store if there is no thread_id.\n *\n * Ignores any receipt that is before an existing receipt for the same user\n * (in the same thread, if applicable). \"Before\" is defined by the\n * unfilteredTimelineSet of the room.\n */\n public add(receiptContent: ReceiptContent, synthetic: boolean): void {\n /*\n Transform this structure:\n {\n \"$EVENTID\": {\n \"m.read|m.read.private\": {\n \"@user:example.org\": {\n \"ts\": 1661,\n \"thread_id\": \"main|$THREAD_ROOT_ID\" // or missing/undefined for an unthreaded receipt\n }\n }\n },\n ...\n }\n into maps of:\n threaded :: threadid :: userId :: ReceiptInfo\n unthreaded :: userId :: ReceiptInfo\n dangling :: eventId :: DanglingReceipt\n */\n for (const [eventId, eventReceipt] of Object.entries(receiptContent)) {\n for (const [receiptType, receiptsByUser] of Object.entries(eventReceipt)) {\n for (const [userId, receipt] of Object.entries(receiptsByUser)) {\n const referencedEvent = this.room.findEventById(eventId);\n if (!referencedEvent) {\n this.danglingReceipts.add(\n new DanglingReceipt(eventId, receiptType, userId, receipt, synthetic),\n );\n } else if (receipt.thread_id) {\n this.threadedReceipts.set(\n receipt.thread_id,\n eventId,\n receiptType,\n userId,\n receipt.ts,\n synthetic,\n );\n } else {\n this.unthreadedReceipts.set(eventId, receiptType, userId, receipt.ts, synthetic);\n }\n }\n }\n }\n }\n\n /**\n * Look for dangling receipts for the given event ID,\n * and add them to the thread of unthread receipts if found.\n * @param event - the event to look for\n */\n private onTimelineEvent = (event: MatrixEvent): void => {\n const eventId = event.getId();\n if (!eventId) return;\n\n const danglingReceipts = this.danglingReceipts.remove(eventId);\n\n danglingReceipts?.forEach((danglingReceipt) => {\n // The receipt is a thread receipt\n if (danglingReceipt.receipt.thread_id) {\n this.threadedReceipts.set(\n danglingReceipt.receipt.thread_id,\n danglingReceipt.eventId,\n danglingReceipt.receiptType,\n danglingReceipt.userId,\n danglingReceipt.receipt.ts,\n danglingReceipt.synthetic,\n );\n } else {\n this.unthreadedReceipts.set(\n eventId,\n danglingReceipt.receiptType,\n danglingReceipt.userId,\n danglingReceipt.receipt.ts,\n danglingReceipt.synthetic,\n );\n }\n });\n };\n\n public hasUserReadEvent(userId: string, eventId: string): boolean {\n const unthreaded = this.unthreadedReceipts.get(userId);\n if (unthreaded) {\n if (isAfterOrSame(unthreaded.eventId, eventId, this.room)) {\n // The unthreaded receipt is after this event, so we have read it.\n return true;\n }\n }\n\n const event = this.room.findEventById(eventId);\n if (!event) {\n // We don't know whether the user has read it - default to caution and say no.\n // This shouldn't really happen and feels like it ought to be an exception: let's\n // log a warn for now.\n logger.warn(\n `hasUserReadEvent event ID ${eventId} not found in room ${this.room.roomId}: this shouldn't happen!`,\n );\n return false;\n }\n\n const threadId = threadIdForReceipt(event);\n const threaded = this.threadedReceipts.get(threadId, userId);\n if (threaded) {\n if (isAfterOrSame(threaded.eventId, eventId, this.room)) {\n // The threaded receipt is after this event, so we have read it.\n return true;\n }\n }\n\n // TODO: what if they sent the second-last event in the thread?\n if (this.userSentLatestEventInThread(threadId, userId)) {\n // The user sent the latest message in this event's thread, so we\n // consider everything in the thread to be read.\n //\n // Note: maybe we don't need this because synthetic receipts should\n // do this job for us?\n return true;\n }\n\n // Neither of the receipts were after the event, so it's unread.\n return false;\n }\n\n /**\n * @returns true if the thread with this ID can be found, and the supplied\n * user sent the latest message in it.\n */\n private userSentLatestEventInThread(threadId: string, userId: string): boolean {\n const timeline =\n threadId === MAIN_ROOM_TIMELINE\n ? this.room.getLiveTimeline().getEvents()\n : this.room.getThread(threadId)?.timeline;\n\n return !!(timeline && timeline.length > 0 && timeline[timeline.length - 1].getSender() === userId);\n }\n}\n\n// --- implementation details ---\n\n/**\n * The information \"inside\" a receipt once it has been stored inside\n * RoomReceipts - what eventId it refers to, its type, and its ts.\n *\n * Does not contain userId or threadId since these are stored as keys of the\n * maps in RoomReceipts.\n */\nclass ReceiptInfo {\n public constructor(\n public eventId: string,\n public receiptType: string,\n public ts: number,\n ) {}\n}\n\n/**\n * Everything we know about a receipt that is \"dangling\" because we can't find\n * the event to which it refers.\n */\nclass DanglingReceipt {\n public constructor(\n public eventId: string,\n public receiptType: string,\n public userId: string,\n public receipt: Receipt,\n public synthetic: boolean,\n ) {}\n}\n\nclass UserReceipts {\n private room: Room;\n\n /**\n * The real receipt for this user.\n */\n private real: ReceiptInfo | undefined;\n\n /**\n * The synthetic receipt for this user. If this is defined, it is later than real.\n */\n private synthetic: ReceiptInfo | undefined;\n\n public constructor(room: Room) {\n this.room = room;\n this.real = undefined;\n this.synthetic = undefined;\n }\n\n public set(synthetic: boolean, receiptInfo: ReceiptInfo): void {\n if (synthetic) {\n this.synthetic = receiptInfo;\n } else {\n this.real = receiptInfo;\n }\n\n // Preserve the invariant: synthetic is only defined if it's later than real\n if (this.synthetic && this.real) {\n if (isAfterOrSame(this.real.eventId, this.synthetic.eventId, this.room)) {\n this.synthetic = undefined;\n }\n }\n }\n\n /**\n * Return the latest receipt we have - synthetic if we have one (and it's\n * later), otherwise real.\n */\n public get(): ReceiptInfo | undefined {\n // Relies on the invariant that synthetic is only defined if it's later than real.\n return this.synthetic ?? this.real;\n }\n\n /**\n * Return the latest receipt we have of the specified type (synthetic or not).\n */\n public getByType(synthetic: boolean): ReceiptInfo | undefined {\n return synthetic ? this.synthetic : this.real;\n }\n}\n\n/**\n * The latest receipt info we have, either for a single thread, or all the\n * unthreaded receipts for a room.\n *\n * userId: ReceiptInfo\n */\nclass ReceiptsByUser {\n private room: Room;\n\n /** map of userId: UserReceipts */\n private data: Map<string, UserReceipts>;\n\n public constructor(room: Room) {\n this.room = room;\n this.data = new Map<string, UserReceipts>();\n }\n\n /**\n * Add the supplied receipt to our structure, if it is not earlier than the\n * one we already hold for this user.\n */\n public set(eventId: string, receiptType: string, userId: string, ts: number, synthetic: boolean): void {\n const userReceipts = getOrCreate(this.data, userId, () => new UserReceipts(this.room));\n\n const existingReceipt = userReceipts.getByType(synthetic);\n if (existingReceipt && isAfter(existingReceipt.eventId, eventId, this.room)) {\n // The new receipt is before the existing one - don't store it.\n return;\n }\n\n // Possibilities:\n //\n // 1. there was no existing receipt, or\n // 2. the existing receipt was before this one, or\n // 3. we were unable to compare the receipts.\n //\n // In the case of 3 it's difficult to decide what to do, so the\n // most-recently-received receipt wins.\n //\n // Case 3 can only happen if the events for these receipts have\n // disappeared, which is quite unlikely since the new one has just been\n // checked, and the old one was checked before it was inserted here.\n //\n // We go ahead and store this receipt (replacing the other if it exists)\n userReceipts.set(synthetic, new ReceiptInfo(eventId, receiptType, ts));\n }\n\n /**\n * Find the latest receipt we have for this user. (Note - there is only one\n * receipt per user, because we are already inside a specific thread or\n * unthreaded list.)\n *\n * If there is a later synthetic receipt for this user, return that.\n * Otherwise, return the real receipt.\n *\n * @returns the found receipt info, or undefined if we have no receipt for this user.\n */\n public get(userId: string): ReceiptInfo | undefined {\n return this.data.get(userId)?.get();\n }\n}\n\n/**\n * The latest threaded receipts we have for a room.\n */\nclass ThreadedReceipts {\n private room: Room;\n\n /** map of threadId: ReceiptsByUser */\n private data: Map<string, ReceiptsByUser>;\n\n public constructor(room: Room) {\n this.room = room;\n this.data = new Map<string, ReceiptsByUser>();\n }\n\n /**\n * Add the supplied receipt to our structure, if it is not earlier than one\n * we already hold for this user in this thread.\n */\n public set(\n threadId: string,\n eventId: string,\n receiptType: string,\n userId: string,\n ts: number,\n synthetic: boolean,\n ): void {\n const receiptsByUser = getOrCreate(this.data, threadId, () => new ReceiptsByUser(this.room));\n receiptsByUser.set(eventId, receiptType, userId, ts, synthetic);\n }\n\n /**\n * Find the latest threaded receipt for the supplied user in the supplied thread.\n *\n * @returns the found receipt info or undefined if we don't have one.\n */\n public get(threadId: string, userId: string): ReceiptInfo | undefined {\n return this.data.get(threadId)?.get(userId);\n }\n}\n\n/**\n * All the receipts that we have received but can't process because we can't\n * find the event they refer to.\n *\n * We hold on to them so we can process them if their event arrives later.\n */\nclass DanglingReceipts {\n /**\n * eventId: DanglingReceipt[]\n */\n private data = new Map<string, Array<DanglingReceipt>>();\n\n /**\n * Remember the supplied dangling receipt.\n */\n public add(danglingReceipt: DanglingReceipt): void {\n const danglingReceipts = getOrCreate(this.data, danglingReceipt.eventId, () => []);\n danglingReceipts.push(danglingReceipt);\n }\n\n /**\n * Remove and return the dangling receipts for the given event ID.\n * @param eventId - the event ID to look for\n * @returns the found dangling receipts, or undefined if we don't have one.\n */\n public remove(eventId: string): Array<DanglingReceipt> | undefined {\n const danglingReceipts = this.data.get(eventId);\n this.data.delete(eventId);\n return danglingReceipts;\n }\n}\n\nfunction getOrCreate<K, V>(m: Map<K, V>, key: K, createFn: () => V): V {\n const found = m.get(key);\n if (found) {\n return found;\n } else {\n const created = createFn();\n m.set(key, created);\n return created;\n }\n}\n\n/**\n * Is left after right (or the same)?\n *\n * Only returns true if both events can be found, and left is after or the same\n * as right.\n *\n * @returns left \\>= right\n */\nfunction isAfterOrSame(leftEventId: string, rightEventId: string, room: Room): boolean {\n const comparison = room.compareEventOrdering(leftEventId, rightEventId);\n return comparison !== null && comparison >= 0;\n}\n\n/**\n * Is left strictly after right?\n *\n * Only returns true if both events can be found, and left is strictly after right.\n *\n * @returns left \\> right\n */\nfunction isAfter(leftEventId: string, rightEventId: string, room: Room): boolean {\n const comparison = room.compareEventOrdering(leftEventId, rightEventId);\n return comparison !== null && comparison > 0;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"room-receipts.js","names":["MAIN_ROOM_TIMELINE","threadIdForReceipt","RoomEvent","logger","RoomReceipts","constructor","room","_defineProperty","event","eventId","getId","danglingReceipts","remove","forEach","danglingReceipt","receipt","thread_id","threadedReceipts","set","receiptType","userId","ts","synthetic","unthreadedReceipts","ThreadedReceipts","ReceiptsByUser","DanglingReceipts","on","Timeline","onTimelineEvent","add","receiptContent","_ref3","Object","entries","_ref2","_slicedToArray","eventReceipt","_ref6","_ref5","receiptsByUser","_ref9","_ref8","referencedEvent","findEventById","DanglingReceipt","hasUserReadEvent","unthreaded","get","isAfterOrSame","warn","concat","roomId","threadId","threaded","userSentLatestEventInThread","_this$room$getThread","timeline","getLiveTimeline","getEvents","getThread","length","getSender","ReceiptInfo","UserReceipts","real","undefined","receiptInfo","_this$synthetic","getByType","data","Map","userReceipts","getOrCreate","existingReceipt","isAfter","_this$data$get","_this$data$get2","push","delete","m","key","createFn","found","created","leftEventId","rightEventId","comparison","compareEventOrdering"],"sources":["../../src/models/room-receipts.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { MAIN_ROOM_TIMELINE, type Receipt, type ReceiptContent } from \"../@types/read_receipts.ts\";\nimport { threadIdForReceipt } from \"../client.ts\";\nimport { type Room, RoomEvent } from \"./room.ts\";\nimport { type MatrixEvent } from \"./event.ts\";\nimport { logger } from \"../logger.ts\";\n\n/**\n * The latest receipts we have for a room.\n */\nexport class RoomReceipts {\n private room: Room;\n private threadedReceipts: ThreadedReceipts;\n private unthreadedReceipts: ReceiptsByUser;\n private danglingReceipts: DanglingReceipts;\n\n public constructor(room: Room) {\n this.room = room;\n this.threadedReceipts = new ThreadedReceipts(room);\n this.unthreadedReceipts = new ReceiptsByUser(room);\n this.danglingReceipts = new DanglingReceipts();\n // We listen for timeline events so we can process dangling receipts\n room.on(RoomEvent.Timeline, this.onTimelineEvent);\n }\n\n /**\n * Remember the receipt information supplied. For each receipt:\n *\n * If we don't have the event for this receipt, store it as \"dangling\" so we\n * can process it later.\n *\n * Otherwise store it per-user in either the threaded store for its\n * thread_id, or the unthreaded store if there is no thread_id.\n *\n * Ignores any receipt that is before an existing receipt for the same user\n * (in the same thread, if applicable). \"Before\" is defined by the\n * unfilteredTimelineSet of the room.\n */\n public add(receiptContent: ReceiptContent, synthetic: boolean): void {\n /*\n Transform this structure:\n {\n \"$EVENTID\": {\n \"m.read|m.read.private\": {\n \"@user:example.org\": {\n \"ts\": 1661,\n \"thread_id\": \"main|$THREAD_ROOT_ID\" // or missing/undefined for an unthreaded receipt\n }\n }\n },\n ...\n }\n into maps of:\n threaded :: threadid :: userId :: ReceiptInfo\n unthreaded :: userId :: ReceiptInfo\n dangling :: eventId :: DanglingReceipt\n */\n for (const [eventId, eventReceipt] of Object.entries(receiptContent)) {\n for (const [receiptType, receiptsByUser] of Object.entries(eventReceipt)) {\n for (const [userId, receipt] of Object.entries(receiptsByUser)) {\n const referencedEvent = this.room.findEventById(eventId);\n if (!referencedEvent) {\n this.danglingReceipts.add(\n new DanglingReceipt(eventId, receiptType, userId, receipt, synthetic),\n );\n } else if (receipt.thread_id) {\n this.threadedReceipts.set(\n receipt.thread_id,\n eventId,\n receiptType,\n userId,\n receipt.ts,\n synthetic,\n );\n } else {\n this.unthreadedReceipts.set(eventId, receiptType, userId, receipt.ts, synthetic);\n }\n }\n }\n }\n }\n\n /**\n * Look for dangling receipts for the given event ID,\n * and add them to the thread of unthread receipts if found.\n * @param event - the event to look for\n */\n private onTimelineEvent = (event: MatrixEvent): void => {\n const eventId = event.getId();\n if (!eventId) return;\n\n const danglingReceipts = this.danglingReceipts.remove(eventId);\n\n danglingReceipts?.forEach((danglingReceipt) => {\n // The receipt is a thread receipt\n if (danglingReceipt.receipt.thread_id) {\n this.threadedReceipts.set(\n danglingReceipt.receipt.thread_id,\n danglingReceipt.eventId,\n danglingReceipt.receiptType,\n danglingReceipt.userId,\n danglingReceipt.receipt.ts,\n danglingReceipt.synthetic,\n );\n } else {\n this.unthreadedReceipts.set(\n eventId,\n danglingReceipt.receiptType,\n danglingReceipt.userId,\n danglingReceipt.receipt.ts,\n danglingReceipt.synthetic,\n );\n }\n });\n };\n\n public hasUserReadEvent(userId: string, eventId: string): boolean {\n const unthreaded = this.unthreadedReceipts.get(userId);\n if (unthreaded) {\n if (isAfterOrSame(unthreaded.eventId, eventId, this.room)) {\n // The unthreaded receipt is after this event, so we have read it.\n return true;\n }\n }\n\n const event = this.room.findEventById(eventId);\n if (!event) {\n // We don't know whether the user has read it - default to caution and say no.\n // This shouldn't really happen and feels like it ought to be an exception: let's\n // log a warn for now.\n logger.warn(\n `hasUserReadEvent event ID ${eventId} not found in room ${this.room.roomId}: this shouldn't happen!`,\n );\n return false;\n }\n\n const threadId = threadIdForReceipt(event);\n const threaded = this.threadedReceipts.get(threadId, userId);\n if (threaded) {\n if (isAfterOrSame(threaded.eventId, eventId, this.room)) {\n // The threaded receipt is after this event, so we have read it.\n return true;\n }\n }\n\n // TODO: what if they sent the second-last event in the thread?\n if (this.userSentLatestEventInThread(threadId, userId)) {\n // The user sent the latest message in this event's thread, so we\n // consider everything in the thread to be read.\n //\n // Note: maybe we don't need this because synthetic receipts should\n // do this job for us?\n return true;\n }\n\n // Neither of the receipts were after the event, so it's unread.\n return false;\n }\n\n /**\n * @returns true if the thread with this ID can be found, and the supplied\n * user sent the latest message in it.\n */\n private userSentLatestEventInThread(threadId: string, userId: string): boolean {\n const timeline =\n threadId === MAIN_ROOM_TIMELINE\n ? this.room.getLiveTimeline().getEvents()\n : this.room.getThread(threadId)?.timeline;\n\n return !!(timeline && timeline.length > 0 && timeline[timeline.length - 1].getSender() === userId);\n }\n}\n\n// --- implementation details ---\n\n/**\n * The information \"inside\" a receipt once it has been stored inside\n * RoomReceipts - what eventId it refers to, its type, and its ts.\n *\n * Does not contain userId or threadId since these are stored as keys of the\n * maps in RoomReceipts.\n */\nclass ReceiptInfo {\n public constructor(\n public eventId: string,\n public receiptType: string,\n public ts: number,\n ) {}\n}\n\n/**\n * Everything we know about a receipt that is \"dangling\" because we can't find\n * the event to which it refers.\n */\nclass DanglingReceipt {\n public constructor(\n public eventId: string,\n public receiptType: string,\n public userId: string,\n public receipt: Receipt,\n public synthetic: boolean,\n ) {}\n}\n\nclass UserReceipts {\n private room: Room;\n\n /**\n * The real receipt for this user.\n */\n private real: ReceiptInfo | undefined;\n\n /**\n * The synthetic receipt for this user. If this is defined, it is later than real.\n */\n private synthetic: ReceiptInfo | undefined;\n\n public constructor(room: Room) {\n this.room = room;\n this.real = undefined;\n this.synthetic = undefined;\n }\n\n public set(synthetic: boolean, receiptInfo: ReceiptInfo): void {\n if (synthetic) {\n this.synthetic = receiptInfo;\n } else {\n this.real = receiptInfo;\n }\n\n // Preserve the invariant: synthetic is only defined if it's later than real\n if (this.synthetic && this.real) {\n if (isAfterOrSame(this.real.eventId, this.synthetic.eventId, this.room)) {\n this.synthetic = undefined;\n }\n }\n }\n\n /**\n * Return the latest receipt we have - synthetic if we have one (and it's\n * later), otherwise real.\n */\n public get(): ReceiptInfo | undefined {\n // Relies on the invariant that synthetic is only defined if it's later than real.\n return this.synthetic ?? this.real;\n }\n\n /**\n * Return the latest receipt we have of the specified type (synthetic or not).\n */\n public getByType(synthetic: boolean): ReceiptInfo | undefined {\n return synthetic ? this.synthetic : this.real;\n }\n}\n\n/**\n * The latest receipt info we have, either for a single thread, or all the\n * unthreaded receipts for a room.\n *\n * userId: ReceiptInfo\n */\nclass ReceiptsByUser {\n private room: Room;\n\n /** map of userId: UserReceipts */\n private data: Map<string, UserReceipts>;\n\n public constructor(room: Room) {\n this.room = room;\n this.data = new Map<string, UserReceipts>();\n }\n\n /**\n * Add the supplied receipt to our structure, if it is not earlier than the\n * one we already hold for this user.\n */\n public set(eventId: string, receiptType: string, userId: string, ts: number, synthetic: boolean): void {\n const userReceipts = getOrCreate(this.data, userId, () => new UserReceipts(this.room));\n\n const existingReceipt = userReceipts.getByType(synthetic);\n if (existingReceipt && isAfter(existingReceipt.eventId, eventId, this.room)) {\n // The new receipt is before the existing one - don't store it.\n return;\n }\n\n // Possibilities:\n //\n // 1. there was no existing receipt, or\n // 2. the existing receipt was before this one, or\n // 3. we were unable to compare the receipts.\n //\n // In the case of 3 it's difficult to decide what to do, so the\n // most-recently-received receipt wins.\n //\n // Case 3 can only happen if the events for these receipts have\n // disappeared, which is quite unlikely since the new one has just been\n // checked, and the old one was checked before it was inserted here.\n //\n // We go ahead and store this receipt (replacing the other if it exists)\n userReceipts.set(synthetic, new ReceiptInfo(eventId, receiptType, ts));\n }\n\n /**\n * Find the latest receipt we have for this user. (Note - there is only one\n * receipt per user, because we are already inside a specific thread or\n * unthreaded list.)\n *\n * If there is a later synthetic receipt for this user, return that.\n * Otherwise, return the real receipt.\n *\n * @returns the found receipt info, or undefined if we have no receipt for this user.\n */\n public get(userId: string): ReceiptInfo | undefined {\n return this.data.get(userId)?.get();\n }\n}\n\n/**\n * The latest threaded receipts we have for a room.\n */\nclass ThreadedReceipts {\n private room: Room;\n\n /** map of threadId: ReceiptsByUser */\n private data: Map<string, ReceiptsByUser>;\n\n public constructor(room: Room) {\n this.room = room;\n this.data = new Map<string, ReceiptsByUser>();\n }\n\n /**\n * Add the supplied receipt to our structure, if it is not earlier than one\n * we already hold for this user in this thread.\n */\n public set(\n threadId: string,\n eventId: string,\n receiptType: string,\n userId: string,\n ts: number,\n synthetic: boolean,\n ): void {\n const receiptsByUser = getOrCreate(this.data, threadId, () => new ReceiptsByUser(this.room));\n receiptsByUser.set(eventId, receiptType, userId, ts, synthetic);\n }\n\n /**\n * Find the latest threaded receipt for the supplied user in the supplied thread.\n *\n * @returns the found receipt info or undefined if we don't have one.\n */\n public get(threadId: string, userId: string): ReceiptInfo | undefined {\n return this.data.get(threadId)?.get(userId);\n }\n}\n\n/**\n * All the receipts that we have received but can't process because we can't\n * find the event they refer to.\n *\n * We hold on to them so we can process them if their event arrives later.\n */\nclass DanglingReceipts {\n /**\n * eventId: DanglingReceipt[]\n */\n private data = new Map<string, Array<DanglingReceipt>>();\n\n /**\n * Remember the supplied dangling receipt.\n */\n public add(danglingReceipt: DanglingReceipt): void {\n const danglingReceipts = getOrCreate(this.data, danglingReceipt.eventId, () => []);\n danglingReceipts.push(danglingReceipt);\n }\n\n /**\n * Remove and return the dangling receipts for the given event ID.\n * @param eventId - the event ID to look for\n * @returns the found dangling receipts, or undefined if we don't have one.\n */\n public remove(eventId: string): Array<DanglingReceipt> | undefined {\n const danglingReceipts = this.data.get(eventId);\n this.data.delete(eventId);\n return danglingReceipts;\n }\n}\n\nfunction getOrCreate<K, V>(m: Map<K, V>, key: K, createFn: () => V): V {\n const found = m.get(key);\n if (found) {\n return found;\n } else {\n const created = createFn();\n m.set(key, created);\n return created;\n }\n}\n\n/**\n * Is left after right (or the same)?\n *\n * Only returns true if both events can be found, and left is after or the same\n * as right.\n *\n * @returns left \\>= right\n */\nfunction isAfterOrSame(leftEventId: string, rightEventId: string, room: Room): boolean {\n const comparison = room.compareEventOrdering(leftEventId, rightEventId);\n return comparison !== null && comparison >= 0;\n}\n\n/**\n * Is left strictly after right?\n *\n * Only returns true if both events can be found, and left is strictly after right.\n *\n * @returns left \\> right\n */\nfunction isAfter(leftEventId: string, rightEventId: string, room: Room): boolean {\n const comparison = room.compareEventOrdering(leftEventId, rightEventId);\n return comparison !== null && comparison > 0;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -79,8 +79,6 @@ export class RoomState extends TypedEventEmitter {
79
79
  status: OobStatus.NotStarted
80
80
  };
81
81
  super();
82
- this.roomId = roomId;
83
- this.oobMemberFlags = oobMemberFlags;
84
82
  _defineProperty(this, "reEmitter", new TypedReEmitter(this));
85
83
  _defineProperty(this, "sentinels", {});
86
84
  // userId: RoomMember
@@ -114,6 +112,8 @@ export class RoomState extends TypedEventEmitter {
114
112
  _defineProperty(this, "_liveBeaconIds", []);
115
113
  // We only wants to print warnings about bad room state once.
116
114
  _defineProperty(this, "getVersionWarning", false);
115
+ this.roomId = roomId;
116
+ this.oobMemberFlags = oobMemberFlags;
117
117
  this.updateModifiedTime();
118
118
  }
119
119