diff --git a/.changeset/wild-pears-enjoy.md b/.changeset/wild-pears-enjoy.md new file mode 100644 index 0000000000..01a8b8a4a1 --- /dev/null +++ b/.changeset/wild-pears-enjoy.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-app-api': patch +--- + +Made `WebStorage` notify its subscribers when `localStorage` values change in other tabs/windows diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts b/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts index b0cbfbd883..3477853241 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts @@ -35,6 +35,8 @@ export class WebStorage implements StorageApi { private readonly errorApi: ErrorApi, ) {} + private static hasSubscribed = false; + static create(options: { errorApi: ErrorApi; namespace?: string; @@ -42,6 +44,16 @@ export class WebStorage implements StorageApi { return new WebStorage(options.namespace ?? '', options.errorApi); } + private static addStorageEventListener() { + window.addEventListener('storage', event => { + for (const [bucketPath, webStorage] of buckets.entries()) { + if (event.key?.startsWith(bucketPath)) { + webStorage.handleStorageChange(event.key); + } + } + }); + } + get(key: string): T | undefined { return this.snapshot(key).value as T | undefined; } @@ -89,9 +101,19 @@ export class WebStorage implements StorageApi { observe$( key: string, ): Observable> { + if (!WebStorage.hasSubscribed) { + WebStorage.addStorageEventListener(); + WebStorage.hasSubscribed = true; + } return this.observable.filter(({ key: messageKey }) => messageKey === key); } + private handleStorageChange(eventKey: StorageEvent['key']) { + if (!eventKey?.startsWith(this.namespace)) return; + const key = eventKey?.replace(`${this.namespace}/`, ''); + this.notifyChanges(key); + } + private getKeyName(key: string) { return `${this.namespace}/${encodeURIComponent(key)}`; }