matrix-js-sdk 28.1.0 → 28.2.0-rc.1

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 (287) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/dist/browser-matrix.js +1458 -391
  3. package/dist/browser-matrix.js.map +32 -22
  4. package/dist/browser-matrix.min.js +5 -5
  5. package/dist/browser-matrix.min.js.map +1 -1
  6. package/git-revision.txt +1 -1
  7. package/lib/ReEmitter.js +1 -1
  8. package/lib/ReEmitter.js.map +1 -1
  9. package/lib/ToDeviceMessageQueue.js +1 -1
  10. package/lib/ToDeviceMessageQueue.js.map +1 -1
  11. package/lib/autodiscovery.js +17 -18
  12. package/lib/autodiscovery.js.map +1 -1
  13. package/lib/client.d.ts +14 -0
  14. package/lib/client.d.ts.map +1 -1
  15. package/lib/client.js +59 -85
  16. package/lib/client.js.map +1 -1
  17. package/lib/common-crypto/CryptoBackend.d.ts +41 -0
  18. package/lib/common-crypto/CryptoBackend.d.ts.map +1 -1
  19. package/lib/common-crypto/CryptoBackend.js.map +1 -1
  20. package/lib/common-crypto/base64.d.ts +22 -0
  21. package/lib/common-crypto/base64.d.ts.map +1 -0
  22. package/lib/common-crypto/base64.js +55 -0
  23. package/lib/common-crypto/base64.js.map +1 -0
  24. package/lib/content-helpers.js +16 -16
  25. package/lib/content-helpers.js.map +1 -1
  26. package/lib/crypto/CrossSigning.js +3 -3
  27. package/lib/crypto/CrossSigning.js.map +1 -1
  28. package/lib/crypto/DeviceList.js +11 -14
  29. package/lib/crypto/DeviceList.js.map +1 -1
  30. package/lib/crypto/EncryptionSetup.js +3 -10
  31. package/lib/crypto/EncryptionSetup.js.map +1 -1
  32. package/lib/crypto/OlmDevice.js +1 -1
  33. package/lib/crypto/OlmDevice.js.map +1 -1
  34. package/lib/crypto/OutgoingRoomKeyRequestManager.js +19 -20
  35. package/lib/crypto/OutgoingRoomKeyRequestManager.js.map +1 -1
  36. package/lib/crypto/RoomList.js +1 -1
  37. package/lib/crypto/RoomList.js.map +1 -1
  38. package/lib/crypto/SecretSharing.js +1 -1
  39. package/lib/crypto/SecretSharing.js.map +1 -1
  40. package/lib/crypto/SecretStorage.js +0 -4
  41. package/lib/crypto/SecretStorage.js.map +1 -1
  42. package/lib/crypto/algorithms/base.js +0 -14
  43. package/lib/crypto/algorithms/base.js.map +1 -1
  44. package/lib/crypto/algorithms/megolm.js +22 -31
  45. package/lib/crypto/algorithms/megolm.js.map +1 -1
  46. package/lib/crypto/backup.d.ts +17 -0
  47. package/lib/crypto/backup.d.ts.map +1 -1
  48. package/lib/crypto/backup.js +29 -8
  49. package/lib/crypto/backup.js.map +1 -1
  50. package/lib/crypto/dehydration.js +1 -5
  51. package/lib/crypto/dehydration.js.map +1 -1
  52. package/lib/crypto/deviceinfo.js +1 -1
  53. package/lib/crypto/deviceinfo.js.map +1 -1
  54. package/lib/crypto/index.d.ts +10 -2
  55. package/lib/crypto/index.d.ts.map +1 -1
  56. package/lib/crypto/index.js +133 -68
  57. package/lib/crypto/index.js.map +1 -1
  58. package/lib/crypto/keybackup.d.ts +1 -16
  59. package/lib/crypto/keybackup.d.ts.map +1 -1
  60. package/lib/crypto/keybackup.js.map +1 -1
  61. package/lib/crypto/olmlib.js +21 -21
  62. package/lib/crypto/olmlib.js.map +1 -1
  63. package/lib/crypto/recoverykey.d.ts.map +1 -1
  64. package/lib/crypto/recoverykey.js +3 -2
  65. package/lib/crypto/recoverykey.js.map +1 -1
  66. package/lib/crypto/store/indexeddb-crypto-store-backend.js +1 -1
  67. package/lib/crypto/store/indexeddb-crypto-store-backend.js.map +1 -1
  68. package/lib/crypto/store/indexeddb-crypto-store.js +0 -2
  69. package/lib/crypto/store/indexeddb-crypto-store.js.map +1 -1
  70. package/lib/crypto/store/memory-crypto-store.js +16 -16
  71. package/lib/crypto/store/memory-crypto-store.js.map +1 -1
  72. package/lib/crypto/verification/Base.js +6 -13
  73. package/lib/crypto/verification/Base.js.map +1 -1
  74. package/lib/crypto/verification/QRCode.js +0 -1
  75. package/lib/crypto/verification/QRCode.js.map +1 -1
  76. package/lib/crypto/verification/SAS.js +0 -4
  77. package/lib/crypto/verification/SAS.js.map +1 -1
  78. package/lib/crypto/verification/request/InRoomChannel.js +0 -1
  79. package/lib/crypto/verification/request/InRoomChannel.js.map +1 -1
  80. package/lib/crypto/verification/request/ToDeviceChannel.js +0 -1
  81. package/lib/crypto/verification/request/ToDeviceChannel.js.map +1 -1
  82. package/lib/crypto/verification/request/VerificationRequest.js +5 -7
  83. package/lib/crypto/verification/request/VerificationRequest.js.map +1 -1
  84. package/lib/crypto-api/keybackup.d.ts +15 -0
  85. package/lib/crypto-api/keybackup.d.ts.map +1 -1
  86. package/lib/crypto-api/keybackup.js.map +1 -1
  87. package/lib/crypto-api.d.ts +53 -0
  88. package/lib/crypto-api.d.ts.map +1 -1
  89. package/lib/crypto-api.js +55 -29
  90. package/lib/crypto-api.js.map +1 -1
  91. package/lib/embedded.d.ts +2 -1
  92. package/lib/embedded.d.ts.map +1 -1
  93. package/lib/embedded.js +29 -14
  94. package/lib/embedded.js.map +1 -1
  95. package/lib/event-mapper.js +17 -17
  96. package/lib/event-mapper.js.map +1 -1
  97. package/lib/extensible_events_v1/MessageEvent.js +31 -31
  98. package/lib/extensible_events_v1/MessageEvent.js.map +1 -1
  99. package/lib/extensible_events_v1/PollEndEvent.js +24 -24
  100. package/lib/extensible_events_v1/PollEndEvent.js.map +1 -1
  101. package/lib/extensible_events_v1/PollResponseEvent.js +0 -1
  102. package/lib/extensible_events_v1/PollResponseEvent.js.map +1 -1
  103. package/lib/extensible_events_v1/PollStartEvent.js +44 -44
  104. package/lib/extensible_events_v1/PollStartEvent.js.map +1 -1
  105. package/lib/filter.js +17 -19
  106. package/lib/filter.js.map +1 -1
  107. package/lib/http-api/errors.js +4 -6
  108. package/lib/http-api/errors.js.map +1 -1
  109. package/lib/http-api/fetch.js +1 -1
  110. package/lib/http-api/fetch.js.map +1 -1
  111. package/lib/http-api/index.js +1 -1
  112. package/lib/http-api/index.js.map +1 -1
  113. package/lib/interactive-auth.js +6 -16
  114. package/lib/interactive-auth.js.map +1 -1
  115. package/lib/matrixrtc/CallMembership.d.ts +31 -0
  116. package/lib/matrixrtc/CallMembership.d.ts.map +1 -0
  117. package/lib/matrixrtc/CallMembership.js +80 -0
  118. package/lib/matrixrtc/CallMembership.js.map +1 -0
  119. package/lib/matrixrtc/MatrixRTCSession.d.ts +81 -0
  120. package/lib/matrixrtc/MatrixRTCSession.d.ts.map +1 -0
  121. package/lib/matrixrtc/MatrixRTCSession.js +345 -0
  122. package/lib/matrixrtc/MatrixRTCSession.js.map +1 -0
  123. package/lib/matrixrtc/MatrixRTCSessionManager.d.ts +38 -0
  124. package/lib/matrixrtc/MatrixRTCSessionManager.d.ts.map +1 -0
  125. package/lib/matrixrtc/MatrixRTCSessionManager.js +116 -0
  126. package/lib/matrixrtc/MatrixRTCSessionManager.js.map +1 -0
  127. package/lib/matrixrtc/focus.d.ts +9 -0
  128. package/lib/matrixrtc/focus.d.ts.map +1 -0
  129. package/lib/matrixrtc/focus.js +6 -0
  130. package/lib/matrixrtc/focus.js.map +1 -0
  131. package/lib/models/MSC3089Branch.js +16 -16
  132. package/lib/models/MSC3089Branch.js.map +1 -1
  133. package/lib/models/MSC3089TreeSpace.js +16 -17
  134. package/lib/models/MSC3089TreeSpace.js.map +1 -1
  135. package/lib/models/beacon.js +3 -8
  136. package/lib/models/beacon.js.map +1 -1
  137. package/lib/models/device.js +14 -16
  138. package/lib/models/device.js.map +1 -1
  139. package/lib/models/event-context.js +1 -2
  140. package/lib/models/event-context.js.map +1 -1
  141. package/lib/models/event-timeline-set.js +1 -7
  142. package/lib/models/event-timeline-set.js.map +1 -1
  143. package/lib/models/event-timeline.js +4 -8
  144. package/lib/models/event-timeline.js.map +1 -1
  145. package/lib/models/event.d.ts +1 -1
  146. package/lib/models/event.js +7 -25
  147. package/lib/models/event.js.map +1 -1
  148. package/lib/models/poll.js +4 -8
  149. package/lib/models/poll.js.map +1 -1
  150. package/lib/models/read-receipt.js +0 -1
  151. package/lib/models/read-receipt.js.map +1 -1
  152. package/lib/models/related-relations.js +0 -3
  153. package/lib/models/related-relations.js.map +1 -1
  154. package/lib/models/relations-container.js +2 -2
  155. package/lib/models/relations-container.js.map +1 -1
  156. package/lib/models/relations.js +3 -4
  157. package/lib/models/relations.js.map +1 -1
  158. package/lib/models/room-member.js +2 -20
  159. package/lib/models/room-member.js.map +1 -1
  160. package/lib/models/room-state.js +3 -3
  161. package/lib/models/room-state.js.map +1 -1
  162. package/lib/models/room.d.ts +1 -1
  163. package/lib/models/room.d.ts.map +1 -1
  164. package/lib/models/room.js +40 -76
  165. package/lib/models/room.js.map +1 -1
  166. package/lib/models/thread.js +21 -32
  167. package/lib/models/thread.js.map +1 -1
  168. package/lib/models/user.js +1 -20
  169. package/lib/models/user.js.map +1 -1
  170. package/lib/oidc/authorize.js +16 -16
  171. package/lib/oidc/authorize.js.map +1 -1
  172. package/lib/oidc/discovery.js +16 -16
  173. package/lib/oidc/discovery.js.map +1 -1
  174. package/lib/pushprocessor.js +17 -17
  175. package/lib/pushprocessor.js.map +1 -1
  176. package/lib/receipt-accumulator.js +1 -1
  177. package/lib/receipt-accumulator.js.map +1 -1
  178. package/lib/rendezvous/MSC3906Rendezvous.js +2 -5
  179. package/lib/rendezvous/MSC3906Rendezvous.js.map +1 -1
  180. package/lib/rendezvous/channels/MSC3903ECDHv2RendezvousChannel.js +1 -4
  181. package/lib/rendezvous/channels/MSC3903ECDHv2RendezvousChannel.js.map +1 -1
  182. package/lib/rendezvous/transports/MSC3886SimpleHttpRendezvousTransport.js +1 -8
  183. package/lib/rendezvous/transports/MSC3886SimpleHttpRendezvousTransport.js.map +1 -1
  184. package/lib/room-hierarchy.js +4 -8
  185. package/lib/room-hierarchy.js.map +1 -1
  186. package/lib/rust-crypto/CrossSigningIdentity.d.ts +1 -5
  187. package/lib/rust-crypto/CrossSigningIdentity.d.ts.map +1 -1
  188. package/lib/rust-crypto/CrossSigningIdentity.js +1 -4
  189. package/lib/rust-crypto/CrossSigningIdentity.js.map +1 -1
  190. package/lib/rust-crypto/KeyClaimManager.js +1 -2
  191. package/lib/rust-crypto/KeyClaimManager.js.map +1 -1
  192. package/lib/rust-crypto/OutgoingRequestProcessor.js +16 -16
  193. package/lib/rust-crypto/OutgoingRequestProcessor.js.map +1 -1
  194. package/lib/rust-crypto/RoomEncryptor.js +0 -3
  195. package/lib/rust-crypto/RoomEncryptor.js.map +1 -1
  196. package/lib/rust-crypto/backup.d.ts +20 -2
  197. package/lib/rust-crypto/backup.d.ts.map +1 -1
  198. package/lib/rust-crypto/backup.js +39 -4
  199. package/lib/rust-crypto/backup.js.map +1 -1
  200. package/lib/rust-crypto/index.d.ts.map +1 -1
  201. package/lib/rust-crypto/index.js +1 -0
  202. package/lib/rust-crypto/index.js.map +1 -1
  203. package/lib/rust-crypto/rust-crypto.d.ts +39 -3
  204. package/lib/rust-crypto/rust-crypto.d.ts.map +1 -1
  205. package/lib/rust-crypto/rust-crypto.js +260 -61
  206. package/lib/rust-crypto/rust-crypto.js.map +1 -1
  207. package/lib/rust-crypto/verification.js +5 -7
  208. package/lib/rust-crypto/verification.js.map +1 -1
  209. package/lib/scheduler.js +2 -2
  210. package/lib/scheduler.js.map +1 -1
  211. package/lib/sliding-sync-sdk.js +4 -7
  212. package/lib/sliding-sync-sdk.js.map +1 -1
  213. package/lib/sliding-sync.js +23 -28
  214. package/lib/sliding-sync.js.map +1 -1
  215. package/lib/store/indexeddb-local-backend.js +6 -10
  216. package/lib/store/indexeddb-local-backend.js.map +1 -1
  217. package/lib/store/indexeddb-remote-backend.js +8 -11
  218. package/lib/store/indexeddb-remote-backend.js.map +1 -1
  219. package/lib/store/indexeddb-store-worker.js +1 -2
  220. package/lib/store/indexeddb-store-worker.js.map +1 -1
  221. package/lib/store/indexeddb.js +0 -1
  222. package/lib/store/indexeddb.js.map +1 -1
  223. package/lib/store/memory.js +0 -3
  224. package/lib/store/memory.js.map +1 -1
  225. package/lib/sync-accumulator.d.ts +11 -1
  226. package/lib/sync-accumulator.d.ts.map +1 -1
  227. package/lib/sync-accumulator.js +55 -4
  228. package/lib/sync-accumulator.js.map +1 -1
  229. package/lib/sync.d.ts.map +1 -1
  230. package/lib/sync.js +53 -39
  231. package/lib/sync.js.map +1 -1
  232. package/lib/timeline-window.js +2 -6
  233. package/lib/timeline-window.js.map +1 -1
  234. package/lib/utils.js +18 -18
  235. package/lib/utils.js.map +1 -1
  236. package/lib/webrtc/audioContext.js +1 -1
  237. package/lib/webrtc/audioContext.js.map +1 -1
  238. package/lib/webrtc/call.js +35 -73
  239. package/lib/webrtc/call.js.map +1 -1
  240. package/lib/webrtc/callEventHandler.js +1 -6
  241. package/lib/webrtc/callEventHandler.js.map +1 -1
  242. package/lib/webrtc/callFeed.js +2 -17
  243. package/lib/webrtc/callFeed.js.map +1 -1
  244. package/lib/webrtc/groupCall.d.ts +7 -1
  245. package/lib/webrtc/groupCall.d.ts.map +1 -1
  246. package/lib/webrtc/groupCall.js +47 -33
  247. package/lib/webrtc/groupCall.js.map +1 -1
  248. package/lib/webrtc/groupCallEventHandler.d.ts.map +1 -1
  249. package/lib/webrtc/groupCallEventHandler.js +3 -2
  250. package/lib/webrtc/groupCallEventHandler.js.map +1 -1
  251. package/lib/webrtc/mediaHandler.js +3 -7
  252. package/lib/webrtc/mediaHandler.js.map +1 -1
  253. package/lib/webrtc/stats/callStatsReportGatherer.js +19 -22
  254. package/lib/webrtc/stats/callStatsReportGatherer.js.map +1 -1
  255. package/lib/webrtc/stats/groupCallStats.js +4 -5
  256. package/lib/webrtc/stats/groupCallStats.js.map +1 -1
  257. package/lib/webrtc/stats/media/mediaSsrcHandler.js +1 -1
  258. package/lib/webrtc/stats/media/mediaSsrcHandler.js.map +1 -1
  259. package/lib/webrtc/stats/media/mediaTrackStats.js +3 -3
  260. package/lib/webrtc/stats/media/mediaTrackStats.js.map +1 -1
  261. package/lib/webrtc/stats/media/mediaTrackStatsHandler.js +1 -1
  262. package/lib/webrtc/stats/media/mediaTrackStatsHandler.js.map +1 -1
  263. package/package.json +4 -4
  264. package/src/client.ts +66 -23
  265. package/src/common-crypto/CryptoBackend.ts +45 -0
  266. package/src/common-crypto/base64.ts +46 -0
  267. package/src/crypto/backup.ts +30 -0
  268. package/src/crypto/index.ts +90 -3
  269. package/src/crypto/keybackup.ts +3 -20
  270. package/src/crypto/recoverykey.ts +3 -4
  271. package/src/crypto-api/keybackup.ts +19 -0
  272. package/src/crypto-api.ts +63 -0
  273. package/src/embedded.ts +28 -1
  274. package/src/matrixrtc/CallMembership.ts +95 -0
  275. package/src/matrixrtc/MatrixRTCSession.ts +418 -0
  276. package/src/matrixrtc/MatrixRTCSessionManager.ts +128 -0
  277. package/src/matrixrtc/focus.ts +24 -0
  278. package/src/models/event.ts +1 -1
  279. package/src/models/room.ts +11 -5
  280. package/src/rust-crypto/CrossSigningIdentity.ts +0 -4
  281. package/src/rust-crypto/backup.ts +56 -2
  282. package/src/rust-crypto/index.ts +3 -0
  283. package/src/rust-crypto/rust-crypto.ts +282 -44
  284. package/src/sync-accumulator.ts +63 -1
  285. package/src/sync.ts +26 -1
  286. package/src/webrtc/groupCall.ts +43 -6
  287. package/src/webrtc/groupCallEventHandler.ts +3 -0
