diff --git a/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.test.ts b/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.test.ts index d9d2047d24..a7cf61027a 100644 --- a/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.test.ts +++ b/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.test.ts @@ -95,6 +95,59 @@ describe('UmbExtensionRegistry', () => { }) .unsubscribe(); }); + + it('Observable only trigged when changes made to the scope of it', (done) => { + let amountOfTimesTriggered = -1; + let lastAmount = 0; + + extensionRegistry + .extensionsOfType('section') + .subscribe((extensions) => { + amountOfTimesTriggered++; + const newAmount = extensions?.length ?? 0; + if (amountOfTimesTriggered === 0) { + expect(newAmount).to.eq(3); + } + if (amountOfTimesTriggered === 1) { + expect(newAmount).to.eq(4); + } + if (lastAmount === newAmount) { + expect(null).to.eq('Update was triggered without a change, this test should fail.'); + } else { + lastAmount = newAmount; + + if (lastAmount === 3) { + // We registerer a extension that should not affect this observable. + extensionRegistry.register({ + type: 'workspace', + name: 'test-editor-2', + alias: 'Umb.Test.Editor.2', + meta: { + entityType: 'testEntity', + }, + }); + // And then register a extension that triggers this observable. + extensionRegistry.register({ + type: 'section', + name: 'test-section-4', + alias: 'Umb.Test.Section.4', + weight: 9999, + meta: { + label: 'Test Section 4', + pathname: 'test-section-4', + }, + }); + } + + if (newAmount === 4) { + expect(amountOfTimesTriggered).to.eq(1); + expect(extensions?.[0]?.alias).to.eq('Umb.Test.Section.4'); + done(); + } + } + }) + .unsubscribe(); + }); }); }); diff --git a/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.ts b/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.ts index 5eee6b93ff..c380dc602e 100644 --- a/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.ts +++ b/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.ts @@ -1,4 +1,4 @@ -import { BehaviorSubject, withLatestFrom, map, Observable, distinctUntilChanged } from 'rxjs'; +import { BehaviorSubject, map, Observable, distinctUntilChanged, combineLatest } from 'rxjs'; import type { ManifestTypes, ManifestTypeMap, @@ -14,13 +14,13 @@ function extensionArrayMemoization( ): boolean { // If length is different, data is different: if (previousValue.length !== currentValue.length) { - return true; + return false; } // previousValue has an alias that is not present in currentValue: if (previousValue.find((p) => !currentValue.find((c) => c.alias === p.alias))) { - return true; + return false; } - return false; + return true; } function extensionSingleMemoization( @@ -28,9 +28,9 @@ function extensionSingleMemoization( currentValue: T | undefined ): boolean { if (previousValue && currentValue) { - return previousValue.alias !== currentValue.alias; + return previousValue.alias === currentValue.alias; } - return previousValue !== currentValue; + return previousValue === currentValue; } const sortExtensions = (a: ManifestBase, b: ManifestBase) => (b.weight || 0) - (a.weight || 0); @@ -124,9 +124,10 @@ export class UmbExtensionRegistry { Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase >(type: Key, alias: string) { - return this.extensions.pipe( - map((exts) => exts.find((ext) => ext.type === type && ext.alias === alias)), - withLatestFrom(this._kindsOfType(type)), + return combineLatest([ + this.extensions.pipe(map((exts) => exts.find((ext) => ext.type === type && ext.alias === alias))), + this._kindsOfType(type), + ]).pipe( map(([ext, kinds]) => { // TODO: share one merge function between the different methods of this class: // Specific Extension Meta merge (does not merge conditions) @@ -150,8 +151,7 @@ export class UmbExtensionRegistry { Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase >(type: Key) { - return this._extensionsOfType(type).pipe( - withLatestFrom(this._kindsOfType(type)), + return combineLatest([this._extensionsOfType(type), this._kindsOfType(type)]).pipe( map(([exts, kinds]) => exts .map((ext) => { @@ -175,8 +175,7 @@ export class UmbExtensionRegistry { extensionsOfTypes( types: string[] ): Observable> { - return this._extensionsOfTypes(types).pipe( - withLatestFrom(this._kindsOfTypes(types)), + return combineLatest([this._extensionsOfTypes(types), this._kindsOfTypes(types)]).pipe( map(([exts, kinds]) => exts .map((ext) => {