matrix-js-sdk 41.8.0 → 41.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +1 -1
- package/lib/@types/AESEncryptedSecretStoragePayload.js +3 -1
- package/lib/@types/IIdentityServerProvider.js +3 -1
- package/lib/@types/PushRules.js +7 -7
- package/lib/@types/PushRules.js.map +1 -1
- package/lib/@types/auth.js +4 -4
- package/lib/@types/auth.js.map +1 -1
- package/lib/@types/beacon.js +2 -2
- package/lib/@types/beacon.js.map +1 -1
- package/lib/@types/common.js +3 -1
- package/lib/@types/crypto.js +3 -1
- package/lib/@types/event.js +20 -20
- package/lib/@types/event.js.map +1 -1
- package/lib/@types/events.js +3 -1
- package/lib/@types/extensible_events.js +6 -6
- package/lib/@types/extensible_events.js.map +1 -1
- package/lib/@types/global.d.js.map +1 -1
- package/lib/@types/json.js +3 -1
- package/lib/@types/local_notifications.js +3 -1
- package/lib/@types/location.js +4 -4
- package/lib/@types/location.js.map +1 -1
- package/lib/@types/matrix-sdk-crypto-wasm.d.js +3 -1
- package/lib/@types/media.js +3 -1
- package/lib/@types/membership.js +1 -1
- package/lib/@types/membership.js.map +1 -1
- package/lib/@types/partials.js +6 -6
- package/lib/@types/partials.js.map +1 -1
- package/lib/@types/polls.js +5 -5
- package/lib/@types/polls.js.map +1 -1
- package/lib/@types/read_receipts.js +2 -2
- package/lib/@types/read_receipts.js.map +1 -1
- package/lib/@types/registration.js +3 -1
- package/lib/@types/requests.js +1 -1
- package/lib/@types/requests.js.map +1 -1
- package/lib/@types/retention.js +1 -1
- package/lib/@types/retention.js.map +1 -1
- package/lib/@types/search.js +1 -1
- package/lib/@types/search.js.map +1 -1
- package/lib/@types/signed.js +3 -1
- package/lib/@types/spaces.js +3 -1
- package/lib/@types/state_events.js +3 -1
- package/lib/@types/synapse.js +3 -1
- package/lib/@types/sync.js +1 -1
- package/lib/@types/sync.js.map +1 -1
- package/lib/@types/threepids.js +1 -1
- package/lib/@types/threepids.js.map +1 -1
- package/lib/@types/topic.js +1 -1
- package/lib/@types/topic.js.map +1 -1
- package/lib/@types/uia.js +3 -1
- package/lib/NamespacedValue.js +8 -8
- package/lib/NamespacedValue.js.map +1 -1
- package/lib/ReEmitter.js +9 -16
- package/lib/ReEmitter.js.map +1 -1
- package/lib/ToDeviceMessageQueue.js +49 -57
- package/lib/ToDeviceMessageQueue.js.map +1 -1
- package/lib/autodiscovery.js +232 -247
- package/lib/autodiscovery.js.map +1 -1
- package/lib/base64.js +1 -1
- package/lib/base64.js.map +1 -1
- package/lib/browser-index.d.ts +2 -2
- package/lib/browser-index.d.ts.map +1 -1
- package/lib/browser-index.js +5 -5
- package/lib/browser-index.js.map +1 -1
- package/lib/capabilityPoller.js +19 -22
- package/lib/capabilityPoller.js.map +1 -1
- package/lib/client.d.ts +2 -8
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +2043 -2487
- package/lib/client.js.map +1 -1
- package/lib/common-crypto/CryptoBackend.js +2 -2
- package/lib/common-crypto/CryptoBackend.js.map +1 -1
- package/lib/common-crypto/key-passphrase.js.map +1 -1
- package/lib/content-helpers.js +43 -48
- package/lib/content-helpers.js.map +1 -1
- package/lib/content-repo.js +14 -24
- package/lib/content-repo.js.map +1 -1
- package/lib/crypto/store/base.js +6 -6
- package/lib/crypto/store/base.js.map +1 -1
- package/lib/crypto/store/indexeddb-crypto-store-backend.js +190 -238
- package/lib/crypto/store/indexeddb-crypto-store-backend.js.map +1 -1
- package/lib/crypto/store/indexeddb-crypto-store.js +25 -30
- package/lib/crypto/store/indexeddb-crypto-store.js.map +1 -1
- package/lib/crypto/store/localStorage-crypto-store.js +113 -145
- package/lib/crypto/store/localStorage-crypto-store.js.map +1 -1
- package/lib/crypto/store/memory-crypto-store.js +74 -105
- package/lib/crypto/store/memory-crypto-store.js.map +1 -1
- package/lib/crypto-api/CryptoEvent.js +1 -1
- package/lib/crypto-api/CryptoEvent.js.map +1 -1
- package/lib/crypto-api/CryptoEventHandlerMap.js +3 -1
- package/lib/crypto-api/index.d.ts +15 -6
- package/lib/crypto-api/index.d.ts.map +1 -1
- package/lib/crypto-api/index.js +22 -22
- package/lib/crypto-api/index.js.map +1 -1
- package/lib/crypto-api/key-passphrase.js +15 -23
- package/lib/crypto-api/key-passphrase.js.map +1 -1
- package/lib/crypto-api/keybackup.js +3 -1
- package/lib/crypto-api/recovery-key.js +11 -12
- package/lib/crypto-api/recovery-key.js.map +1 -1
- package/lib/crypto-api/verification.js +3 -3
- package/lib/crypto-api/verification.js.map +1 -1
- package/lib/digest.js +7 -14
- package/lib/digest.js.map +1 -1
- package/lib/embedded.d.ts.map +1 -1
- package/lib/embedded.js +380 -505
- package/lib/embedded.js.map +1 -1
- package/lib/errors.js +2 -2
- package/lib/errors.js.map +1 -1
- package/lib/event-mapper.js +10 -12
- package/lib/event-mapper.js.map +1 -1
- package/lib/extensible_events_v1/ExtensibleEvent.js.map +1 -1
- package/lib/extensible_events_v1/InvalidEventError.js.map +1 -1
- package/lib/extensible_events_v1/MessageEvent.js +11 -13
- package/lib/extensible_events_v1/MessageEvent.js.map +1 -1
- package/lib/extensible_events_v1/PollEndEvent.js +3 -4
- package/lib/extensible_events_v1/PollEndEvent.js.map +1 -1
- package/lib/extensible_events_v1/PollResponseEvent.js +5 -6
- package/lib/extensible_events_v1/PollResponseEvent.js.map +1 -1
- package/lib/extensible_events_v1/PollStartEvent.js +8 -10
- package/lib/extensible_events_v1/PollStartEvent.js.map +1 -1
- package/lib/extensible_events_v1/utilities.js.map +1 -1
- package/lib/feature.js +18 -31
- package/lib/feature.js.map +1 -1
- package/lib/filter-component.d.ts.map +1 -1
- package/lib/filter-component.js +20 -26
- package/lib/filter-component.js.map +1 -1
- package/lib/filter.js +14 -17
- package/lib/filter.js.map +1 -1
- package/lib/http-api/errors.js +28 -43
- package/lib/http-api/errors.js.map +1 -1
- package/lib/http-api/fetch.js +141 -159
- package/lib/http-api/fetch.js.map +1 -1
- package/lib/http-api/index.js +17 -20
- package/lib/http-api/index.js.map +1 -1
- package/lib/http-api/interface.js +1 -1
- package/lib/http-api/interface.js.map +1 -1
- package/lib/http-api/method.js +1 -1
- package/lib/http-api/method.js.map +1 -1
- package/lib/http-api/prefix.js +3 -3
- package/lib/http-api/prefix.js.map +1 -1
- package/lib/http-api/refresh.js +74 -94
- package/lib/http-api/refresh.js.map +1 -1
- package/lib/http-api/utils.d.ts +1 -1
- package/lib/http-api/utils.d.ts.map +1 -1
- package/lib/http-api/utils.js +34 -42
- package/lib/http-api/utils.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/indexeddb-helpers.js +3 -3
- package/lib/indexeddb-helpers.js.map +1 -1
- package/lib/indexeddb-worker.js.map +1 -1
- package/lib/interactive-auth.d.ts +5 -5
- package/lib/interactive-auth.d.ts.map +1 -1
- package/lib/interactive-auth.js +172 -204
- package/lib/interactive-auth.js.map +1 -1
- package/lib/logger.js +21 -57
- package/lib/logger.js.map +1 -1
- package/lib/matrix.js +7 -11
- package/lib/matrix.js.map +1 -1
- package/lib/matrixrtc/CallMembership.js +80 -74
- package/lib/matrixrtc/CallMembership.js.map +1 -1
- package/lib/matrixrtc/EncryptionManager.js +1 -1
- package/lib/matrixrtc/EncryptionManager.js.map +1 -1
- package/lib/matrixrtc/IKeyTransport.js +1 -1
- package/lib/matrixrtc/IKeyTransport.js.map +1 -1
- package/lib/matrixrtc/IMembershipManager.js +1 -1
- package/lib/matrixrtc/IMembershipManager.js.map +1 -1
- package/lib/matrixrtc/LivekitTransport.d.ts +1 -1
- package/lib/matrixrtc/LivekitTransport.js +4 -4
- package/lib/matrixrtc/LivekitTransport.js.map +1 -1
- package/lib/matrixrtc/MatrixRTCSession.js +137 -187
- package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
- package/lib/matrixrtc/MatrixRTCSessionManager.js +36 -41
- package/lib/matrixrtc/MatrixRTCSessionManager.js.map +1 -1
- package/lib/matrixrtc/MembershipManager.js +332 -378
- package/lib/matrixrtc/MembershipManager.js.map +1 -1
- package/lib/matrixrtc/MembershipManagerActionScheduler.js +54 -63
- package/lib/matrixrtc/MembershipManagerActionScheduler.js.map +1 -1
- package/lib/matrixrtc/RTCEncryptionManager.js +119 -143
- package/lib/matrixrtc/RTCEncryptionManager.js.map +1 -1
- package/lib/matrixrtc/ToDeviceKeyTransport.js +53 -58
- package/lib/matrixrtc/ToDeviceKeyTransport.js.map +1 -1
- package/lib/matrixrtc/index.js.map +1 -1
- package/lib/matrixrtc/membershipData/common.js +1 -1
- package/lib/matrixrtc/membershipData/common.js.map +1 -1
- package/lib/matrixrtc/membershipData/index.js.map +1 -1
- package/lib/matrixrtc/membershipData/rtc.js +15 -23
- package/lib/matrixrtc/membershipData/rtc.js.map +1 -1
- package/lib/matrixrtc/membershipData/session.js +4 -5
- package/lib/matrixrtc/membershipData/session.js.map +1 -1
- package/lib/matrixrtc/types.js +4 -6
- package/lib/matrixrtc/types.js.map +1 -1
- package/lib/matrixrtc/utils.js +4 -11
- package/lib/matrixrtc/utils.js.map +1 -1
- package/lib/models/MSC3089Branch.js +91 -116
- package/lib/models/MSC3089Branch.js.map +1 -1
- package/lib/models/MSC3089TreeSpace.js +209 -245
- package/lib/models/MSC3089TreeSpace.js.map +1 -1
- package/lib/models/ToDeviceMessage.js +3 -1
- package/lib/models/beacon.js +14 -13
- package/lib/models/beacon.js.map +1 -1
- package/lib/models/compare-event-ordering.js +13 -13
- package/lib/models/compare-event-ordering.js.map +1 -1
- package/lib/models/device.js +3 -3
- package/lib/models/device.js.map +1 -1
- package/lib/models/event-context.js +5 -8
- package/lib/models/event-context.js.map +1 -1
- package/lib/models/event-status.js +1 -1
- package/lib/models/event-status.js.map +1 -1
- package/lib/models/event-timeline-set.js +88 -94
- package/lib/models/event-timeline-set.js.map +1 -1
- package/lib/models/event-timeline.js +28 -30
- package/lib/models/event-timeline.js.map +1 -1
- package/lib/models/event.js +182 -226
- package/lib/models/event.js.map +1 -1
- package/lib/models/invites-ignorer-types.js +4 -4
- package/lib/models/invites-ignorer-types.js.map +1 -1
- package/lib/models/invites-ignorer.js +159 -179
- package/lib/models/invites-ignorer.js.map +1 -1
- package/lib/models/poll.js +71 -81
- package/lib/models/poll.js.map +1 -1
- package/lib/models/profile-keys.js +2 -2
- package/lib/models/profile-keys.js.map +1 -1
- package/lib/models/read-receipt.js +40 -56
- package/lib/models/read-receipt.js.map +1 -1
- package/lib/models/related-relations.js.map +1 -1
- package/lib/models/relations-container.js +22 -23
- package/lib/models/relations-container.js.map +1 -1
- package/lib/models/relations.js +133 -159
- package/lib/models/relations.js.map +1 -1
- package/lib/models/room-member.js +24 -29
- package/lib/models/room-member.js.map +1 -1
- package/lib/models/room-receipts.js +29 -43
- package/lib/models/room-receipts.js.map +1 -1
- package/lib/models/room-retention.js +74 -83
- package/lib/models/room-retention.js.map +1 -1
- package/lib/models/room-state.js +143 -172
- package/lib/models/room-state.js.map +1 -1
- package/lib/models/room-sticky-events.d.ts +1 -0
- package/lib/models/room-sticky-events.d.ts.map +1 -1
- package/lib/models/room-sticky-events.js +45 -65
- package/lib/models/room-sticky-events.js.map +1 -1
- package/lib/models/room-summary.js.map +1 -1
- package/lib/models/room.d.ts.map +1 -1
- package/lib/models/room.js +765 -909
- package/lib/models/room.js.map +1 -1
- package/lib/models/search-result.js +5 -5
- package/lib/models/search-result.js.map +1 -1
- package/lib/models/thread.js +225 -285
- package/lib/models/thread.js.map +1 -1
- package/lib/models/typed-event-emitter.js +7 -18
- package/lib/models/typed-event-emitter.js.map +1 -1
- package/lib/models/user.js +8 -8
- package/lib/models/user.js.map +1 -1
- package/lib/oidc/authorize.js +208 -241
- package/lib/oidc/authorize.js.map +1 -1
- package/lib/oidc/discovery.js +23 -36
- package/lib/oidc/discovery.js.map +1 -1
- package/lib/oidc/error.js +1 -1
- package/lib/oidc/error.js.map +1 -1
- package/lib/oidc/index.js +1 -0
- package/lib/oidc/index.js.map +1 -1
- package/lib/oidc/register.js +60 -66
- package/lib/oidc/register.js.map +1 -1
- package/lib/oidc/tokenRefresher.js +77 -91
- package/lib/oidc/tokenRefresher.js.map +1 -1
- package/lib/oidc/validate.js +18 -18
- package/lib/oidc/validate.js.map +1 -1
- package/lib/pushprocessor.js +71 -82
- package/lib/pushprocessor.js.map +1 -1
- package/lib/randomstring.js +9 -9
- package/lib/randomstring.js.map +1 -1
- package/lib/realtime-callbacks.js +25 -28
- package/lib/realtime-callbacks.js.map +1 -1
- package/lib/receipt-accumulator.d.ts +2 -0
- package/lib/receipt-accumulator.d.ts.map +1 -1
- package/lib/receipt-accumulator.js +14 -22
- package/lib/receipt-accumulator.js.map +1 -1
- package/lib/rendezvous/MSC4108SignInWithQR.js +271 -302
- package/lib/rendezvous/MSC4108SignInWithQR.js.map +1 -1
- package/lib/rendezvous/RendezvousChannel.js +3 -1
- package/lib/rendezvous/RendezvousCode.js +3 -1
- package/lib/rendezvous/RendezvousError.js.map +1 -1
- package/lib/rendezvous/RendezvousFailureReason.js +2 -2
- package/lib/rendezvous/RendezvousFailureReason.js.map +1 -1
- package/lib/rendezvous/RendezvousIntent.js +1 -1
- package/lib/rendezvous/RendezvousIntent.js.map +1 -1
- package/lib/rendezvous/RendezvousTransport.js +3 -1
- package/lib/rendezvous/channels/MSC4108SecureChannel.js +123 -147
- package/lib/rendezvous/channels/MSC4108SecureChannel.js.map +1 -1
- package/lib/rendezvous/index.js +44 -69
- package/lib/rendezvous/index.js.map +1 -1
- package/lib/rendezvous/transports/MSC4108RendezvousSession.d.ts +1 -1
- package/lib/rendezvous/transports/MSC4108RendezvousSession.js +134 -152
- package/lib/rendezvous/transports/MSC4108RendezvousSession.js.map +1 -1
- package/lib/retentionPolicy.js +6 -9
- package/lib/retentionPolicy.js.map +1 -1
- package/lib/room-hierarchy.js +52 -60
- package/lib/room-hierarchy.js.map +1 -1
- package/lib/rust-crypto/CrossSigningIdentity.js +94 -104
- package/lib/rust-crypto/CrossSigningIdentity.js.map +1 -1
- package/lib/rust-crypto/DehydratedDeviceManager.js +157 -190
- package/lib/rust-crypto/DehydratedDeviceManager.js.map +1 -1
- package/lib/rust-crypto/KeyClaimManager.js +18 -22
- package/lib/rust-crypto/KeyClaimManager.js.map +1 -1
- package/lib/rust-crypto/OutgoingRequestProcessor.js +109 -139
- package/lib/rust-crypto/OutgoingRequestProcessor.js.map +1 -1
- package/lib/rust-crypto/OutgoingRequestsManager.js +66 -80
- package/lib/rust-crypto/OutgoingRequestsManager.js.map +1 -1
- package/lib/rust-crypto/PerSessionKeyBackupDownloader.d.ts +1 -1
- package/lib/rust-crypto/PerSessionKeyBackupDownloader.js +196 -224
- package/lib/rust-crypto/PerSessionKeyBackupDownloader.js.map +1 -1
- package/lib/rust-crypto/RoomEncryptor.js +127 -143
- package/lib/rust-crypto/RoomEncryptor.js.map +1 -1
- package/lib/rust-crypto/backup.js +453 -549
- package/lib/rust-crypto/backup.js.map +1 -1
- package/lib/rust-crypto/constants.js +1 -1
- package/lib/rust-crypto/constants.js.map +1 -1
- package/lib/rust-crypto/device-converter.js +15 -28
- package/lib/rust-crypto/device-converter.js.map +1 -1
- package/lib/rust-crypto/index.js +103 -116
- package/lib/rust-crypto/index.js.map +1 -1
- package/lib/rust-crypto/libolm_migration.js +303 -365
- package/lib/rust-crypto/libolm_migration.js.map +1 -1
- package/lib/rust-crypto/rust-crypto.d.ts +5 -1
- package/lib/rust-crypto/rust-crypto.d.ts.map +1 -1
- package/lib/rust-crypto/rust-crypto.js +1067 -1332
- package/lib/rust-crypto/rust-crypto.js.map +1 -1
- package/lib/rust-crypto/secret-storage.js +12 -25
- package/lib/rust-crypto/secret-storage.js.map +1 -1
- package/lib/rust-crypto/verification.js +137 -189
- package/lib/rust-crypto/verification.js.map +1 -1
- package/lib/scheduler.js +44 -19
- package/lib/scheduler.js.map +1 -1
- package/lib/secret-storage.js +179 -213
- package/lib/secret-storage.js.map +1 -1
- package/lib/serverCapabilities.js +6 -9
- package/lib/serverCapabilities.js.map +1 -1
- package/lib/service-types.js +1 -1
- package/lib/service-types.js.map +1 -1
- package/lib/sliding-sync-sdk.d.ts.map +1 -1
- package/lib/sliding-sync-sdk.js +368 -424
- package/lib/sliding-sync-sdk.js.map +1 -1
- package/lib/sliding-sync.js +135 -171
- package/lib/sliding-sync.js.map +1 -1
- package/lib/store/index.js +3 -1
- package/lib/store/indexeddb-backend.js +3 -1
- package/lib/store/indexeddb-local-backend.js +194 -253
- package/lib/store/indexeddb-local-backend.js.map +1 -1
- package/lib/store/indexeddb-remote-backend.js +33 -63
- package/lib/store/indexeddb-remote-backend.js.map +1 -1
- package/lib/store/indexeddb-store-worker.js +22 -23
- package/lib/store/indexeddb-store-worker.js.map +1 -1
- package/lib/store/indexeddb.js +44 -71
- package/lib/store/indexeddb.js.map +1 -1
- package/lib/store/local-storage-events-emitter.js +2 -2
- package/lib/store/local-storage-events-emitter.js.map +1 -1
- package/lib/store/memory.js +34 -57
- package/lib/store/memory.js.map +1 -1
- package/lib/store/stub.js +22 -35
- package/lib/store/stub.js.map +1 -1
- package/lib/sync-accumulator.js +54 -66
- package/lib/sync-accumulator.js.map +1 -1
- package/lib/sync.d.ts.map +1 -1
- package/lib/sync.js +905 -998
- package/lib/sync.js.map +1 -1
- package/lib/testing.js +63 -105
- package/lib/testing.js.map +1 -1
- package/lib/thread-utils.js +1 -4
- package/lib/thread-utils.js.map +1 -1
- package/lib/timeline-window.js +89 -102
- package/lib/timeline-window.js.map +1 -1
- package/lib/types.js +1 -1
- package/lib/types.js.map +1 -1
- package/lib/utils/decryptAESSecretStorageItem.js +14 -25
- package/lib/utils/decryptAESSecretStorageItem.js.map +1 -1
- package/lib/utils/encryptAESSecretStorageItem.js +27 -38
- package/lib/utils/encryptAESSecretStorageItem.js.map +1 -1
- package/lib/utils/internal/deriveKeys.js +25 -32
- package/lib/utils/internal/deriveKeys.js.map +1 -1
- package/lib/utils/roomVersion.js +1 -1
- package/lib/utils/roomVersion.js.map +1 -1
- package/lib/utils.js +83 -135
- package/lib/utils.js.map +1 -1
- package/lib/version-support.js +3 -3
- package/lib/version-support.js.map +1 -1
- package/lib/webrtc/audioContext.js +5 -6
- package/lib/webrtc/audioContext.js.map +1 -1
- package/lib/webrtc/call.js +1081 -1250
- package/lib/webrtc/call.js.map +1 -1
- package/lib/webrtc/callEventHandler.js +202 -214
- package/lib/webrtc/callEventHandler.js.map +1 -1
- package/lib/webrtc/callEventTypes.js +2 -2
- package/lib/webrtc/callEventTypes.js.map +1 -1
- package/lib/webrtc/callFeed.js +18 -20
- package/lib/webrtc/callFeed.js.map +1 -1
- package/lib/webrtc/groupCall.js +513 -602
- package/lib/webrtc/groupCall.js.map +1 -1
- package/lib/webrtc/groupCallEventHandler.js +59 -62
- package/lib/webrtc/groupCallEventHandler.js.map +1 -1
- package/lib/webrtc/mediaHandler.js +198 -232
- package/lib/webrtc/mediaHandler.js.map +1 -1
- package/lib/webrtc/stats/callFeedStatsReporter.js +16 -20
- package/lib/webrtc/stats/callFeedStatsReporter.js.map +1 -1
- package/lib/webrtc/stats/callStatsReportGatherer.js +67 -75
- package/lib/webrtc/stats/callStatsReportGatherer.js.map +1 -1
- package/lib/webrtc/stats/callStatsReportSummary.js +3 -1
- package/lib/webrtc/stats/connectionStats.js.map +1 -1
- package/lib/webrtc/stats/connectionStatsBuilder.js +2 -2
- package/lib/webrtc/stats/connectionStatsBuilder.js.map +1 -1
- package/lib/webrtc/stats/connectionStatsReportBuilder.js +20 -24
- package/lib/webrtc/stats/connectionStatsReportBuilder.js.map +1 -1
- package/lib/webrtc/stats/groupCallStats.js +6 -8
- package/lib/webrtc/stats/groupCallStats.js.map +1 -1
- package/lib/webrtc/stats/media/mediaSsrcHandler.js +7 -8
- package/lib/webrtc/stats/media/mediaSsrcHandler.js.map +1 -1
- package/lib/webrtc/stats/media/mediaTrackHandler.js +7 -9
- package/lib/webrtc/stats/media/mediaTrackHandler.js.map +1 -1
- package/lib/webrtc/stats/media/mediaTrackStats.js +3 -3
- package/lib/webrtc/stats/media/mediaTrackStats.js.map +1 -1
- package/lib/webrtc/stats/media/mediaTrackStatsHandler.js +7 -7
- package/lib/webrtc/stats/media/mediaTrackStatsHandler.js.map +1 -1
- package/lib/webrtc/stats/statsReport.js +1 -1
- package/lib/webrtc/stats/statsReport.js.map +1 -1
- package/lib/webrtc/stats/statsReportEmitter.js.map +1 -1
- package/lib/webrtc/stats/summaryStatsReportGatherer.js +14 -14
- package/lib/webrtc/stats/summaryStatsReportGatherer.js.map +1 -1
- package/lib/webrtc/stats/trackStatsBuilder.js +32 -34
- package/lib/webrtc/stats/trackStatsBuilder.js.map +1 -1
- package/lib/webrtc/stats/transportStats.js +3 -1
- package/lib/webrtc/stats/transportStatsBuilder.js +9 -9
- package/lib/webrtc/stats/transportStatsBuilder.js.map +1 -1
- package/lib/webrtc/stats/valueFormatter.js +1 -1
- package/lib/webrtc/stats/valueFormatter.js.map +1 -1
- package/package.json +18 -33
- package/src/@types/global.d.ts +2 -2
- package/src/ToDeviceMessageQueue.ts +2 -2
- package/src/browser-index.ts +4 -4
- package/src/client.ts +15 -20
- package/src/crypto-api/index.ts +17 -6
- package/src/embedded.ts +4 -6
- package/src/filter-component.ts +1 -0
- package/src/http-api/utils.ts +1 -1
- package/src/interactive-auth.ts +11 -5
- package/src/matrixrtc/LivekitTransport.ts +1 -1
- package/src/matrixrtc/MatrixRTCSession.ts +1 -1
- package/src/models/MSC3089Branch.ts +1 -1
- package/src/models/room-sticky-events.ts +1 -0
- package/src/models/room.ts +9 -11
- package/src/receipt-accumulator.ts +2 -0
- package/src/rendezvous/index.ts +1 -1
- package/src/rendezvous/transports/MSC4108RendezvousSession.ts +2 -2
- package/src/rust-crypto/PerSessionKeyBackupDownloader.ts +1 -1
- package/src/rust-crypto/index.ts +6 -6
- package/src/rust-crypto/rust-crypto.ts +31 -7
- package/src/rust-crypto/verification.ts +1 -1
- package/src/sliding-sync-sdk.ts +5 -7
- package/src/store/indexeddb-local-backend.ts +3 -3
- package/src/sync.ts +6 -8
package/lib/models/poll.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
2
|
/*
|
|
4
3
|
Copyright 2023 The Matrix.org Foundation C.I.C.
|
|
@@ -20,7 +19,7 @@ import { M_POLL_START } from "matrix-events-sdk";
|
|
|
20
19
|
import { M_POLL_END, M_POLL_RESPONSE } from "../@types/polls.js";
|
|
21
20
|
import { Relations } from "./relations.js";
|
|
22
21
|
import { TypedEventEmitter } from "./typed-event-emitter.js";
|
|
23
|
-
export
|
|
22
|
+
export let PollEvent = /*#__PURE__*/function (PollEvent) {
|
|
24
23
|
PollEvent["New"] = "Poll.new";
|
|
25
24
|
PollEvent["End"] = "Poll.end";
|
|
26
25
|
PollEvent["Update"] = "Poll.update";
|
|
@@ -29,8 +28,8 @@ export var PollEvent = /*#__PURE__*/function (PollEvent) {
|
|
|
29
28
|
PollEvent["UndecryptableRelations"] = "Poll.UndecryptableRelations";
|
|
30
29
|
return PollEvent;
|
|
31
30
|
}({});
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
const filterResponseRelations = (relationEvents, pollEndTimestamp) => {
|
|
32
|
+
const responseEvents = relationEvents.filter(event => {
|
|
34
33
|
if (event.isDecryptionFailure()) {
|
|
35
34
|
return;
|
|
36
35
|
}
|
|
@@ -46,9 +45,6 @@ var filterResponseRelations = (relationEvents, pollEndTimestamp) => {
|
|
|
46
45
|
export class Poll extends TypedEventEmitter {
|
|
47
46
|
constructor(rootEvent, matrixClient, room) {
|
|
48
47
|
super();
|
|
49
|
-
this.rootEvent = rootEvent;
|
|
50
|
-
this.matrixClient = matrixClient;
|
|
51
|
-
this.room = room;
|
|
52
48
|
_defineProperty(this, "roomId", void 0);
|
|
53
49
|
_defineProperty(this, "pollEvent", void 0);
|
|
54
50
|
_defineProperty(this, "_isFetchingResponses", false);
|
|
@@ -61,13 +57,16 @@ export class Poll extends TypedEventEmitter {
|
|
|
61
57
|
*/
|
|
62
58
|
_defineProperty(this, "undecryptableRelationEventIds", new Set());
|
|
63
59
|
_defineProperty(this, "countUndecryptableEvents", events => {
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
const undecryptableEventIds = events.filter(event => event.isDecryptionFailure()).map(event => event.getId());
|
|
61
|
+
const previousCount = this.undecryptableRelationsCount;
|
|
66
62
|
this.undecryptableRelationEventIds = new Set([...this.undecryptableRelationEventIds, ...undecryptableEventIds]);
|
|
67
63
|
if (this.undecryptableRelationsCount !== previousCount) {
|
|
68
64
|
this.emit(PollEvent.UndecryptableRelations, this.undecryptableRelationsCount);
|
|
69
65
|
}
|
|
70
66
|
});
|
|
67
|
+
this.rootEvent = rootEvent;
|
|
68
|
+
this.matrixClient = matrixClient;
|
|
69
|
+
this.room = room;
|
|
71
70
|
if (!this.rootEvent.getRoomId() || !this.rootEvent.getId()) {
|
|
72
71
|
throw new Error("Invalid poll start event.");
|
|
73
72
|
}
|
|
@@ -78,8 +77,7 @@ export class Poll extends TypedEventEmitter {
|
|
|
78
77
|
return this.rootEvent.getId();
|
|
79
78
|
}
|
|
80
79
|
get endEventId() {
|
|
81
|
-
|
|
82
|
-
return (_this$endEvent = this.endEvent) === null || _this$endEvent === void 0 ? void 0 : _this$endEvent.getId();
|
|
80
|
+
return this.endEvent?.getId();
|
|
83
81
|
}
|
|
84
82
|
get isEnded() {
|
|
85
83
|
return !!this.endEvent;
|
|
@@ -90,23 +88,20 @@ export class Poll extends TypedEventEmitter {
|
|
|
90
88
|
get undecryptableRelationsCount() {
|
|
91
89
|
return this.undecryptableRelationEventIds.size;
|
|
92
90
|
}
|
|
93
|
-
getResponses() {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return _this.responses;
|
|
100
|
-
}
|
|
91
|
+
async getResponses() {
|
|
92
|
+
// if we have already fetched some responses
|
|
93
|
+
// just return them
|
|
94
|
+
if (this.responses) {
|
|
95
|
+
return this.responses;
|
|
96
|
+
}
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
})();
|
|
98
|
+
// if there is no fetching in progress
|
|
99
|
+
// start fetching
|
|
100
|
+
if (!this.isFetchingResponses) {
|
|
101
|
+
await this.fetchResponses();
|
|
102
|
+
}
|
|
103
|
+
// return whatever responses we got from the first page
|
|
104
|
+
return this.responses;
|
|
110
105
|
}
|
|
111
106
|
|
|
112
107
|
/**
|
|
@@ -115,7 +110,6 @@ export class Poll extends TypedEventEmitter {
|
|
|
115
110
|
* @returns void
|
|
116
111
|
*/
|
|
117
112
|
onNewRelation(event) {
|
|
118
|
-
var _this$endEvent2;
|
|
119
113
|
if (M_POLL_END.matches(event.getType()) && this.validateEndEvent(event)) {
|
|
120
114
|
this.endEvent = event;
|
|
121
115
|
this.refilterResponsesOnEnd();
|
|
@@ -126,9 +120,10 @@ export class Poll extends TypedEventEmitter {
|
|
|
126
120
|
if (!this.responses) {
|
|
127
121
|
return;
|
|
128
122
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
responseEvents
|
|
123
|
+
const pollEndTimestamp = this.endEvent?.getTs() || Number.MAX_SAFE_INTEGER;
|
|
124
|
+
const {
|
|
125
|
+
responseEvents
|
|
126
|
+
} = filterResponseRelations([event], pollEndTimestamp);
|
|
132
127
|
this.countUndecryptableEvents([event]);
|
|
133
128
|
if (responseEvents.length) {
|
|
134
129
|
responseEvents.forEach(event => {
|
|
@@ -137,51 +132,48 @@ export class Poll extends TypedEventEmitter {
|
|
|
137
132
|
this.emit(PollEvent.Responses, this.responses);
|
|
138
133
|
}
|
|
139
134
|
}
|
|
140
|
-
fetchResponses() {
|
|
141
|
-
|
|
142
|
-
return _asyncToGenerator(function* () {
|
|
143
|
-
var _this2$endEvent, _allRelations$nextBat;
|
|
144
|
-
_this2._isFetchingResponses = true;
|
|
135
|
+
async fetchResponses() {
|
|
136
|
+
this._isFetchingResponses = true;
|
|
145
137
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
138
|
+
// we want:
|
|
139
|
+
// - stable and unstable M_POLL_RESPONSE
|
|
140
|
+
// - stable and unstable M_POLL_END
|
|
141
|
+
// so make one api call and filter by event type client side
|
|
142
|
+
const allRelations = await this.matrixClient.relations(this.roomId, this.rootEvent.getId(), "m.reference", undefined, {
|
|
143
|
+
from: this.relationsNextBatch || undefined
|
|
144
|
+
});
|
|
145
|
+
await Promise.all(allRelations.events.map(event => this.matrixClient.decryptEventIfNeeded(event)));
|
|
146
|
+
const responses = this.responses || new Relations("m.reference", M_POLL_RESPONSE.name, this.matrixClient, [M_POLL_RESPONSE.altName]);
|
|
147
|
+
const pollEndEvent = allRelations.events.find(event => M_POLL_END.matches(event.getType()));
|
|
148
|
+
if (this.validateEndEvent(pollEndEvent)) {
|
|
149
|
+
this.endEvent = pollEndEvent;
|
|
150
|
+
this.refilterResponsesOnEnd();
|
|
151
|
+
this.emit(PollEvent.End);
|
|
152
|
+
}
|
|
153
|
+
const pollCloseTimestamp = this.endEvent?.getTs() || Number.MAX_SAFE_INTEGER;
|
|
154
|
+
const {
|
|
155
|
+
responseEvents
|
|
156
|
+
} = filterResponseRelations(allRelations.events, pollCloseTimestamp);
|
|
157
|
+
responseEvents.forEach(event => {
|
|
158
|
+
responses.addEvent(event);
|
|
159
|
+
});
|
|
160
|
+
this.relationsNextBatch = allRelations.nextBatch ?? undefined;
|
|
161
|
+
this.responses = responses;
|
|
162
|
+
this.countUndecryptableEvents(allRelations.events);
|
|
170
163
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
164
|
+
// while there are more pages of relations
|
|
165
|
+
// fetch them
|
|
166
|
+
if (this.relationsNextBatch) {
|
|
167
|
+
// don't await
|
|
168
|
+
// we want to return the first page as soon as possible
|
|
169
|
+
this.fetchResponses();
|
|
170
|
+
} else {
|
|
171
|
+
// no more pages
|
|
172
|
+
this._isFetchingResponses = false;
|
|
173
|
+
}
|
|
181
174
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
})();
|
|
175
|
+
// emit after updating _isFetchingResponses state
|
|
176
|
+
this.emit(PollEvent.Responses, this.responses);
|
|
185
177
|
}
|
|
186
178
|
|
|
187
179
|
/**
|
|
@@ -190,15 +182,13 @@ export class Poll extends TypedEventEmitter {
|
|
|
190
182
|
* To ensure responses are valid
|
|
191
183
|
*/
|
|
192
184
|
refilterResponsesOnEnd() {
|
|
193
|
-
var _this$endEvent3;
|
|
194
185
|
if (!this.responses) {
|
|
195
186
|
return;
|
|
196
187
|
}
|
|
197
|
-
|
|
188
|
+
const pollEndTimestamp = this.endEvent?.getTs() || Number.MAX_SAFE_INTEGER;
|
|
198
189
|
this.responses.getRelations().forEach(event => {
|
|
199
190
|
if (event.getTs() > pollEndTimestamp) {
|
|
200
|
-
|
|
201
|
-
(_this$responses = this.responses) === null || _this$responses === void 0 || _this$responses.removeEvent(event);
|
|
191
|
+
this.responses?.removeEvent(event);
|
|
202
192
|
}
|
|
203
193
|
});
|
|
204
194
|
this.emit(PollEvent.Responses, this.responses);
|
|
@@ -220,8 +210,8 @@ export class Poll extends TypedEventEmitter {
|
|
|
220
210
|
* If a m.poll.end event is received from someone other than the poll creator or user with permission to redact
|
|
221
211
|
* others' messages in the room, the event must be ignored by clients due to being invalid.
|
|
222
212
|
*/
|
|
223
|
-
|
|
224
|
-
|
|
213
|
+
const roomCurrentState = this.room.currentState;
|
|
214
|
+
const endEventSender = endEvent.getSender();
|
|
225
215
|
return !!endEventSender && (endEventSender === this.rootEvent.getSender() || roomCurrentState.maySendRedactionForEvent(this.rootEvent, endEventSender));
|
|
226
216
|
}
|
|
227
217
|
}
|
|
@@ -232,8 +222,8 @@ export class Poll extends TypedEventEmitter {
|
|
|
232
222
|
* @param event - Event to test
|
|
233
223
|
* @returns true if the event is a poll event, else false
|
|
234
224
|
*/
|
|
235
|
-
export
|
|
236
|
-
|
|
225
|
+
export const isPollEvent = event => {
|
|
226
|
+
const eventType = event.getType();
|
|
237
227
|
return M_POLL_START.matches(eventType) || M_POLL_RESPONSE.matches(eventType) || M_POLL_END.matches(eventType);
|
|
238
228
|
};
|
|
239
229
|
//# sourceMappingURL=poll.js.map
|
package/lib/models/poll.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poll.js","names":["M_POLL_START","M_POLL_END","M_POLL_RESPONSE","Relations","TypedEventEmitter","PollEvent","filterResponseRelations","relationEvents","pollEndTimestamp","responseEvents","filter","event","isDecryptionFailure","matches","getType","getTs","Poll","constructor","rootEvent","matrixClient","room","_defineProperty","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","_this","_asyncToGenerator","responses","fetchResponses","onNewRelation","_this$endEvent2","validateEndEvent","refilterResponsesOnEnd","End","Number","MAX_SAFE_INTEGER","_filterResponseRelati","countUndecryptableEvents","length","forEach","addEvent","Responses","_this2","_this2$endEvent","_allRelations$nextBat","allRelations","relations","undefined","from","relationsNextBatch","Promise","all","decryptEventIfNeeded","name","altName","pollEndEvent","find","pollCloseTimestamp","_filterResponseRelati2","nextBatch","_this$endEvent3","getRelations","_this$responses","removeEvent","roomCurrentState","currentState","endEventSender","getSender","maySendRedactionForEvent","isPollEvent","eventType"],"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.ts\";\nimport { type MatrixClient } from \"../client.ts\";\nimport { type PollStartEvent } from \"../extensible_events_v1/PollStartEvent.ts\";\nimport { type MatrixEvent } from \"./event.ts\";\nimport { Relations } from \"./relations.ts\";\nimport { type Room } from \"./room.ts\";\nimport { TypedEventEmitter } from \"./typed-event-emitter.ts\";\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(\n public readonly rootEvent: MatrixEvent,\n private matrixClient: MatrixClient,\n private room: Room,\n ) {\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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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"poll.js","names":[],"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.ts\";\nimport { type MatrixClient } from \"../client.ts\";\nimport { type PollStartEvent } from \"../extensible_events_v1/PollStartEvent.ts\";\nimport { type MatrixEvent } from \"./event.ts\";\nimport { Relations } from \"./relations.ts\";\nimport { type Room } from \"./room.ts\";\nimport { TypedEventEmitter } from \"./typed-event-emitter.ts\";\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(\n public readonly rootEvent: MatrixEvent,\n private matrixClient: MatrixClient,\n private room: Room,\n ) {\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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","ignoreList":[]}
|
|
@@ -20,7 +20,7 @@ limitations under the License.
|
|
|
20
20
|
*
|
|
21
21
|
* This key was introduced in Matrix v1.16.
|
|
22
22
|
*/
|
|
23
|
-
export
|
|
23
|
+
export const ProfileKeyTimezone = "m.tz";
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* The timezone the user is currently in. The value of this property should
|
|
@@ -30,5 +30,5 @@ export var ProfileKeyTimezone = "m.tz";
|
|
|
30
30
|
* @experimental
|
|
31
31
|
* @deprecated Unstable MSC field - Use `ProfileKeyTimezone`
|
|
32
32
|
*/
|
|
33
|
-
export
|
|
33
|
+
export const ProfileKeyMSC4175Timezone = "us.cloke.msc4175.tz";
|
|
34
34
|
//# sourceMappingURL=profile-keys.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-keys.js","names":[
|
|
1
|
+
{"version":3,"file":"profile-keys.js","names":[],"sources":["../../src/models/profile-keys.ts"],"sourcesContent":["/*\nCopyright 2025 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\n/**\n * The timezone the user is currently in. The value of this property should\n * match a timezone provided in https://www.iana.org/time-zones.\n *\n * This key was introduced in Matrix v1.16.\n */\nexport const ProfileKeyTimezone = \"m.tz\";\n\n/**\n * The timezone the user is currently in. The value of this property should\n * match a timezone provided in https://www.iana.org/time-zones.\n *\n * @see https://github.com/matrix-org/matrix-spec-proposals/blob/clokep/profile-tz/proposals/4175-profile-field-time-zone.md\n * @experimental\n * @deprecated Unstable MSC field - Use `ProfileKeyTimezone`\n */\nexport const ProfileKeyMSC4175Timezone = \"us.cloke.msc4175.tz\";\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAM,kBAAkB,GAAG,MAAM;;AAExC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAM,yBAAyB,GAAG,qBAAqB","ignoreList":[]}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
|
-
|
|
4
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
2
|
+
import _objectSpread from "@babel/runtime/helpers/objectSpread2";
|
|
5
3
|
/*
|
|
6
4
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
7
5
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -33,8 +31,7 @@ import { inMainTimelineForReceipt, threadIdForReceipt } from "../client.js";
|
|
|
33
31
|
* @param unthreaded - the receipt is unthreaded
|
|
34
32
|
* @returns a new event with the synthetic receipt in it
|
|
35
33
|
*/
|
|
36
|
-
export function synthesizeReceipt(userId, event, receiptType) {
|
|
37
|
-
var unthreaded = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
34
|
+
export function synthesizeReceipt(userId, event, receiptType, unthreaded = false) {
|
|
38
35
|
return new MatrixEvent({
|
|
39
36
|
content: {
|
|
40
37
|
[event.getId()]: {
|
|
@@ -51,11 +48,11 @@ export function synthesizeReceipt(userId, event, receiptType) {
|
|
|
51
48
|
room_id: event.getRoomId()
|
|
52
49
|
});
|
|
53
50
|
}
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
const ReceiptPairRealIndex = 0;
|
|
52
|
+
const ReceiptPairSyntheticIndex = 1;
|
|
56
53
|
export class ReadReceipt extends TypedEventEmitter {
|
|
57
|
-
constructor() {
|
|
58
|
-
super(...
|
|
54
|
+
constructor(...args) {
|
|
55
|
+
super(...args);
|
|
59
56
|
// receipts should clobber based on receipt_type and user_id pairs hence
|
|
60
57
|
// the form of this structure. This is sub-optimal for the exposed APIs
|
|
61
58
|
// which pass in an event ID and get back some receipts, so we also store
|
|
@@ -71,25 +68,18 @@ export class ReadReceipt extends TypedEventEmitter {
|
|
|
71
68
|
* @param receiptType - Optional. The type of the receipt we want to get
|
|
72
69
|
* @returns the latest receipts of the chosen type for the chosen user
|
|
73
70
|
*/
|
|
74
|
-
getReadReceiptForUserId(userId) {
|
|
75
|
-
|
|
76
|
-
var ignoreSynthesized = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
77
|
-
var receiptType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ReceiptType.Read;
|
|
78
|
-
var _ref = (_this$receipts$get$ge = (_this$receipts$get = this.receipts.get(receiptType)) === null || _this$receipts$get === void 0 ? void 0 : _this$receipts$get.get(userId)) !== null && _this$receipts$get$ge !== void 0 ? _this$receipts$get$ge : [null, null],
|
|
79
|
-
_ref2 = _slicedToArray(_ref, 2),
|
|
80
|
-
realReceipt = _ref2[0],
|
|
81
|
-
syntheticReceipt = _ref2[1];
|
|
71
|
+
getReadReceiptForUserId(userId, ignoreSynthesized = false, receiptType = ReceiptType.Read) {
|
|
72
|
+
const [realReceipt, syntheticReceipt] = this.receipts.get(receiptType)?.get(userId) ?? [null, null];
|
|
82
73
|
if (ignoreSynthesized) {
|
|
83
74
|
return realReceipt;
|
|
84
75
|
}
|
|
85
|
-
return syntheticReceipt
|
|
76
|
+
return syntheticReceipt ?? realReceipt;
|
|
86
77
|
}
|
|
87
78
|
compareReceipts(a, b) {
|
|
88
|
-
var _this$getUnfilteredTi;
|
|
89
79
|
// Try compare them in our unfiltered timeline set order, falling back to receipt timestamp which should be
|
|
90
80
|
// relatively sane as receipts are set only by the originating homeserver so as long as its clock doesn't
|
|
91
81
|
// jump around then it should be valid.
|
|
92
|
-
return
|
|
82
|
+
return this.getUnfilteredTimelineSet().compareEventOrdering(a.eventId, b.eventId) ?? a.data.ts - b.data.ts;
|
|
93
83
|
}
|
|
94
84
|
|
|
95
85
|
/**
|
|
@@ -108,10 +98,9 @@ export class ReadReceipt extends TypedEventEmitter {
|
|
|
108
98
|
* by the JS SDK.
|
|
109
99
|
* @returns ID of the latest existing event that the given user has read, or null.
|
|
110
100
|
*/
|
|
111
|
-
getEventReadUpTo(userId) {
|
|
112
|
-
var ignoreSynthesized = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
101
|
+
getEventReadUpTo(userId, ignoreSynthesized = false) {
|
|
113
102
|
// Find what the latest receipt says is the latest event we have read
|
|
114
|
-
|
|
103
|
+
const latestReceipt = this.getLatestReceipt(userId, ignoreSynthesized);
|
|
115
104
|
if (!latestReceipt) {
|
|
116
105
|
return null;
|
|
117
106
|
}
|
|
@@ -123,8 +112,7 @@ export class ReadReceipt extends TypedEventEmitter {
|
|
|
123
112
|
* threadRootId is consistent with the thread information in the receipt.
|
|
124
113
|
*/
|
|
125
114
|
receiptPointsAtConsistentEvent(receipt) {
|
|
126
|
-
|
|
127
|
-
var event = this.findEventById(receipt.eventId);
|
|
115
|
+
const event = this.findEventById(receipt.eventId);
|
|
128
116
|
if (!event) {
|
|
129
117
|
// If the receipt points at a non-existent event, we have multiple
|
|
130
118
|
// possibilities:
|
|
@@ -146,7 +134,7 @@ export class ReadReceipt extends TypedEventEmitter {
|
|
|
146
134
|
// we have. We want to pretend it doesn't exist.
|
|
147
135
|
return false;
|
|
148
136
|
}
|
|
149
|
-
if (!
|
|
137
|
+
if (!receipt.data?.thread_id) {
|
|
150
138
|
// If this is an unthreaded receipt, it could point at any event, so
|
|
151
139
|
// there is no need to validate further - this receipt is valid.
|
|
152
140
|
return true;
|
|
@@ -158,7 +146,7 @@ export class ReadReceipt extends TypedEventEmitter {
|
|
|
158
146
|
// in the main timeline.
|
|
159
147
|
|
|
160
148
|
// Check if the event is in the main timeline
|
|
161
|
-
|
|
149
|
+
const eventIsInMainTimeline = inMainTimelineForReceipt(event);
|
|
162
150
|
if (eventIsInMainTimeline) {
|
|
163
151
|
// The receipt is for the main timeline, and so is the event, so
|
|
164
152
|
// the receipt is valid.
|
|
@@ -188,70 +176,67 @@ export class ReadReceipt extends TypedEventEmitter {
|
|
|
188
176
|
// would have already returned null. We include this check to cover
|
|
189
177
|
// cases when `this` is a room, meaning findEventById will find events
|
|
190
178
|
// in any thread, and to be defensive against unforeseen code paths.
|
|
191
|
-
logger.warn(
|
|
179
|
+
logger.warn(`Ignoring receipt because its thread_id (${receipt.data.thread_id}) disagrees ` + `with the thread root (${event.threadRootId}) of the referenced event ` + `(event ID = ${receipt.eventId})`);
|
|
192
180
|
|
|
193
181
|
// This receipt is not "valid" because it disagrees with us about what
|
|
194
182
|
// thread the event is in. We want to pretend it doesn't exist.
|
|
195
183
|
return false;
|
|
196
184
|
}
|
|
197
185
|
getLatestReceipt(userId, ignoreSynthesized) {
|
|
198
|
-
var _ref3, _ref4;
|
|
199
186
|
// XXX: This is very very ugly and I hope I won't have to ever add a new
|
|
200
187
|
// receipt type here again. IMHO this should be done by the server in
|
|
201
188
|
// some more intelligent manner or the client should just use timestamps
|
|
202
189
|
|
|
203
|
-
|
|
204
|
-
|
|
190
|
+
const publicReadReceipt = this.getReadReceiptForUserId(userId, ignoreSynthesized, ReceiptType.Read);
|
|
191
|
+
const privateReadReceipt = this.getReadReceiptForUserId(userId, ignoreSynthesized, ReceiptType.ReadPrivate);
|
|
205
192
|
|
|
206
193
|
// If we have both, compare them
|
|
207
|
-
|
|
208
|
-
if (publicReadReceipt
|
|
194
|
+
let comparison;
|
|
195
|
+
if (publicReadReceipt?.eventId && privateReadReceipt?.eventId) {
|
|
209
196
|
comparison = this.compareReceipts(publicReadReceipt, privateReadReceipt);
|
|
210
197
|
}
|
|
211
198
|
|
|
212
199
|
// The public receipt is more likely to drift out of date so the private
|
|
213
200
|
// one has precedence
|
|
214
|
-
if (!comparison) return
|
|
201
|
+
if (!comparison) return privateReadReceipt ?? publicReadReceipt ?? null;
|
|
215
202
|
|
|
216
203
|
// If public read receipt is older, return the private one
|
|
217
|
-
return (
|
|
204
|
+
return (comparison < 0 ? privateReadReceipt : publicReadReceipt) ?? null;
|
|
218
205
|
}
|
|
219
206
|
addReceiptToStructure(eventId, receiptType, userId, receipt, synthetic) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
var pair = receiptTypesMap.get(userId);
|
|
207
|
+
const receiptTypesMap = this.receipts.getOrCreate(receiptType);
|
|
208
|
+
let pair = receiptTypesMap.get(userId);
|
|
223
209
|
if (!pair) {
|
|
224
210
|
pair = [null, null];
|
|
225
211
|
receiptTypesMap.set(userId, pair);
|
|
226
212
|
}
|
|
227
|
-
|
|
213
|
+
let existingReceipt = pair[ReceiptPairRealIndex];
|
|
228
214
|
if (synthetic) {
|
|
229
|
-
|
|
230
|
-
existingReceipt = (_pair$ReceiptPairSynt = pair[ReceiptPairSyntheticIndex]) !== null && _pair$ReceiptPairSynt !== void 0 ? _pair$ReceiptPairSynt : pair[ReceiptPairRealIndex];
|
|
215
|
+
existingReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];
|
|
231
216
|
}
|
|
232
|
-
|
|
217
|
+
const wrappedReceipt = {
|
|
233
218
|
eventId,
|
|
234
219
|
data: receipt
|
|
235
220
|
};
|
|
236
221
|
if (existingReceipt) {
|
|
237
222
|
// We only want to add this receipt if we think it is later than the one we already have.
|
|
238
223
|
// This is managed server-side, but because we synthesize RRs locally we have to do it here too.
|
|
239
|
-
|
|
240
|
-
if (
|
|
224
|
+
const ordering = this.compareReceipts(existingReceipt, wrappedReceipt);
|
|
225
|
+
if (ordering >= 0) {
|
|
241
226
|
return;
|
|
242
227
|
}
|
|
243
228
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
229
|
+
const realReceipt = synthetic ? pair[ReceiptPairRealIndex] : wrappedReceipt;
|
|
230
|
+
const syntheticReceipt = synthetic ? wrappedReceipt : pair[ReceiptPairSyntheticIndex];
|
|
231
|
+
let ordering = null;
|
|
247
232
|
if (realReceipt && syntheticReceipt) {
|
|
248
233
|
ordering = this.getUnfilteredTimelineSet().compareEventOrdering(realReceipt.eventId, syntheticReceipt.eventId);
|
|
249
234
|
}
|
|
250
|
-
|
|
235
|
+
const preferSynthetic = ordering === null || ordering < 0;
|
|
251
236
|
|
|
252
237
|
// we don't bother caching just real receipts by event ID as there's nothing that would read it.
|
|
253
238
|
// Take the current cached receipt before we overwrite the pair elements.
|
|
254
|
-
|
|
239
|
+
const cachedReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];
|
|
255
240
|
if (synthetic && preferSynthetic) {
|
|
256
241
|
pair[ReceiptPairSyntheticIndex] = wrappedReceipt;
|
|
257
242
|
} else if (!synthetic) {
|
|
@@ -260,12 +245,12 @@ export class ReadReceipt extends TypedEventEmitter {
|
|
|
260
245
|
pair[ReceiptPairSyntheticIndex] = null;
|
|
261
246
|
}
|
|
262
247
|
}
|
|
263
|
-
|
|
248
|
+
const newCachedReceipt = pair[ReceiptPairSyntheticIndex] ?? pair[ReceiptPairRealIndex];
|
|
264
249
|
if (cachedReceipt === newCachedReceipt) return;
|
|
265
250
|
|
|
266
251
|
// clean up any previous cache entry
|
|
267
252
|
if (cachedReceipt && this.receiptCacheByEventId.get(cachedReceipt.eventId)) {
|
|
268
|
-
|
|
253
|
+
const previousEventId = cachedReceipt.eventId;
|
|
269
254
|
// Remove the receipt we're about to clobber out of existence from the cache
|
|
270
255
|
this.receiptCacheByEventId.set(previousEventId, this.receiptCacheByEventId.get(previousEventId).filter(r => {
|
|
271
256
|
return r.type !== receiptType || r.userId !== userId;
|
|
@@ -314,9 +299,9 @@ export class ReadReceipt extends TypedEventEmitter {
|
|
|
314
299
|
* @param userId - the logged in user
|
|
315
300
|
*/
|
|
316
301
|
fixupNotifications(userId) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
if (lastEvent &&
|
|
302
|
+
const receipt = this.getReadReceiptForUserId(userId, false);
|
|
303
|
+
const lastEvent = this.timeline[this.timeline.length - 1];
|
|
304
|
+
if (lastEvent && receipt?.eventId === lastEvent.getId() && userId === lastEvent.getSender()) {
|
|
320
305
|
this.setUnread(NotificationCountType.Total, 0);
|
|
321
306
|
this.setUnread(NotificationCountType.Highlight, 0);
|
|
322
307
|
}
|
|
@@ -330,8 +315,7 @@ export class ReadReceipt extends TypedEventEmitter {
|
|
|
330
315
|
* @param receiptType - The type of receipt
|
|
331
316
|
* @param unthreaded - the receipt is unthreaded
|
|
332
317
|
*/
|
|
333
|
-
addLocalEchoReceipt(userId, e, receiptType) {
|
|
334
|
-
var unthreaded = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
318
|
+
addLocalEchoReceipt(userId, e, receiptType, unthreaded = false) {
|
|
335
319
|
this.addReceipt(synthesizeReceipt(userId, e, receiptType, unthreaded), true);
|
|
336
320
|
}
|
|
337
321
|
|