@@ -1 +1 @@
1
- {"version":3,"file":"poll.js","names":["_matrixEventsSdk","require","_polls","_relations","_typedEventEmitter","PollEvent","exports","filterResponseRelations","relationEvents","pollEndTimestamp","responseEvents","filter","event","isDecryptionFailure","M_POLL_RESPONSE","matches","getType","getTs","Poll","TypedEventEmitter","constructor","rootEvent","matrixClient","room","_defineProperty2","default","Set","events","undecryptableEventIds","map","getId","previousCount","undecryptableRelationsCount","undecryptableRelationEventIds","emit","UndecryptableRelations","getRoomId","Error","roomId","pollEvent","unstableExtensibleEvent","pollId","endEventId","_this$endEvent","endEvent","isEnded","isFetchingResponses","_isFetchingResponses","size","getResponses","responses","fetchResponses","onNewRelation","_this$endEvent2","M_POLL_END","validateEndEvent","refilterResponsesOnEnd","End","Number","MAX_SAFE_INTEGER","countUndecryptableEvents","length","forEach","addEvent","Responses","_this$endEvent3","_allRelations$nextBat","allRelations","relations","undefined","from","relationsNextBatch","Promise","all","decryptEventIfNeeded","Relations","name","altName","pollEndEvent","find","pollCloseTimestamp","nextBatch","_this$endEvent4","getRelations","_this$responses","removeEvent","roomCurrentState","currentState","endEventSender","getSender","maySendRedactionForEvent","isPollEvent","eventType","M_POLL_START"],"sources":["../../src/models/poll.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 { M_POLL_START } from \"matrix-events-sdk\";\n\nimport { M_POLL_END, M_POLL_RESPONSE } from \"../@types/polls\";\nimport { MatrixClient } from \"../client\";\nimport { PollStartEvent } from \"../extensible_events_v1/PollStartEvent\";\nimport { MatrixEvent } from \"./event\";\nimport { Relations } from \"./relations\";\nimport { Room } from \"./room\";\nimport { TypedEventEmitter } from \"./typed-event-emitter\";\n\nexport enum PollEvent {\n New = \"Poll.new\",\n End = \"Poll.end\",\n Update = \"Poll.update\",\n Responses = \"Poll.Responses\",\n Destroy = \"Poll.Destroy\",\n UndecryptableRelations = \"Poll.UndecryptableRelations\",\n}\n\nexport type PollEventHandlerMap = {\n [PollEvent.Update]: (event: MatrixEvent, poll: Poll) => void;\n [PollEvent.Destroy]: (pollIdentifier: string) => void;\n [PollEvent.End]: () => void;\n [PollEvent.Responses]: (responses: Relations) => void;\n [PollEvent.UndecryptableRelations]: (count: number) => void;\n};\n\nconst filterResponseRelations = (\n relationEvents: MatrixEvent[],\n pollEndTimestamp: number,\n): {\n responseEvents: MatrixEvent[];\n} => {\n const responseEvents = relationEvents.filter((event) => {\n if (event.isDecryptionFailure()) {\n return;\n }\n return (\n M_POLL_RESPONSE.matches(event.getType()) &&\n // From MSC3381:\n // \"Votes sent on or before the end event's timestamp are valid votes\"\n event.getTs() <= pollEndTimestamp\n );\n });\n\n return { responseEvents };\n};\n\nexport class Poll extends TypedEventEmitter<Exclude<PollEvent, PollEvent.New>, PollEventHandlerMap> {\n public readonly roomId: string;\n public readonly pollEvent: PollStartEvent;\n private _isFetchingResponses = false;\n private relationsNextBatch: string | undefined;\n private responses: null | Relations = null;\n private endEvent: MatrixEvent | undefined;\n /**\n * Keep track of undecryptable relations\n * As incomplete result sets affect poll results\n */\n private undecryptableRelationEventIds = new Set<string>();\n\n public constructor(public readonly rootEvent: MatrixEvent, private matrixClient: MatrixClient, private room: Room) {\n super();\n if (!this.rootEvent.getRoomId() || !this.rootEvent.getId()) {\n throw new Error(\"Invalid poll start event.\");\n }\n this.roomId = this.rootEvent.getRoomId()!;\n this.pollEvent = this.rootEvent.unstableExtensibleEvent as unknown as PollStartEvent;\n }\n\n public get pollId(): string {\n return this.rootEvent.getId()!;\n }\n\n public get endEventId(): string | undefined {\n return this.endEvent?.getId();\n }\n\n public get isEnded(): boolean {\n return !!this.endEvent;\n }\n\n public get isFetchingResponses(): boolean {\n return this._isFetchingResponses;\n }\n\n public get undecryptableRelationsCount(): number {\n return this.undecryptableRelationEventIds.size;\n }\n\n public async getResponses(): Promise<Relations> {\n // if we have already fetched some responses\n // just return them\n if (this.responses) {\n return this.responses;\n }\n\n // if there is no fetching in progress\n // start fetching\n if (!this.isFetchingResponses) {\n await this.fetchResponses();\n }\n // return whatever responses we got from the first page\n return this.responses!;\n }\n\n /**\n *\n * @param event - event with a relation to the rootEvent\n * @returns void\n */\n public onNewRelation(event: MatrixEvent): void {\n if (M_POLL_END.matches(event.getType()) && this.validateEndEvent(event)) {\n this.endEvent = event;\n this.refilterResponsesOnEnd();\n this.emit(PollEvent.End);\n }\n\n // wait for poll responses to be initialised\n if (!this.responses) {\n return;\n }\n\n const pollEndTimestamp = this.endEvent?.getTs() || Number.MAX_SAFE_INTEGER;\n const { responseEvents } = filterResponseRelations([event], pollEndTimestamp);\n\n this.countUndecryptableEvents([event]);\n\n if (responseEvents.length) {\n responseEvents.forEach((event) => {\n this.responses!.addEvent(event);\n });\n\n this.emit(PollEvent.Responses, this.responses);\n }\n }\n\n private async fetchResponses(): Promise<void> {\n this._isFetchingResponses = true;\n\n // we want:\n // - stable and unstable M_POLL_RESPONSE\n // - stable and unstable M_POLL_END\n // so make one api call and filter by event type client side\n const allRelations = await this.matrixClient.relations(\n this.roomId,\n this.rootEvent.getId()!,\n \"m.reference\",\n undefined,\n {\n from: this.relationsNextBatch || undefined,\n },\n );\n\n await Promise.all(allRelations.events.map((event) => this.matrixClient.decryptEventIfNeeded(event)));\n\n const responses =\n this.responses ||\n new Relations(\"m.reference\", M_POLL_RESPONSE.name, this.matrixClient, [M_POLL_RESPONSE.altName!]);\n\n const pollEndEvent = allRelations.events.find((event) => M_POLL_END.matches(event.getType()));\n\n if (this.validateEndEvent(pollEndEvent)) {\n this.endEvent = pollEndEvent;\n this.refilterResponsesOnEnd();\n this.emit(PollEvent.End);\n }\n\n const pollCloseTimestamp = this.endEvent?.getTs() || Number.MAX_SAFE_INTEGER;\n\n const { responseEvents } = filterResponseRelations(allRelations.events, pollCloseTimestamp);\n\n responseEvents.forEach((event) => {\n responses.addEvent(event);\n });\n\n this.relationsNextBatch = allRelations.nextBatch ?? undefined;\n this.responses = responses;\n this.countUndecryptableEvents(allRelations.events);\n\n // while there are more pages of relations\n // fetch them\n if (this.relationsNextBatch) {\n // don't await\n // we want to return the first page as soon as possible\n this.fetchResponses();\n } else {\n // no more pages\n this._isFetchingResponses = false;\n }\n\n // emit after updating _isFetchingResponses state\n this.emit(PollEvent.Responses, this.responses);\n }\n\n /**\n * Only responses made before the poll ended are valid\n * Refilter after an end event is recieved\n * To ensure responses are valid\n */\n private refilterResponsesOnEnd(): void {\n if (!this.responses) {\n return;\n }\n\n const pollEndTimestamp = this.endEvent?.getTs() || Number.MAX_SAFE_INTEGER;\n this.responses.getRelations().forEach((event) => {\n if (event.getTs() > pollEndTimestamp) {\n this.responses?.removeEvent(event);\n }\n });\n\n this.emit(PollEvent.Responses, this.responses);\n }\n\n private countUndecryptableEvents = (events: MatrixEvent[]): void => {\n const undecryptableEventIds = events\n .filter((event) => event.isDecryptionFailure())\n .map((event) => event.getId()!);\n\n const previousCount = this.undecryptableRelationsCount;\n this.undecryptableRelationEventIds = new Set([...this.undecryptableRelationEventIds, ...undecryptableEventIds]);\n\n if (this.undecryptableRelationsCount !== previousCount) {\n this.emit(PollEvent.UndecryptableRelations, this.undecryptableRelationsCount);\n }\n };\n\n private validateEndEvent(endEvent?: MatrixEvent): boolean {\n if (!endEvent) {\n return false;\n }\n /**\n * Repeated end events are ignored -\n * only the first (valid) closure event by origin_server_ts is counted.\n */\n if (this.endEvent && this.endEvent.getTs() < endEvent.getTs()) {\n return false;\n }\n\n /**\n * MSC3381\n * If a m.poll.end event is received from someone other than the poll creator or user with permission to redact\n * others' messages in the room, the event must be ignored by clients due to being invalid.\n */\n const roomCurrentState = this.room.currentState;\n const endEventSender = endEvent.getSender();\n return (\n !!endEventSender &&\n (endEventSender === this.rootEvent.getSender() ||\n roomCurrentState.maySendRedactionForEvent(this.rootEvent, endEventSender))\n );\n }\n}\n\n/**\n * Tests whether the event is a start, response or end poll event.\n *\n * @param event - Event to test\n * @returns true if the event is a poll event, else false\n */\nexport const isPollEvent = (event: MatrixEvent): boolean => {\n const eventType = event.getType();\n return M_POLL_START.matches(eventType) || M_POLL_RESPONSE.matches(eventType) || M_POLL_END.matches(eventType);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"poll.js","names":["_matrixEventsSdk","require","_polls","_relations","_typedEventEmitter","PollEvent","exports","filterResponseRelations","relationEvents","pollEndTimestamp","responseEvents","filter","event","isDecryptionFailure","M_POLL_RESPONSE","matches","getType","getTs","Poll","TypedEventEmitter","constructor","rootEvent","matrixClient","room","_defineProperty2","default","Set","events","undecryptableEventIds","map","getId","previousCount","undecryptableRelationsCount","undecryptableRelationEventIds","emit","UndecryptableRelations","getRoomId","Error","roomId","pollEvent","unstableExtensibleEvent","pollId","endEventId","_this$endEvent","endEvent","isEnded","isFetchingResponses","_isFetchingResponses","size","getResponses","responses","fetchResponses","onNewRelation","_this$endEvent2","M_POLL_END","validateEndEvent","refilterResponsesOnEnd","End","Number","MAX_SAFE_INTEGER","countUndecryptableEvents","length","forEach","addEvent","Responses","_this$endEvent3","_allRelations$nextBat","allRelations","relations","undefined","from","relationsNextBatch","Promise","all","decryptEventIfNeeded","Relations","name","altName","pollEndEvent","find","pollCloseTimestamp","nextBatch","_this$endEvent4","getRelations","_this$responses","removeEvent","roomCurrentState","currentState","endEventSender","getSender","maySendRedactionForEvent","isPollEvent","eventType","M_POLL_START"],"sources":["../../src/models/poll.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 { M_POLL_START } from \"matrix-events-sdk\";\n\nimport { M_POLL_END, M_POLL_RESPONSE } from \"../@types/polls\";\nimport { MatrixClient } from \"../client\";\nimport { PollStartEvent } from \"../extensible_events_v1/PollStartEvent\";\nimport { MatrixEvent } from \"./event\";\nimport { Relations } from \"./relations\";\nimport { Room } from \"./room\";\nimport { TypedEventEmitter } from \"./typed-event-emitter\";\n\nexport enum PollEvent {\n New = \"Poll.new\",\n End = \"Poll.end\",\n Update = \"Poll.update\",\n Responses = \"Poll.Responses\",\n Destroy = \"Poll.Destroy\",\n UndecryptableRelations = \"Poll.UndecryptableRelations\",\n}\n\nexport type PollEventHandlerMap = {\n [PollEvent.Update]: (event: MatrixEvent, poll: Poll) => void;\n [PollEvent.Destroy]: (pollIdentifier: string) => void;\n [PollEvent.End]: () => void;\n [PollEvent.Responses]: (responses: Relations) => void;\n [PollEvent.UndecryptableRelations]: (count: number) => void;\n};\n\nconst filterResponseRelations = (\n relationEvents: MatrixEvent[],\n pollEndTimestamp: number,\n): {\n responseEvents: MatrixEvent[];\n} => {\n const responseEvents = relationEvents.filter((event) => {\n if (event.isDecryptionFailure()) {\n return;\n }\n return (\n M_POLL_RESPONSE.matches(event.getType()) &&\n // From MSC3381:\n // \"Votes sent on or before the end event's timestamp are valid votes\"\n event.getTs() <= pollEndTimestamp\n );\n });\n\n return { responseEvents };\n};\n\nexport class Poll extends TypedEventEmitter<Exclude<PollEvent, PollEvent.New>, PollEventHandlerMap> {\n public readonly roomId: string;\n public readonly pollEvent: PollStartEvent;\n private _isFetchingResponses = false;\n private relationsNextBatch: string | undefined;\n private responses: null | Relations = null;\n private endEvent: MatrixEvent | undefined;\n /**\n * Keep track of undecryptable relations\n * As incomplete result sets affect poll results\n */\n private undecryptableRelationEventIds = new Set<string>();\n\n public constructor(public readonly rootEvent: MatrixEvent, private matrixClient: MatrixClient, private room: Room) {\n super();\n if (!this.rootEvent.getRoomId() || !this.rootEvent.getId()) {\n throw new Error(\"Invalid poll start event.\");\n }\n this.roomId = this.rootEvent.getRoomId()!;\n this.pollEvent = this.rootEvent.unstableExtensibleEvent as unknown as PollStartEvent;\n }\n\n public get pollId(): string {\n return this.rootEvent.getId()!;\n }\n\n public get endEventId(): string | undefined {\n return this.endEvent?.getId();\n }\n\n public get isEnded(): boolean {\n return !!this.endEvent;\n }\n\n public get isFetchingResponses(): boolean {\n return this._isFetchingResponses;\n }\n\n public get undecryptableRelationsCount(): number {\n return this.undecryptableRelationEventIds.size;\n }\n\n public async getResponses(): Promise<Relations> {\n // if we have already fetched some responses\n // just return them\n if (this.responses) {\n return this.responses;\n }\n\n // if there is no fetching in progress\n // start fetching\n if (!this.isFetchingResponses) {\n await this.fetchResponses();\n }\n // return whatever responses we got from the first page\n return this.responses!;\n }\n\n /**\n *\n * @param event - event with a relation to the rootEvent\n * @returns void\n */\n public onNewRelation(event: MatrixEvent): void {\n if (M_POLL_END.matches(event.getType()) && this.validateEndEvent(event)) {\n this.endEvent = event;\n this.refilterResponsesOnEnd();\n this.emit(PollEvent.End);\n }\n\n // wait for poll responses to be initialised\n if (!this.responses) {\n return;\n }\n\n const pollEndTimestamp = this.endEvent?.getTs() || Number.MAX_SAFE_INTEGER;\n const { responseEvents } = filterResponseRelations([event], pollEndTimestamp);\n\n this.countUndecryptableEvents([event]);\n\n if (responseEvents.length) {\n responseEvents.forEach((event) => {\n this.responses!.addEvent(event);\n });\n\n this.emit(PollEvent.Responses, this.responses);\n }\n }\n\n private async fetchResponses(): Promise<void> {\n this._isFetchingResponses = true;\n\n // we want:\n // - stable and unstable M_POLL_RESPONSE\n // - stable and unstable M_POLL_END\n // so make one api call and filter by event type client side\n const allRelations = await this.matrixClient.relations(\n this.roomId,\n this.rootEvent.getId()!,\n \"m.reference\",\n undefined,\n {\n from: this.relationsNextBatch || undefined,\n },\n );\n\n await Promise.all(allRelations.events.map((event) => this.matrixClient.decryptEventIfNeeded(event)));\n\n const responses =\n this.responses ||\n new Relations(\"m.reference\", M_POLL_RESPONSE.name, this.matrixClient, [M_POLL_RESPONSE.altName!]);\n\n const pollEndEvent = allRelations.events.find((event) => M_POLL_END.matches(event.getType()));\n\n if (this.validateEndEvent(pollEndEvent)) {\n this.endEvent = pollEndEvent;\n this.refilterResponsesOnEnd();\n this.emit(PollEvent.End);\n }\n\n const pollCloseTimestamp = this.endEvent?.getTs() || Number.MAX_SAFE_INTEGER;\n\n const { responseEvents } = filterResponseRelations(allRelations.events, pollCloseTimestamp);\n\n responseEvents.forEach((event) => {\n responses.addEvent(event);\n });\n\n this.relationsNextBatch = allRelations.nextBatch ?? undefined;\n this.responses = responses;\n this.countUndecryptableEvents(allRelations.events);\n\n // while there are more pages of relations\n // fetch them\n if (this.relationsNextBatch) {\n // don't await\n // we want to return the first page as soon as possible\n this.fetchResponses();\n } else {\n // no more pages\n this._isFetchingResponses = false;\n }\n\n // emit after updating _isFetchingResponses state\n this.emit(PollEvent.Responses, this.responses);\n }\n\n /**\n * Only responses made before the poll ended are valid\n * Refilter after an end event is recieved\n * To ensure responses are valid\n */\n private refilterResponsesOnEnd(): void {\n if (!this.responses) {\n return;\n }\n\n const pollEndTimestamp = this.endEvent?.getTs() || Number.MAX_SAFE_INTEGER;\n this.responses.getRelations().forEach((event) => {\n if (event.getTs() > pollEndTimestamp) {\n this.responses?.removeEvent(event);\n }\n });\n\n this.emit(PollEvent.Responses, this.responses);\n }\n\n private countUndecryptableEvents = (events: MatrixEvent[]): void => {\n const undecryptableEventIds = events\n .filter((event) => event.isDecryptionFailure())\n .map((event) => event.getId()!);\n\n const previousCount = this.undecryptableRelationsCount;\n this.undecryptableRelationEventIds = new Set([...this.undecryptableRelationEventIds, ...undecryptableEventIds]);\n\n if (this.undecryptableRelationsCount !== previousCount) {\n this.emit(PollEvent.UndecryptableRelations, this.undecryptableRelationsCount);\n }\n };\n\n private validateEndEvent(endEvent?: MatrixEvent): boolean {\n if (!endEvent) {\n return false;\n }\n /**\n * Repeated end events are ignored -\n * only the first (valid) closure event by origin_server_ts is counted.\n */\n if (this.endEvent && this.endEvent.getTs() < endEvent.getTs()) {\n return false;\n }\n\n /**\n * MSC3381\n * If a m.poll.end event is received from someone other than the poll creator or user with permission to redact\n * others' messages in the room, the event must be ignored by clients due to being invalid.\n */\n const roomCurrentState = this.room.currentState;\n const endEventSender = endEvent.getSender();\n return (\n !!endEventSender &&\n (endEventSender === this.rootEvent.getSender() ||\n roomCurrentState.maySendRedactionForEvent(this.rootEvent, endEventSender))\n );\n }\n}\n\n/**\n * Tests whether the event is a start, response or end poll event.\n *\n * @param event - Event to test\n * @returns true if the event is a poll event, else false\n */\nexport const isPollEvent = (event: MatrixEvent): boolean => {\n const eventType = event.getType();\n return M_POLL_START.matches(eventType) || M_POLL_RESPONSE.matches(eventType) || M_POLL_END.matches(eventType);\n};\n"],"mappings":"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"}
@@ -55,7 +55,6 @@ class ReadReceipt extends _typedEventEmitter.TypedEventEmitter {
55
55
  // Map: receipt type → user Id → receipt
56
56
  (0, _defineProperty2.default)(this, "receipts", new _utils.MapWithDefault(() => new Map()));
57
57
  (0, _defineProperty2.default)(this, "receiptCacheByEventId", new Map());
58
- (0, _defineProperty2.default)(this, "timeline", void 0);
59
58
  }
