2020-10-30 15:19:51 +01:00
|
|
|
/*
|
|
|
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2021-09-30 02:30:21 +02:00
|
|
|
import {BaseObservableValue} from "../../observable/ObservableValue";
|
2020-10-30 15:19:51 +01:00
|
|
|
|
|
|
|
export class ObservedEventMap {
|
|
|
|
constructor(notifyEmpty) {
|
|
|
|
this._map = new Map();
|
|
|
|
this._notifyEmpty = notifyEmpty;
|
|
|
|
}
|
|
|
|
|
|
|
|
observe(eventId, eventEntry = null) {
|
|
|
|
let observable = this._map.get(eventId);
|
|
|
|
if (!observable) {
|
2021-08-04 20:08:35 +02:00
|
|
|
observable = new ObservedEvent(this, eventEntry, eventId);
|
2020-10-30 15:19:51 +01:00
|
|
|
this._map.set(eventId, observable);
|
|
|
|
}
|
|
|
|
return observable;
|
|
|
|
}
|
|
|
|
|
|
|
|
updateEvents(eventEntries) {
|
|
|
|
for (let i = 0; i < eventEntries.length; i += 1) {
|
|
|
|
const entry = eventEntries[i];
|
|
|
|
const observable = this._map.get(entry.id);
|
|
|
|
observable?.update(entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-04 20:08:35 +02:00
|
|
|
_remove(id) {
|
|
|
|
this._map.delete(id);
|
2020-10-30 15:19:51 +01:00
|
|
|
if (this._map.size === 0) {
|
|
|
|
this._notifyEmpty();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class ObservedEvent extends BaseObservableValue {
|
2021-08-04 20:08:35 +02:00
|
|
|
constructor(eventMap, entry, id) {
|
2020-10-30 15:19:51 +01:00
|
|
|
super();
|
|
|
|
this._eventMap = eventMap;
|
|
|
|
this._entry = entry;
|
2021-08-04 20:08:35 +02:00
|
|
|
this._id = id;
|
2020-10-30 15:19:51 +01:00
|
|
|
// remove subscription in microtask after creating it
|
|
|
|
// otherwise ObservedEvents would easily never get
|
|
|
|
// removed if you never subscribe
|
|
|
|
Promise.resolve().then(() => {
|
|
|
|
if (!this.hasSubscriptions) {
|
2021-08-04 20:08:35 +02:00
|
|
|
this._eventMap._remove(this._id);
|
2020-10-30 15:19:51 +01:00
|
|
|
this._eventMap = null;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
subscribe(handler) {
|
|
|
|
if (!this._eventMap) {
|
|
|
|
throw new Error("ObservedEvent expired, subscribe right after calling room.observeEvent()");
|
|
|
|
}
|
|
|
|
return super.subscribe(handler);
|
|
|
|
}
|
|
|
|
|
|
|
|
onUnsubscribeLast() {
|
2021-08-04 20:08:35 +02:00
|
|
|
this._eventMap._remove(this._id);
|
2020-10-30 15:19:51 +01:00
|
|
|
this._eventMap = null;
|
|
|
|
super.onUnsubscribeLast();
|
|
|
|
}
|
|
|
|
|
|
|
|
update(entry) {
|
|
|
|
// entries are mostly updated in-place,
|
|
|
|
// apart from when they are created,
|
|
|
|
// but doesn't hurt to reassign
|
|
|
|
this._entry = entry;
|
|
|
|
this.emit(this._entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
get() {
|
|
|
|
return this._entry;
|
|
|
|
}
|
|
|
|
}
|