From 8191483fbd9b5a68c47cad2b6d66738adc5fa66b Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 7 Aug 2022 08:05:42 -0700 Subject: [PATCH] Evict links from maps when markers are disposed --- src/common/services/OscLinkService.ts | 45 ++++++++++++++++++++------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/src/common/services/OscLinkService.ts b/src/common/services/OscLinkService.ts index d3744229c..13bd8aa4b 100644 --- a/src/common/services/OscLinkService.ts +++ b/src/common/services/OscLinkService.ts @@ -10,12 +10,16 @@ export class OscLinkService implements IOscLinkService { private _nextId = 1; - // TODO: Evict on marker dispose - private _entriesNoId: IOscLinkEntryNoId[] = []; + /** + * A map of the link key to link entry. This is used to add additional lines to links with ids. + */ private _entriesWithId: Map = new Map(); - // The "link id" (number) which is the numberic representation of a unique link should not be - // confused with "id" (string) which comes in with "id=" in the OSC link's properties + /** + * A map of the link id to the link entry. The "link id" (number) which is the numberic + * representation of a unique link should not be confused with "id" (string) which comes in with + * `id=` in the OSC link's properties. + */ private _dataByLinkId: Map = new Map(); constructor( @@ -28,12 +32,13 @@ export class OscLinkService implements IOscLinkService { // Links with no id will only ever be registered a single time if (data.id === undefined) { + const marker = buffer.addMarker(buffer.ybase + buffer.y); const entry: IOscLinkEntryNoId = { data, id: this._nextId++, - lines: [buffer.addMarker(buffer.ybase + buffer.y)] + lines: [marker] }; - this._entriesNoId.push(entry); + marker.onDispose(() => this._removeMarkerFromLink(entry, marker)); this._dataByLinkId.set(entry.id, entry); return entry.id; } @@ -48,24 +53,28 @@ export class OscLinkService implements IOscLinkService { } // Create the link + const marker = buffer.addMarker(buffer.ybase + buffer.y); const entry: IOscLinkEntryWithId = { id: this._nextId++, key: this._getEntryIdKey(castData), data: castData, - lines: [buffer.addMarker(buffer.ybase + buffer.y)] + lines: [marker] }; + marker.onDispose(() => this._removeMarkerFromLink(entry, marker)); this._entriesWithId.set(entry.key, entry); this._dataByLinkId.set(entry.id, entry); return entry.id; } public addLineToLink(linkId: number, y: number): void { - const link = this._dataByLinkId.get(linkId); - if (!link) { + const entry = this._dataByLinkId.get(linkId); + if (!entry) { return; } - if (link.lines.every(e => e.line !== y)) { - link.lines.push(this._bufferService.buffer.addMarker(y)); + if (entry.lines.every(e => e.line !== y)) { + const marker = this._bufferService.buffer.addMarker(y); + entry.lines.push(marker); + marker.onDispose(() => this._removeMarkerFromLink(entry, marker)); } } @@ -76,6 +85,20 @@ export class OscLinkService implements IOscLinkService { private _getEntryIdKey(linkData: Required): string { return `${linkData.id};;${linkData.uri}`; } + + private _removeMarkerFromLink(entry: IOscLinkEntryNoId | IOscLinkEntryWithId, marker: IMarker): void { + const index = entry.lines.indexOf(marker); + if (index === -1) { + return; + } + entry.lines.splice(index, 1); + if (entry.lines.length === 0) { + if (entry.data.id !== undefined) { + this._entriesWithId.delete((entry as IOscLinkEntryWithId).key); + } + this._dataByLinkId.delete(entry.id); + } + } } interface IOscLinkEntry {