60
59
  /**
61
60
  * Gets the latest receipt for a given user in the room
@@ -1 +1 @@
1
- {"version":3,"file":"read-receipt.js","names":["_read_receipts","require","_typedEventEmitter","_utils","_event","_event2","_room","synthesizeReceipt","userId","event","receiptType","_event$threadRootId","MatrixEvent","content","getId","ts","getTs","thread_id","threadRootId","MAIN_ROOM_TIMELINE","type","EventType","Receipt","room_id","getRoomId","ReceiptPairRealIndex","ReceiptPairSyntheticIndex","ReadReceipt","TypedEventEmitter","constructor","args","_defineProperty2","default","MapWithDefault","Map","getReadReceiptForUserId","ignoreSynthesized","ReceiptType","Read","_this$receipts$get$ge","_this$receipts$get","realReceipt","syntheticReceipt","receipts","get","compareReceipts","a","b","_this$getUnfilteredTi","getUnfilteredTimelineSet","compareEventOrdering","eventId","data","getEventReadUpTo","_ref","_privateReadReceipt$e","_ref2","publicReadReceipt","privateReadReceipt","ReadPrivate","comparison","addReceiptToStructure","receipt","synthetic","_pair$ReceiptPairSynt2","_pair$ReceiptPairSynt3","receiptTypesMap","getOrCreate","pair","set","existingReceipt","_pair$ReceiptPairSynt","wrappedReceipt","ordering","preferSynthetic","cachedReceipt","newCachedReceipt","receiptCacheByEventId","previousEventId","filter","r","length","delete","push","getReceiptsForEvent","fixupNotifications","lastEvent","timeline","getSender","setUnread","NotificationCountType","Total","Highlight","addLocalEchoReceipt","e","addReceipt","getUsersReadUpTo","isSupportedReceiptType","map","hasUserReadEvent","_this$timeline","readUpToId","i","_this$timeline2","ev","exports"],"sources":["../../src/models/read-receipt.ts"],"sourcesContent":["/*\nCopyright 2022 The Matrix.org Foundation C.I.C.\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 http://www.apache.org/licenses/LICENSE-2.0\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 {\n CachedReceipt,\n MAIN_ROOM_TIMELINE,\n Receipt,\n ReceiptCache,\n ReceiptType,\n WrappedReceipt,\n} from \"../@types/read_receipts\";\nimport { ListenerMap, TypedEventEmitter } from \"./typed-event-emitter\";\nimport { isSupportedReceiptType } from \"../utils\";\nimport { MatrixEvent } from \"./event\";\nimport { EventType } from \"../@types/event\";\nimport { EventTimelineSet } from \"./event-timeline-set\";\nimport { MapWithDefault } from \"../utils\";\nimport { NotificationCountType } from \"./room\";\n\nexport function synthesizeReceipt(userId: string, event: MatrixEvent, receiptType: ReceiptType): MatrixEvent {\n return new MatrixEvent({\n content: {\n [event.getId()!]: {\n [receiptType]: {\n [userId]: {\n ts: event.getTs(),\n thread_id: event.threadRootId ?? MAIN_ROOM_TIMELINE,\n },\n },\n },\n },\n type: EventType.Receipt,\n room_id: event.getRoomId(),\n });\n}\n\nconst ReceiptPairRealIndex = 0;\nconst ReceiptPairSyntheticIndex = 1;\n\nexport abstract class ReadReceipt<\n Events extends string,\n Arguments extends ListenerMap<Events>,\n SuperclassArguments extends ListenerMap<any> = Arguments,\n> extends TypedEventEmitter<Events, Arguments, SuperclassArguments> {\n // receipts should clobber based on receipt_type and user_id pairs hence\n // the form of this structure. This is sub-optimal for the exposed APIs\n // which pass in an event ID and get back some receipts, so we also store\n // a pre-cached list for this purpose.\n // Map: receipt type → user Id → receipt\n private receipts = new MapWithDefault<\n string,\n Map<string, [realReceipt: WrappedReceipt | null, syntheticReceipt: WrappedReceipt | null]>\n >(() => new Map());\n private receiptCacheByEventId: ReceiptCache = new Map();\n\n public abstract getUnfilteredTimelineSet(): EventTimelineSet;\n public abstract timeline: MatrixEvent[];\n\n /**\n * Gets the latest receipt for a given user in the room\n * @param userId - The id of the user for which we want the receipt\n * @param ignoreSynthesized - Whether to ignore synthesized receipts or not\n * @param receiptType - Optional. The type of the receipt we want to get\n * @returns the latest receipts of the chosen type for the chosen user\n */\n public getReadReceiptForUserId(\n userId: string,\n ignoreSynthesized = false,\n receiptType = ReceiptType.Read,\n ): WrappedReceipt | null {\n const [realReceipt, syntheticReceipt] = this.receipts.get(receiptType)?.get(userId) ?? [null, null];\n if (ignoreSynthesized) {\n return realReceipt;\n }\n\n return syntheticReceipt ?? realReceipt;\n }\n\n private compareReceipts(a: WrappedReceipt, b: WrappedReceipt): number {\n // Try compare them in our unfiltered timeline set order, falling back to receipt timestamp which should be\n // relatively sane as receipts are set only by the originating homeserver so as long as its clock doesn't\n // jump around then it should be valid.\n return this.getUnfilteredTimelineSet().compareEventOrdering(a.eventId, b.eventId) ?? a.data.ts - b.data.ts;\n }\n\n /**\n * Get the ID of the event that a given user has read up to, or null if we\n * have received no read receipts from them.\n * @param userId - The user ID to get read receipt event ID for\n * @param ignoreSynthesized - If true, return only receipts that have been\n * sent by the server, not implicit ones generated\n * by the JS SDK.\n * @returns ID of the latest event that the given user has read, or null.\n */\n public getEventReadUpTo(userId: string, ignoreSynthesized = false): string | null {\n // XXX: This is very very ugly and I hope I won't have to ever add a new\n // receipt type here again. IMHO this should be done by the server in\n // some more intelligent manner or the client should just use timestamps\n\n const publicReadReceipt = this.getReadReceiptForUserId(userId, ignoreSynthesized, ReceiptType.Read);\n const privateReadReceipt = this.getReadReceiptForUserId(userId, ignoreSynthesized, ReceiptType.ReadPrivate);\n\n // If we have both, compare them\n let comparison: number | null | undefined;\n if (publicReadReceipt?.eventId && privateReadReceipt?.eventId) {\n comparison = this.compareReceipts(publicReadReceipt, privateReadReceipt);\n }\n\n // The public receipt is more likely to drift out of date so the private\n // one has precedence\n if (!comparison) return privateReadReceipt?.eventId ?? publicReadReceipt?.eventId ?? null;\n\n // If public read receipt is older, return the private one\n return (comparison < 0 ? privateReadReceipt?.eventId : publicReadReceipt?.eventId) ?? null;\n }\n\n public addReceiptToStructure(\n eventId: string,\n receiptType: ReceiptType,\n userId: string,\n receipt: Receipt,\n synthetic: boolean,\n ): void {\n const receiptTypesMap = this.receipts.getOrCreate(receiptType);\n let pair = receiptTypesMap.get(userId);\n\n if (!pair) {\n pair = [null, null];\n receiptTypesMap.set(userId, pair);\n }\n\n let existingReceipt = pair[ReceiptPairRealIndex];\n if (synthetic) {\n existingReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];\n }\n\n const wrappedReceipt: WrappedReceipt = {\n eventId,\n data: receipt,\n };\n\n if (existingReceipt) {\n // We only want to add this receipt if we think it is later than the one we already have.\n // This is managed server-side, but because we synthesize RRs locally we have to do it here too.\n const ordering = this.compareReceipts(existingReceipt, wrappedReceipt);\n if (ordering >= 0) {\n return;\n }\n }\n\n const realReceipt = synthetic ? pair[ReceiptPairRealIndex] : wrappedReceipt;\n const syntheticReceipt = synthetic ? wrappedReceipt : pair[ReceiptPairSyntheticIndex];\n\n let ordering: number | null = null;\n if (realReceipt && syntheticReceipt) {\n ordering = this.getUnfilteredTimelineSet().compareEventOrdering(\n realReceipt.eventId,\n syntheticReceipt.eventId,\n );\n }\n\n const preferSynthetic = ordering === null || ordering < 0;\n\n // we don't bother caching just real receipts by event ID as there's nothing that would read it.\n // Take the current cached receipt before we overwrite the pair elements.\n const cachedReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];\n\n if (synthetic && preferSynthetic) {\n pair[ReceiptPairSyntheticIndex] = wrappedReceipt;\n } else if (!synthetic) {\n pair[ReceiptPairRealIndex] = wrappedReceipt;\n\n if (!preferSynthetic) {\n pair[ReceiptPairSyntheticIndex] = null;\n }\n }\n\n const newCachedReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];\n if (cachedReceipt === newCachedReceipt) return;\n\n // clean up any previous cache entry\n if (cachedReceipt && this.receiptCacheByEventId.get(cachedReceipt.eventId)) {\n const previousEventId = cachedReceipt.eventId;\n // Remove the receipt we're about to clobber out of existence from the cache\n this.receiptCacheByEventId.set(\n previousEventId,\n this.receiptCacheByEventId.get(previousEventId)!.filter((r) => {\n return r.type !== receiptType || r.userId !== userId;\n }),\n );\n\n if (this.receiptCacheByEventId.get(previousEventId)!.length < 1) {\n this.receiptCacheByEventId.delete(previousEventId); // clean up the cache keys\n }\n }\n\n // cache the new one\n if (!this.receiptCacheByEventId.get(eventId)) {\n this.receiptCacheByEventId.set(eventId, []);\n }\n this.receiptCacheByEventId.get(eventId)!.push({\n userId: userId,\n type: receiptType as ReceiptType,\n data: receipt,\n });\n }\n\n /**\n * Get a list of receipts for the given event.\n * @param event - the event to get receipts for\n * @returns A list of receipts with a userId, type and data keys or\n * an empty list.\n */\n public getReceiptsForEvent(event: MatrixEvent): CachedReceipt[] {\n return this.receiptCacheByEventId.get(event.getId()!) || [];\n }\n\n public abstract addReceipt(event: MatrixEvent, synthetic: boolean): void;\n\n public abstract setUnread(type: NotificationCountType, count: number): void;\n\n /**\n * This issue should also be addressed on synapse's side and is tracked as part\n * of https://github.com/matrix-org/synapse/issues/14837\n *\n * Retrieves the read receipt for the logged in user and checks if it matches\n * the last event in the room and whether that event originated from the logged\n * in user.\n * Under those conditions we can consider the context as read. This is useful\n * because we never send read receipts against our own events\n * @param userId - the logged in user\n */\n public fixupNotifications(userId: string): void {\n const receipt = this.getReadReceiptForUserId(userId, false);\n\n const lastEvent = this.timeline[this.timeline.length - 1];\n if (lastEvent && receipt?.eventId === lastEvent.getId() && userId === lastEvent.getSender()) {\n this.setUnread(NotificationCountType.Total, 0);\n this.setUnread(NotificationCountType.Highlight, 0);\n }\n }\n\n /**\n * Add a temporary local-echo receipt to the room to reflect in the\n * client the fact that we've sent one.\n * @param userId - The user ID if the receipt sender\n * @param e - The event that is to be acknowledged\n * @param receiptType - The type of receipt\n */\n public addLocalEchoReceipt(userId: string, e: MatrixEvent, receiptType: ReceiptType): void {\n this.addReceipt(synthesizeReceipt(userId, e, receiptType), true);\n }\n\n /**\n * Get a list of user IDs who have <b>read up to</b> the given event.\n * @param event - the event to get read receipts for.\n * @returns A list of user IDs.\n */\n public getUsersReadUpTo(event: MatrixEvent): string[] {\n return this.getReceiptsForEvent(event)\n .filter(function (receipt) {\n return isSupportedReceiptType(receipt.type);\n })\n .map(function (receipt) {\n return receipt.userId;\n });\n }\n\n /**\n * Determines if the given user has read a particular event ID with the known\n * history of the room. This is not a definitive check as it relies only on\n * what is available to the room at the time of execution.\n * @param userId - The user ID to check the read state of.\n * @param eventId - The event ID to check if the user read.\n * @returns True if the user has read the event, false otherwise.\n */\n public hasUserReadEvent(userId: string, eventId: string): boolean {\n const readUpToId = this.getEventReadUpTo(userId, false);\n if (readUpToId === eventId) return true;\n\n if (\n this.timeline?.length &&\n this.timeline[this.timeline.length - 1].getSender() &&\n this.timeline[this.timeline.length - 1].getSender() === userId\n ) {\n // It doesn't matter where the event is in the timeline, the user has read\n // it because they've sent the latest event.\n return true;\n }\n\n for (let i = this.timeline?.length - 1; i >= 0; --i) {\n const ev = this.timeline[i];\n\n // If we encounter the target event first, the user hasn't read it\n // however if we encounter the readUpToId first then the user has read\n // it. These rules apply because we're iterating bottom-up.\n if (ev.getId() === eventId) return false;\n if (ev.getId() === readUpToId) return true;\n }\n\n // We don't know if the user has read it, so assume not.\n return false;\n }\n\n /**\n * Returns the most recent unthreaded receipt for a given user\n * @param userId - the MxID of the User\n * @returns an unthreaded Receipt. Can be undefined if receipts have been disabled\n * or a user chooses to use private read receipts (or we have simply not received\n * a receipt from this user yet).\n */\n public abstract getLastUnthreadedReceiptFor(userId: string): Receipt | undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"read-receipt.js","names":["_read_receipts","require","_typedEventEmitter","_utils","_event","_event2","_room","synthesizeReceipt","userId","event","receiptType","_event$threadRootId","MatrixEvent","content","getId","ts","getTs","thread_id","threadRootId","MAIN_ROOM_TIMELINE","type","EventType","Receipt","room_id","getRoomId","ReceiptPairRealIndex","ReceiptPairSyntheticIndex","ReadReceipt","TypedEventEmitter","constructor","args","_defineProperty2","default","MapWithDefault","Map","getReadReceiptForUserId","ignoreSynthesized","ReceiptType","Read","_this$receipts$get$ge","_this$receipts$get","realReceipt","syntheticReceipt","receipts","get","compareReceipts","a","b","_this$getUnfilteredTi","getUnfilteredTimelineSet","compareEventOrdering","eventId","data","getEventReadUpTo","_ref","_privateReadReceipt$e","_ref2","publicReadReceipt","privateReadReceipt","ReadPrivate","comparison","addReceiptToStructure","receipt","synthetic","_pair$ReceiptPairSynt2","_pair$ReceiptPairSynt3","receiptTypesMap","getOrCreate","pair","set","existingReceipt","_pair$ReceiptPairSynt","wrappedReceipt","ordering","preferSynthetic","cachedReceipt","newCachedReceipt","receiptCacheByEventId","previousEventId","filter","r","length","delete","push","getReceiptsForEvent","fixupNotifications","lastEvent","timeline","getSender","setUnread","NotificationCountType","Total","Highlight","addLocalEchoReceipt","e","addReceipt","getUsersReadUpTo","isSupportedReceiptType","map","hasUserReadEvent","_this$timeline","readUpToId","i","_this$timeline2","ev","exports"],"sources":["../../src/models/read-receipt.ts"],"sourcesContent":["/*\nCopyright 2022 The Matrix.org Foundation C.I.C.\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 http://www.apache.org/licenses/LICENSE-2.0\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 {\n CachedReceipt,\n MAIN_ROOM_TIMELINE,\n Receipt,\n ReceiptCache,\n ReceiptType,\n WrappedReceipt,\n} from \"../@types/read_receipts\";\nimport { ListenerMap, TypedEventEmitter } from \"./typed-event-emitter\";\nimport { isSupportedReceiptType } from \"../utils\";\nimport { MatrixEvent } from \"./event\";\nimport { EventType } from \"../@types/event\";\nimport { EventTimelineSet } from \"./event-timeline-set\";\nimport { MapWithDefault } from \"../utils\";\nimport { NotificationCountType } from \"./room\";\n\nexport function synthesizeReceipt(userId: string, event: MatrixEvent, receiptType: ReceiptType): MatrixEvent {\n return new MatrixEvent({\n content: {\n [event.getId()!]: {\n [receiptType]: {\n [userId]: {\n ts: event.getTs(),\n thread_id: event.threadRootId ?? MAIN_ROOM_TIMELINE,\n },\n },\n },\n },\n type: EventType.Receipt,\n room_id: event.getRoomId(),\n });\n}\n\nconst ReceiptPairRealIndex = 0;\nconst ReceiptPairSyntheticIndex = 1;\n\nexport abstract class ReadReceipt<\n Events extends string,\n Arguments extends ListenerMap<Events>,\n SuperclassArguments extends ListenerMap<any> = Arguments,\n> extends TypedEventEmitter<Events, Arguments, SuperclassArguments> {\n // receipts should clobber based on receipt_type and user_id pairs hence\n // the form of this structure. This is sub-optimal for the exposed APIs\n // which pass in an event ID and get back some receipts, so we also store\n // a pre-cached list for this purpose.\n // Map: receipt type → user Id → receipt\n private receipts = new MapWithDefault<\n string,\n Map<string, [realReceipt: WrappedReceipt | null, syntheticReceipt: WrappedReceipt | null]>\n >(() => new Map());\n private receiptCacheByEventId: ReceiptCache = new Map();\n\n public abstract getUnfilteredTimelineSet(): EventTimelineSet;\n public abstract timeline: MatrixEvent[];\n\n /**\n * Gets the latest receipt for a given user in the room\n * @param userId - The id of the user for which we want the receipt\n * @param ignoreSynthesized - Whether to ignore synthesized receipts or not\n * @param receiptType - Optional. The type of the receipt we want to get\n * @returns the latest receipts of the chosen type for the chosen user\n */\n public getReadReceiptForUserId(\n userId: string,\n ignoreSynthesized = false,\n receiptType = ReceiptType.Read,\n ): WrappedReceipt | null {\n const [realReceipt, syntheticReceipt] = this.receipts.get(receiptType)?.get(userId) ?? [null, null];\n if (ignoreSynthesized) {\n return realReceipt;\n }\n\n return syntheticReceipt ?? realReceipt;\n }\n\n private compareReceipts(a: WrappedReceipt, b: WrappedReceipt): number {\n // Try compare them in our unfiltered timeline set order, falling back to receipt timestamp which should be\n // relatively sane as receipts are set only by the originating homeserver so as long as its clock doesn't\n // jump around then it should be valid.\n return this.getUnfilteredTimelineSet().compareEventOrdering(a.eventId, b.eventId) ?? a.data.ts - b.data.ts;\n }\n\n /**\n * Get the ID of the event that a given user has read up to, or null if we\n * have received no read receipts from them.\n * @param userId - The user ID to get read receipt event ID for\n * @param ignoreSynthesized - If true, return only receipts that have been\n * sent by the server, not implicit ones generated\n * by the JS SDK.\n * @returns ID of the latest event that the given user has read, or null.\n */\n public getEventReadUpTo(userId: string, ignoreSynthesized = false): string | null {\n // XXX: This is very very ugly and I hope I won't have to ever add a new\n // receipt type here again. IMHO this should be done by the server in\n // some more intelligent manner or the client should just use timestamps\n\n const publicReadReceipt = this.getReadReceiptForUserId(userId, ignoreSynthesized, ReceiptType.Read);\n const privateReadReceipt = this.getReadReceiptForUserId(userId, ignoreSynthesized, ReceiptType.ReadPrivate);\n\n // If we have both, compare them\n let comparison: number | null | undefined;\n if (publicReadReceipt?.eventId && privateReadReceipt?.eventId) {\n comparison = this.compareReceipts(publicReadReceipt, privateReadReceipt);\n }\n\n // The public receipt is more likely to drift out of date so the private\n // one has precedence\n if (!comparison) return privateReadReceipt?.eventId ?? publicReadReceipt?.eventId ?? null;\n\n // If public read receipt is older, return the private one\n return (comparison < 0 ? privateReadReceipt?.eventId : publicReadReceipt?.eventId) ?? null;\n }\n\n public addReceiptToStructure(\n eventId: string,\n receiptType: ReceiptType,\n userId: string,\n receipt: Receipt,\n synthetic: boolean,\n ): void {\n const receiptTypesMap = this.receipts.getOrCreate(receiptType);\n let pair = receiptTypesMap.get(userId);\n\n if (!pair) {\n pair = [null, null];\n receiptTypesMap.set(userId, pair);\n }\n\n let existingReceipt = pair[ReceiptPairRealIndex];\n if (synthetic) {\n existingReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];\n }\n\n const wrappedReceipt: WrappedReceipt = {\n eventId,\n data: receipt,\n };\n\n if (existingReceipt) {\n // We only want to add this receipt if we think it is later than the one we already have.\n // This is managed server-side, but because we synthesize RRs locally we have to do it here too.\n const ordering = this.compareReceipts(existingReceipt, wrappedReceipt);\n if (ordering >= 0) {\n return;\n }\n }\n\n const realReceipt = synthetic ? pair[ReceiptPairRealIndex] : wrappedReceipt;\n const syntheticReceipt = synthetic ? wrappedReceipt : pair[ReceiptPairSyntheticIndex];\n\n let ordering: number | null = null;\n if (realReceipt && syntheticReceipt) {\n ordering = this.getUnfilteredTimelineSet().compareEventOrdering(\n realReceipt.eventId,\n syntheticReceipt.eventId,\n );\n }\n\n const preferSynthetic = ordering === null || ordering < 0;\n\n // we don't bother caching just real receipts by event ID as there's nothing that would read it.\n // Take the current cached receipt before we overwrite the pair elements.\n const cachedReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];\n\n if (synthetic && preferSynthetic) {\n pair[ReceiptPairSyntheticIndex] = wrappedReceipt;\n } else if (!synthetic) {\n pair[ReceiptPairRealIndex] = wrappedReceipt;\n\n if (!preferSynthetic) {\n pair[ReceiptPairSyntheticIndex] = null;\n }\n }\n\n const newCachedReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];\n if (cachedReceipt === newCachedReceipt) return;\n\n // clean up any previous cache entry\n if (cachedReceipt && this.receiptCacheByEventId.get(cachedReceipt.eventId)) {\n const previousEventId = cachedReceipt.eventId;\n // Remove the receipt we're about to clobber out of existence from the cache\n this.receiptCacheByEventId.set(\n previousEventId,\n this.receiptCacheByEventId.get(previousEventId)!.filter((r) => {\n return r.type !== receiptType || r.userId !== userId;\n }),\n );\n\n if (this.receiptCacheByEventId.get(previousEventId)!.length < 1) {\n this.receiptCacheByEventId.delete(previousEventId); // clean up the cache keys\n }\n }\n\n // cache the new one\n if (!this.receiptCacheByEventId.get(eventId)) {\n this.receiptCacheByEventId.set(eventId, []);\n }\n this.receiptCacheByEventId.get(eventId)!.push({\n userId: userId,\n type: receiptType as ReceiptType,\n data: receipt,\n });\n }\n\n /**\n * Get a list of receipts for the given event.\n * @param event - the event to get receipts for\n * @returns A list of receipts with a userId, type and data keys or\n * an empty list.\n */\n public getReceiptsForEvent(event: MatrixEvent): CachedReceipt[] {\n return this.receiptCacheByEventId.get(event.getId()!) || [];\n }\n\n public abstract addReceipt(event: MatrixEvent, synthetic: boolean): void;\n\n public abstract setUnread(type: NotificationCountType, count: number): void;\n\n /**\n * This issue should also be addressed on synapse's side and is tracked as part\n * of https://github.com/matrix-org/synapse/issues/14837\n *\n * Retrieves the read receipt for the logged in user and checks if it matches\n * the last event in the room and whether that event originated from the logged\n * in user.\n * Under those conditions we can consider the context as read. This is useful\n * because we never send read receipts against our own events\n * @param userId - the logged in user\n */\n public fixupNotifications(userId: string): void {\n const receipt = this.getReadReceiptForUserId(userId, false);\n\n const lastEvent = this.timeline[this.timeline.length - 1];\n if (lastEvent && receipt?.eventId === lastEvent.getId() && userId === lastEvent.getSender()) {\n this.setUnread(NotificationCountType.Total, 0);\n this.setUnread(NotificationCountType.Highlight, 0);\n }\n }\n\n /**\n * Add a temporary local-echo receipt to the room to reflect in the\n * client the fact that we've sent one.\n * @param userId - The user ID if the receipt sender\n * @param e - The event that is to be acknowledged\n * @param receiptType - The type of receipt\n */\n public addLocalEchoReceipt(userId: string, e: MatrixEvent, receiptType: ReceiptType): void {\n this.addReceipt(synthesizeReceipt(userId, e, receiptType), true);\n }\n\n /**\n * Get a list of user IDs who have <b>read up to</b> the given event.\n * @param event - the event to get read receipts for.\n * @returns A list of user IDs.\n */\n public getUsersReadUpTo(event: MatrixEvent): string[] {\n return this.getReceiptsForEvent(event)\n .filter(function (receipt) {\n return isSupportedReceiptType(receipt.type);\n })\n .map(function (receipt) {\n return receipt.userId;\n });\n }\n\n /**\n * Determines if the given user has read a particular event ID with the known\n * history of the room. This is not a definitive check as it relies only on\n * what is available to the room at the time of execution.\n * @param userId - The user ID to check the read state of.\n * @param eventId - The event ID to check if the user read.\n * @returns True if the user has read the event, false otherwise.\n */\n public hasUserReadEvent(userId: string, eventId: string): boolean {\n const readUpToId = this.getEventReadUpTo(userId, false);\n if (readUpToId === eventId) return true;\n\n if (\n this.timeline?.length &&\n this.timeline[this.timeline.length - 1].getSender() &&\n this.timeline[this.timeline.length - 1].getSender() === userId\n ) {\n // It doesn't matter where the event is in the timeline, the user has read\n // it because they've sent the latest event.\n return true;\n }\n\n for (let i = this.timeline?.length - 1; i >= 0; --i) {\n const ev = this.timeline[i];\n\n // If we encounter the target event first, the user hasn't read it\n // however if we encounter the readUpToId first then the user has read\n // it. These rules apply because we're iterating bottom-up.\n if (ev.getId() === eventId) return false;\n if (ev.getId() === readUpToId) return true;\n }\n\n // We don't know if the user has read it, so assume not.\n return false;\n }\n\n /**\n * Returns the most recent unthreaded receipt for a given user\n * @param userId - the MxID of the User\n * @returns an unthreaded Receipt. Can be undefined if receipts have been disabled\n * or a user chooses to use private read receipts (or we have simply not received\n * a receipt from this user yet).\n */\n public abstract getLastUnthreadedReceiptFor(userId: string): Receipt | undefined;\n}\n"],"mappings":"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"}
@@ -1,11 +1,9 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
3
  Object.defineProperty(exports, "__esModule", {
5
4
  value: true
6
5
  });
7
6
  exports.RelatedRelations = void 0;
8
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
7
  /*
10
8
  Copyright 2022 The Matrix.org Foundation C.I.C.
11
9
 
@@ -24,7 +22,6 @@ limitations under the License.
24
22
 
25
23
  class RelatedRelations {
26
24
  constructor(relations) {
27
- (0, _defineProperty2.default)(this, "relations", void 0);
28
25
  this.relations = relations.filter(r => !!r);
29
26
  }
30
27
  getRelations() {
@@ -1 +1 @@
1
- {"version":3,"file":"related-relations.js","names":["RelatedRelations","constructor","relations","_defineProperty2","default","filter","r","getRelations","reduce","c","p","on","ev","fn","forEach","off","exports"],"sources":["../../src/models/related-relations.ts"],"sourcesContent":["/*\nCopyright 2022 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 { Relations, RelationsEvent, EventHandlerMap } from \"./relations\";\nimport { MatrixEvent } from \"./event\";\nimport { Listener } from \"./typed-event-emitter\";\n\nexport class RelatedRelations {\n private relations: Relations[];\n\n public constructor(relations: Relations[]) {\n this.relations = relations.filter((r) => !!r);\n }\n\n public getRelations(): MatrixEvent[] {\n return this.relations.reduce<MatrixEvent[]>((c, p) => [...c, ...p.getRelations()], []);\n }\n\n public on<T extends RelationsEvent>(ev: T, fn: Listener<RelationsEvent, EventHandlerMap, T>): void {\n this.relations.forEach((r) => r.on(ev, fn));\n }\n\n public off<T extends RelationsEvent>(ev: T, fn: Listener<RelationsEvent, EventHandlerMap, T>): void {\n this.relations.forEach((r) => r.off(ev, fn));\n }\n}\n"],"mappings":";;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAMO,MAAMA,gBAAgB,CAAC;EAGnBC,WAAWA,CAACC,SAAsB,EAAE;IAAA,IAAAC,gBAAA,CAAAC,OAAA;IACvC,IAAI,CAACF,SAAS,GAAGA,SAAS,CAACG,MAAM,CAAEC,CAAC,IAAK,CAAC,CAACA,CAAC,CAAC;EACjD;EAEOC,YAAYA,CAAA,EAAkB;IACjC,OAAO,IAAI,CAACL,SAAS,CAACM,MAAM,CAAgB,CAACC,CAAC,EAAEC,CAAC,KAAK,CAAC,GAAGD,CAAC,EAAE,GAAGC,CAAC,CAACH,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;EAC1F;EAEOI,EAAEA,CAA2BC,EAAK,EAAEC,EAAgD,EAAQ;IAC/F,IAAI,CAACX,SAAS,CAACY,OAAO,CAAER,CAAC,IAAKA,CAAC,CAACK,EAAE,CAACC,EAAE,EAAEC,EAAE,CAAC,CAAC;EAC/C;EAEOE,GAAGA,CAA2BH,EAAK,EAAEC,EAAgD,EAAQ;IAChG,IAAI,CAACX,SAAS,CAACY,OAAO,CAAER,CAAC,IAAKA,CAAC,CAACS,GAAG,CAACH,EAAE,EAAEC,EAAE,CAAC,CAAC;EAChD;AACJ;AAACG,OAAA,CAAAhB,gBAAA,GAAAA,gBAAA"}
1
+ {"version":3,"file":"related-relations.js","names":["RelatedRelations","constructor","relations","filter","r","getRelations","reduce","c","p","on","ev","fn","forEach","off","exports"],"sources":["../../src/models/related-relations.ts"],"sourcesContent":["/*\nCopyright 2022 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 { Relations, RelationsEvent, EventHandlerMap } from \"./relations\";\nimport { MatrixEvent } from \"./event\";\nimport { Listener } from \"./typed-event-emitter\";\n\nexport class RelatedRelations {\n private relations: Relations[];\n\n public constructor(relations: Relations[]) {\n this.relations = relations.filter((r) => !!r);\n }\n\n public getRelations(): MatrixEvent[] {\n return this.relations.reduce<MatrixEvent[]>((c, p) => [...c, ...p.getRelations()], []);\n }\n\n public on<T extends RelationsEvent>(ev: T, fn: Listener<RelationsEvent, EventHandlerMap, T>): void {\n this.relations.forEach((r) => r.on(ev, fn));\n }\n\n public off<T extends RelationsEvent>(ev: T, fn: Listener<RelationsEvent, EventHandlerMap, T>): void {\n this.relations.forEach((r) => r.off(ev, fn));\n }\n}\n"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAMO,MAAMA,gBAAgB,CAAC;EAGnBC,WAAWA,CAACC,SAAsB,EAAE;IACvC,IAAI,CAACA,SAAS,GAAGA,SAAS,CAACC,MAAM,CAAEC,CAAC,IAAK,CAAC,CAACA,CAAC,CAAC;EACjD;EAEOC,YAAYA,CAAA,EAAkB;IACjC,OAAO,IAAI,CAACH,SAAS,CAACI,MAAM,CAAgB,CAACC,CAAC,EAAEC,CAAC,KAAK,CAAC,GAAGD,CAAC,EAAE,GAAGC,CAAC,CAACH,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;EAC1F;EAEOI,EAAEA,CAA2BC,EAAK,EAAEC,EAAgD,EAAQ;IAC/F,IAAI,CAACT,SAAS,CAACU,OAAO,CAAER,CAAC,IAAKA,CAAC,CAACK,EAAE,CAACC,EAAE,EAAEC,EAAE,CAAC,CAAC;EAC/C;EAEOE,GAAGA,CAA2BH,EAAK,EAAEC,EAAgD,EAAQ;IAChG,IAAI,CAACT,SAAS,CAACU,OAAO,CAAER,CAAC,IAAKA,CAAC,CAACS,GAAG,CAACH,EAAE,EAAEC,EAAE,CAAC,CAAC;EAChD;AACJ;AAACG,OAAA,CAAAd,gBAAA,GAAAA,gBAAA"}
@@ -26,11 +26,11 @@ limitations under the License.
26
26
 
27
27
  class RelationsContainer {
28
28
  constructor(client, room) {
29
- this.client = client;
30
- this.room = room;
31
29
  // A tree of objects to access a set of related children for an event, as in:
32
30
  // this.relations.get(parentEventId).get(relationType).get(relationEventType)
33
31
  (0, _defineProperty2.default)(this, "relations", new Map());
32
+ this.client = client;
33
+ this.room = room;
34
34
  }
35
35
 
36
36
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"relations-container.js","names":["_relations","require","_event","RelationsContainer","constructor","client","room","_defineProperty2","default","Map","getChildEventsForEvent","eventId","relationType","eventType","_this$relations$get","relations","get","getAllChildEventsForEvent","parentEventId","_this$relations$get2","relationsForEvent","events","relationsRecord","values","push","getRelations","aggregateParentEvent","event","getId","relationsWithRelType","relationsWithEventType","setTargetEvent","aggregateChildEvent","timelineSet","isRedacted","status","EventStatus","CANCELLED","relation","getRelation","onEventDecrypted","isDecryptionFailure","once","MatrixEventEvent","Decrypted","isBeingDecrypted","shouldAttemptDecryption","event_id","relatesToEventId","rel_type","getType","set","_this$room","_ref","_timelineSet$findEven","Relations","relatesToEvent","findEventById","getPendingEvent","addEvent","exports"],"sources":["../../src/models/relations-container.ts"],"sourcesContent":["/*\nCopyright 2022 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 { Relations } from \"./relations\";\nimport { EventType, RelationType } from \"../@types/event\";\nimport { EventStatus, MatrixEvent, MatrixEventEvent } from \"./event\";\nimport { EventTimelineSet } from \"./event-timeline-set\";\nimport { MatrixClient } from \"../client\";\nimport { Room } from \"./room\";\n\nexport class RelationsContainer {\n // A tree of objects to access a set of related children for an event, as in:\n // this.relations.get(parentEventId).get(relationType).get(relationEventType)\n private relations = new Map<string, Map<RelationType | string, Map<EventType | string, Relations>>>();\n\n public constructor(private readonly client: MatrixClient, private readonly room?: Room) {}\n\n /**\n * Get a collection of child events to a given event in this timeline set.\n *\n * @param eventId - The ID of the event that you'd like to access child events for.\n * For example, with annotations, this would be the ID of the event being annotated.\n * @param relationType - The type of relationship involved, such as \"m.annotation\", \"m.reference\", \"m.replace\", etc.\n * @param eventType - The relation event's type, such as \"m.reaction\", etc.\n * @throws If `eventId</code>, <code>relationType</code> or <code>eventType`\n * are not valid.\n *\n * @returns\n * A container for relation events or undefined if there are no relation events for\n * the relationType.\n */\n public getChildEventsForEvent(\n eventId: string,\n relationType: RelationType | string,\n eventType: EventType | string,\n ): Relations | undefined {\n return this.relations.get(eventId)?.get(relationType)?.get(eventType);\n }\n\n public getAllChildEventsForEvent(parentEventId: string): MatrixEvent[] {\n const relationsForEvent =\n this.relations.get(parentEventId) ?? new Map<RelationType | string, Map<EventType | string, Relations>>();\n const events: MatrixEvent[] = [];\n for (const relationsRecord of relationsForEvent.values()) {\n for (const relations of relationsRecord.values()) {\n events.push(...relations.getRelations());\n }\n }\n return events;\n }\n\n /**\n * Set an event as the target event if any Relations exist for it already.\n * Child events can point to other child events as their parent, so this method may be\n * called for events which are also logically child events.\n *\n * @param event - The event to check as relation target.\n */\n public aggregateParentEvent(event: MatrixEvent): void {\n const relationsForEvent = this.relations.get(event.getId()!);\n if (!relationsForEvent) return;\n\n for (const relationsWithRelType of relationsForEvent.values()) {\n for (const relationsWithEventType of relationsWithRelType.values()) {\n relationsWithEventType.setTargetEvent(event);\n }\n }\n }\n\n /**\n * Add relation events to the relevant relation collection.\n *\n * @param event - The new child event to be aggregated.\n * @param timelineSet - The event timeline set within which to search for the related event if any.\n */\n public aggregateChildEvent(event: MatrixEvent, timelineSet?: EventTimelineSet): void {\n if (event.isRedacted() || event.status === EventStatus.CANCELLED) {\n return;\n }\n\n const relation = event.getRelation();\n if (!relation) return;\n\n const onEventDecrypted = (): void => {\n if (event.isDecryptionFailure()) {\n // This could for example happen if the encryption keys are not yet available.\n // The event may still be decrypted later. Register the listener again.\n event.once(MatrixEventEvent.Decrypted, onEventDecrypted);\n return;\n }\n\n this.aggregateChildEvent(event, timelineSet);\n };\n\n // If the event is currently encrypted, wait until it has been decrypted.\n if (event.isBeingDecrypted() || event.shouldAttemptDecryption()) {\n event.once(MatrixEventEvent.Decrypted, onEventDecrypted);\n return;\n }\n\n const { event_id: relatesToEventId, rel_type: relationType } = relation;\n const eventType = event.getType();\n\n let relationsForEvent = this.relations.get(relatesToEventId!);\n if (!relationsForEvent) {\n relationsForEvent = new Map<RelationType | string, Map<EventType | string, Relations>>();\n this.relations.set(relatesToEventId!, relationsForEvent);\n }\n\n let relationsWithRelType = relationsForEvent.get(relationType!);\n if (!relationsWithRelType) {\n relationsWithRelType = new Map<EventType | string, Relations>();\n relationsForEvent.set(relationType!, relationsWithRelType);\n }\n\n let relationsWithEventType = relationsWithRelType.get(eventType);\n if (!relationsWithEventType) {\n relationsWithEventType = new Relations(relationType!, eventType, this.client);\n relationsWithRelType.set(eventType, relationsWithEventType);\n\n const room = this.room ?? timelineSet?.room;\n const relatesToEvent =\n timelineSet?.findEventById(relatesToEventId!) ??\n room?.findEventById(relatesToEventId!) ??\n room?.getPendingEvent(relatesToEventId!);\n if (relatesToEvent) {\n relationsWithEventType.setTargetEvent(relatesToEvent);\n }\n }\n\n relationsWithEventType.addEvent(event);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"relations-container.js","names":["_relations","require","_event","RelationsContainer","constructor","client","room","_defineProperty2","default","Map","getChildEventsForEvent","eventId","relationType","eventType","_this$relations$get","relations","get","getAllChildEventsForEvent","parentEventId","_this$relations$get2","relationsForEvent","events","relationsRecord","values","push","getRelations","aggregateParentEvent","event","getId","relationsWithRelType","relationsWithEventType","setTargetEvent","aggregateChildEvent","timelineSet","isRedacted","status","EventStatus","CANCELLED","relation","getRelation","onEventDecrypted","isDecryptionFailure","once","MatrixEventEvent","Decrypted","isBeingDecrypted","shouldAttemptDecryption","event_id","relatesToEventId","rel_type","getType","set","_this$room","_ref","_timelineSet$findEven","Relations","relatesToEvent","findEventById","getPendingEvent","addEvent","exports"],"sources":["../../src/models/relations-container.ts"],"sourcesContent":["/*\nCopyright 2022 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 { Relations } from \"./relations\";\nimport { EventType, RelationType } from \"../@types/event\";\nimport { EventStatus, MatrixEvent, MatrixEventEvent } from \"./event\";\nimport { EventTimelineSet } from \"./event-timeline-set\";\nimport { MatrixClient } from \"../client\";\nimport { Room } from \"./room\";\n\nexport class RelationsContainer {\n // A tree of objects to access a set of related children for an event, as in:\n // this.relations.get(parentEventId).get(relationType).get(relationEventType)\n private relations = new Map<string, Map<RelationType | string, Map<EventType | string, Relations>>>();\n\n public constructor(private readonly client: MatrixClient, private readonly room?: Room) {}\n\n /**\n * Get a collection of child events to a given event in this timeline set.\n *\n * @param eventId - The ID of the event that you'd like to access child events for.\n * For example, with annotations, this would be the ID of the event being annotated.\n * @param relationType - The type of relationship involved, such as \"m.annotation\", \"m.reference\", \"m.replace\", etc.\n * @param eventType - The relation event's type, such as \"m.reaction\", etc.\n * @throws If `eventId</code>, <code>relationType</code> or <code>eventType`\n * are not valid.\n *\n * @returns\n * A container for relation events or undefined if there are no relation events for\n * the relationType.\n */\n public getChildEventsForEvent(\n eventId: string,\n relationType: RelationType | string,\n eventType: EventType | string,\n ): Relations | undefined {\n return this.relations.get(eventId)?.get(relationType)?.get(eventType);\n }\n\n public getAllChildEventsForEvent(parentEventId: string): MatrixEvent[] {\n const relationsForEvent =\n this.relations.get(parentEventId) ?? new Map<RelationType | string, Map<EventType | string, Relations>>();\n const events: MatrixEvent[] = [];\n for (const relationsRecord of relationsForEvent.values()) {\n for (const relations of relationsRecord.values()) {\n events.push(...relations.getRelations());\n }\n }\n return events;\n }\n\n /**\n * Set an event as the target event if any Relations exist for it already.\n * Child events can point to other child events as their parent, so this method may be\n * called for events which are also logically child events.\n *\n * @param event - The event to check as relation target.\n */\n public aggregateParentEvent(event: MatrixEvent): void {\n const relationsForEvent = this.relations.get(event.getId()!);\n if (!relationsForEvent) return;\n\n for (const relationsWithRelType of relationsForEvent.values()) {\n for (const relationsWithEventType of relationsWithRelType.values()) {\n relationsWithEventType.setTargetEvent(event);\n }\n }\n }\n\n /**\n * Add relation events to the relevant relation collection.\n *\n * @param event - The new child event to be aggregated.\n * @param timelineSet - The event timeline set within which to search for the related event if any.\n */\n public aggregateChildEvent(event: MatrixEvent, timelineSet?: EventTimelineSet): void {\n if (event.isRedacted() || event.status === EventStatus.CANCELLED) {\n return;\n }\n\n const relation = event.getRelation();\n if (!relation) return;\n\n const onEventDecrypted = (): void => {\n if (event.isDecryptionFailure()) {\n // This could for example happen if the encryption keys are not yet available.\n // The event may still be decrypted later. Register the listener again.\n event.once(MatrixEventEvent.Decrypted, onEventDecrypted);\n return;\n }\n\n this.aggregateChildEvent(event, timelineSet);\n };\n\n // If the event is currently encrypted, wait until it has been decrypted.\n if (event.isBeingDecrypted() || event.shouldAttemptDecryption()) {\n event.once(MatrixEventEvent.Decrypted, onEventDecrypted);\n return;\n }\n\n const { event_id: relatesToEventId, rel_type: relationType } = relation;\n const eventType = event.getType();\n\n let relationsForEvent = this.relations.get(relatesToEventId!);\n if (!relationsForEvent) {\n relationsForEvent = new Map<RelationType | string, Map<EventType | string, Relations>>();\n this.relations.set(relatesToEventId!, relationsForEvent);\n }\n\n let relationsWithRelType = relationsForEvent.get(relationType!);\n if (!relationsWithRelType) {\n relationsWithRelType = new Map<EventType | string, Relations>();\n relationsForEvent.set(relationType!, relationsWithRelType);\n }\n\n let relationsWithEventType = relationsWithRelType.get(eventType);\n if (!relationsWithEventType) {\n relationsWithEventType = new Relations(relationType!, eventType, this.client);\n relationsWithRelType.set(eventType, relationsWithEventType);\n\n const room = this.room ?? timelineSet?.room;\n const relatesToEvent =\n timelineSet?.findEventById(relatesToEventId!) ??\n room?.findEventById(relatesToEventId!) ??\n room?.getPendingEvent(relatesToEventId!);\n if (relatesToEvent) {\n relationsWithEventType.setTargetEvent(relatesToEvent);\n }\n }\n\n relationsWithEventType.addEvent(event);\n }\n}\n"],"mappings":"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"}
@@ -52,9 +52,6 @@ class Relations extends _typedEventEmitter.TypedEventEmitter {
52
52
  */
53
53
  constructor(relationType, eventType, client, altEventTypes) {
54
54
  super();
55
- this.relationType = relationType;
56
- this.eventType = eventType;
57
- this.altEventTypes = altEventTypes;
58
55
  (0, _defineProperty2.default)(this, "relationEventIds", new Set());
59
56
  (0, _defineProperty2.default)(this, "relations", new Set());
60
57
  (0, _defineProperty2.default)(this, "annotationsByKey", {});
@@ -62,7 +59,6 @@ class Relations extends _typedEventEmitter.TypedEventEmitter {
62
59
  (0, _defineProperty2.default)(this, "sortedAnnotationsByKey", []);
63
60
  (0, _defineProperty2.default)(this, "targetEvent", null);
64
61
  (0, _defineProperty2.default)(this, "creationEmitted", false);
65
- (0, _defineProperty2.default)(this, "client", void 0);
66
62
  /**
67
63
  * Listens for event status changes to remove cancelled events.
68
64
  *
@@ -107,6 +103,9 @@ class Relations extends _typedEventEmitter.TypedEventEmitter {
107
103
  redactedEvent.removeListener(_event.MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);
108
104
  this.emit(RelationsEvent.Redaction, redactedEvent);
109
105
  });
106
+ this.relationType = relationType;
107
+ this.eventType = eventType;
108
+ this.altEventTypes = altEventTypes;
110
109
  this.client = client instanceof _room.Room ? client.client : client;
111
110
  }
112
111
 
@@ -1 +1 @@
1
- {"version":3,"file":"relations.js","names":["_event","require","_logger","_event2","_typedEventEmitter","_room","RelationsEvent","exports","matchesEventType","eventType","targetEventType","altTargetEventTypes","includes","Relations","TypedEventEmitter","constructor","relationType","client","altEventTypes","_defineProperty2","default","Set","event","status","isSending","removeListener","MatrixEventEvent","Status","onEventStatus","EventStatus","CANCELLED","removeEvent","redactedEvent","relations","has","delete","RelationType","Annotation","removeAnnotationFromAggregation","Replace","targetEvent","isState","lastReplacement","getLastReplacement","makeReplaced","BeforeRedaction","onBeforeRedaction","emit","Redaction","Room","addEvent","relationEventIds","getId","relation","getRelation","logger","error","rel_type","getType","on","add","addAnnotationToAggregation","Add","maybeEmitCreated","Remove","getRelations","_event$getRelation","key","eventsForKey","annotationsByKey","sortedAnnotationsByKey","push","sort","a","b","aEvents","bEvents","size","sender","getSender","eventsFromSender","annotationsBySender","_event$getRelation2","getSortedAnnotationsByKey","getAnnotationsBySender","replaceRelation","getServerAggregatedRelation","minTs","origin_server_ts","reduce","last","getTs","shouldAttemptDecryption","isCryptoEnabled","attemptDecryption","crypto","isBeingDecrypted","getDecryptionPromise","setTargetEvent","replacement","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, IAggregatedRelation, MatrixEvent, MatrixEventEvent } from \"./event\";\nimport { logger } from \"../logger\";\nimport { RelationType } from \"../@types/event\";\nimport { TypedEventEmitter } from \"./typed-event-emitter\";\nimport { MatrixClient } from \"../client\";\nimport { Room } from \"./room\";\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 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 && this.targetEvent && !this.targetEvent.isState()) {\n const lastReplacement = await this.getLastReplacement();\n this.targetEvent.makeReplaced(lastReplacement!);\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 && this.targetEvent && !this.targetEvent.isState()) {\n const lastReplacement = await this.getLastReplacement();\n this.targetEvent.makeReplaced(lastReplacement!);\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 && this.targetEvent && !this.targetEvent.isState()) {\n const lastReplacement = await this.getLastReplacement();\n this.targetEvent.makeReplaced(lastReplacement!);\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.isCryptoEnabled()) {\n await lastReplacement.attemptDecryption(this.client.crypto!);\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 && !this.targetEvent.isState()) {\n const replacement = await this.getLastReplacement();\n // this is the initial update, so only call it if we already have something\n // to not emit Event.replaced needlessly\n if (replacement) {\n this.targetEvent.makeReplaced(replacement);\n }\n }\n\n this.maybeEmitCreated();\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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"}
1
+ {"version":3,"file":"relations.js","names":["_event","require","_logger","_event2","_typedEventEmitter","_room","RelationsEvent","exports","matchesEventType","eventType","targetEventType","altTargetEventTypes","includes","Relations","TypedEventEmitter","constructor","relationType","client","altEventTypes","_defineProperty2","default","Set","event","status","isSending","removeListener","MatrixEventEvent","Status","onEventStatus","EventStatus","CANCELLED","removeEvent","redactedEvent","relations","has","delete","RelationType","Annotation","removeAnnotationFromAggregation","Replace","targetEvent","isState","lastReplacement","getLastReplacement","makeReplaced","BeforeRedaction","onBeforeRedaction","emit","Redaction","Room","addEvent","relationEventIds","getId","relation","getRelation","logger","error","rel_type","getType","on","add","addAnnotationToAggregation","Add","maybeEmitCreated","Remove","getRelations","_event$getRelation","key","eventsForKey","annotationsByKey","sortedAnnotationsByKey","push","sort","a","b","aEvents","bEvents","size","sender","getSender","eventsFromSender","annotationsBySender","_event$getRelation2","getSortedAnnotationsByKey","getAnnotationsBySender","replaceRelation","getServerAggregatedRelation","minTs","origin_server_ts","reduce","last","getTs","shouldAttemptDecryption","isCryptoEnabled","attemptDecryption","crypto","isBeingDecrypted","getDecryptionPromise","setTargetEvent","replacement","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, IAggregatedRelation, MatrixEvent, MatrixEventEvent } from \"./event\";\nimport { logger } from \"../logger\";\nimport { RelationType } from \"../@types/event\";\nimport { TypedEventEmitter } from \"./typed-event-emitter\";\nimport { MatrixClient } from \"../client\";\nimport { Room } from \"./room\";\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 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 && this.targetEvent && !this.targetEvent.isState()) {\n const lastReplacement = await this.getLastReplacement();\n this.targetEvent.makeReplaced(lastReplacement!);\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 && this.targetEvent && !this.targetEvent.isState()) {\n const lastReplacement = await this.getLastReplacement();\n this.targetEvent.makeReplaced(lastReplacement!);\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 && this.targetEvent && !this.targetEvent.isState()) {\n const lastReplacement = await this.getLastReplacement();\n this.targetEvent.makeReplaced(lastReplacement!);\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.isCryptoEnabled()) {\n await lastReplacement.attemptDecryption(this.client.crypto!);\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 && !this.targetEvent.isState()) {\n const replacement = await this.getLastReplacement();\n // this is the initial update, so only call it if we already have something\n // to not emit Event.replaced needlessly\n if (replacement) {\n this.targetEvent.makeReplaced(replacement);\n }\n }\n\n this.maybeEmitCreated();\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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"}
@@ -43,8 +43,6 @@ class RoomMember extends _typedEventEmitter.TypedEventEmitter {
43
43
  */
44
44
  constructor(roomId, userId) {
45
45
  super();
46
- this.roomId = roomId;
47
- this.userId = userId;
48
46
  (0, _defineProperty2.default)(this, "_isOutOfBand", false);
49
47
  (0, _defineProperty2.default)(this, "modified", -1);
50
48
  (0, _defineProperty2.default)(this, "requestedProfileInfo", false);
@@ -54,16 +52,6 @@ class RoomMember extends _typedEventEmitter.TypedEventEmitter {
54
52
  * True if the room member is currently typing.
55
53
  */
56
54
  (0, _defineProperty2.default)(this, "typing", false);
57
- /**
58
- * The human-readable name for this room member. This will be
59
- * disambiguated with a suffix of " (\@user_id:matrix.org)" if another member shares the
60
- * same displayname.
61
- */
62
- (0, _defineProperty2.default)(this, "name", void 0);
63
- /**
64
- * The ambiguous displayname of this room member.
65
- */
66
- (0, _defineProperty2.default)(this, "rawDisplayName", void 0);
67
55
  /**
68
56
  * The power level for this room member.
69
57
  */
@@ -72,14 +60,6 @@ class RoomMember extends _typedEventEmitter.TypedEventEmitter {
72
60
  * The normalised power level (0-100) for this room member.
73
61
  */
74
62
  (0, _defineProperty2.default)(this, "powerLevelNorm", 0);
75
- /**
76
- * The User object for this room member, if one exists.
77
- */
78
- (0, _defineProperty2.default)(this, "user", void 0);
79
- /**
80
- * The membership state for this room member e.g. 'join'.
81
- */
82
- (0, _defineProperty2.default)(this, "membership", void 0);
83
63
  /**
84
64
  * True if the member's name is disambiguated.
85
65
  */
@@ -88,6 +68,8 @@ class RoomMember extends _typedEventEmitter.TypedEventEmitter {
88
68
  * The events describing this RoomMember.
89
69
  */
90
70
  (0, _defineProperty2.default)(this, "events", {});
71
+ this.roomId = roomId;
72
+ this.userId = userId;
91
73
  this.name = userId;
92
74
  this.rawDisplayName = userId;
93
75
  this.updateModifiedTime();