Merge pull request #24982 from drodil/user_settings_signals

feat: use signals to update user settings over sessions
This commit is contained in:
Fredrik Adelöw
2024-06-08 09:26:12 +02:00
committed by GitHub
19 changed files with 234 additions and 11 deletions
+2
View File
@@ -22,6 +22,7 @@ import { PropsWithChildren } from 'react';
import { default as React_2 } from 'react';
import { RouteRef } from '@backstage/core-plugin-api';
import { SessionApi } from '@backstage/core-plugin-api';
import { SignalApi } from '@backstage/plugin-signals-react';
import { StorageApi } from '@backstage/core-plugin-api';
import { StorageValueSnapshot } from '@backstage/core-plugin-api';
import { TabProps } from '@material-ui/core/Tab';
@@ -133,6 +134,7 @@ export class UserSettingsStorage implements StorageApi {
discoveryApi: DiscoveryApi;
errorApi: ErrorApi;
identityApi: IdentityApi;
signalApi?: SignalApi;
namespace?: string;
}): UserSettingsStorage;
// (undocumented)
+2
View File
@@ -56,6 +56,8 @@
"@backstage/errors": "workspace:^",
"@backstage/frontend-plugin-api": "workspace:^",
"@backstage/plugin-catalog-react": "workspace:^",
"@backstage/plugin-signals-react": "workspace:^",
"@backstage/plugin-user-settings-common": "workspace:^",
"@backstage/theme": "workspace:^",
"@backstage/types": "workspace:^",
"@material-ui/core": "^4.12.2",
@@ -25,7 +25,9 @@ import {
} from '@backstage/core-plugin-api';
import { ResponseError } from '@backstage/errors';
import { JsonValue, Observable } from '@backstage/types';
import { SignalApi, SignalSubscriber } from '@backstage/plugin-signals-react';
import ObservableImpl from 'zen-observable';
import { UserSettingsSignal } from '@backstage/plugin-user-settings-common';
const JSON_HEADERS = {
'Content-Type': 'application/json; charset=utf-8',
@@ -57,6 +59,7 @@ export class UserSettingsStorage implements StorageApi {
private readonly errorApi: ErrorApi,
private readonly identityApi: IdentityApi,
private readonly fallback: WebStorage,
private readonly signalApi?: SignalApi,
) {}
static create(options: {
@@ -64,6 +67,7 @@ export class UserSettingsStorage implements StorageApi {
discoveryApi: DiscoveryApi;
errorApi: ErrorApi;
identityApi: IdentityApi;
signalApi?: SignalApi;
namespace?: string;
}): UserSettingsStorage {
return new UserSettingsStorage(
@@ -76,6 +80,7 @@ export class UserSettingsStorage implements StorageApi {
namespace: options.namespace,
errorApi: options.errorApi,
}),
options.signalApi,
);
}
@@ -145,15 +150,33 @@ export class UserSettingsStorage implements StorageApi {
this.observables.set(
key,
new ObservableImpl<StorageValueSnapshot<JsonValue>>(subscriber => {
let signalSubscription: SignalSubscriber | undefined;
this.subscribers.add(subscriber);
// TODO(freben): Introduce server polling or similar, to ensure that different devices update when values change
Promise.resolve()
.then(() => this.get(key))
.then(snapshot => subscriber.next(snapshot))
.catch(error => this.errorApi.post(error));
const updateSnapshot = () => {
Promise.resolve()
.then(() => this.get(key))
.then(snapshot => subscriber.next(snapshot))
.catch(error => this.errorApi.post(error));
};
if (this.signalApi) {
signalSubscription = this.signalApi.subscribe(
`user-settings`,
(msg: UserSettingsSignal) => {
if (msg.key === key) {
updateSnapshot();
}
},
);
}
updateSnapshot();
return () => {
if (signalSubscription) {
signalSubscription.unsubscribe();
}
this.subscribers.delete(subscriber);
};
}).filter(({ key: messageKey }) => messageKey === key),