Skip to content

Commit ae4c598

Browse files
committed
Refactors integrations change event
- Updates change event to provide added/removed integrations - Avoids firing unless there is a meaningful change - Removes the `onDidSyncCloudIntegrations` event
1 parent a3a2c09 commit ae4c598

File tree

6 files changed

+72
-53
lines changed

6 files changed

+72
-53
lines changed

src/autolinks/autolinksProvider.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export class AutolinksProvider implements Disposable {
5050
constructor(private readonly container: Container) {
5151
this._disposable = Disposable.from(
5252
configuration.onDidChange(this.onConfigurationChanged, this),
53-
container.integrations.onDidChangeConfiguredIntegrations(this.onConfiguredIntegrationsChanged, this),
53+
container.integrations.onDidChange(this.onIntegrationsChanged, this),
5454
);
5555

5656
this.setAutolinksFromConfig();
@@ -67,7 +67,7 @@ export class AutolinksProvider implements Disposable {
6767
}
6868
}
6969

70-
private onConfiguredIntegrationsChanged(_e: ConfiguredIntegrationsChangeEvent) {
70+
private onIntegrationsChanged(_e: ConfiguredIntegrationsChangeEvent) {
7171
this._refsetCache.clear();
7272
}
7373

src/plus/integrations/authentication/configuredIntegrationService.ts

Lines changed: 63 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@ import type { ConfiguredIntegrationDescriptor, ProviderAuthenticationSession } f
1717
interface StoredSession {
1818
id: string;
1919
accessToken: string;
20-
account?: {
21-
label?: string;
22-
displayName?: string;
23-
id: string;
24-
};
20+
account?: { label?: string; displayName?: string; id: string };
2521
scopes: string[];
2622
cloud?: boolean;
2723
expiresAt?: string;
@@ -30,7 +26,8 @@ interface StoredSession {
3026
}
3127

3228
export interface ConfiguredIntegrationsChangeEvent {
33-
ids: IntegrationIds[];
29+
readonly added: readonly IntegrationIds[];
30+
readonly removed: readonly IntegrationIds[];
3431
}
3532

3633
export class ConfiguredIntegrationService implements Disposable {
@@ -171,7 +168,7 @@ export class ConfiguredIntegrationService implements Disposable {
171168
await this.container.storage.store('integrations:configured', configured);
172169
}
173170

174-
private async addConfigured(descriptor: ConfiguredIntegrationDescriptor): Promise<void> {
171+
private async addOrUpdateConfigured(descriptor: ConfiguredIntegrationDescriptor): Promise<void> {
175172
const descriptors = this.configured.get(descriptor.integrationId) ?? [];
176173
const existing = descriptors.find(
177174
d =>
@@ -180,39 +177,57 @@ export class ConfiguredIntegrationService implements Disposable {
180177
d.cloud === descriptor.cloud,
181178
);
182179

180+
let changed = false;
183181
if (existing != null) {
184182
if (existing.expiresAt === descriptor.expiresAt && existing.scopes === descriptor.scopes) {
185183
return;
186184
}
187185

188-
//remove the existing descriptor from the array
189-
const index = descriptors.indexOf(existing);
190-
descriptors.splice(index, 1);
186+
// Only fire the change event if the scopes changes (i.e. ignore any expiresAt changes)
187+
changed = existing.scopes !== descriptor.scopes;
188+
189+
// remove the existing descriptor from the array
190+
descriptors.splice(descriptors.indexOf(existing), 1);
191+
} else {
192+
changed = true;
191193
}
192194

193195
descriptors.push(descriptor);
194196
this.configured.set(descriptor.integrationId, descriptors);
195-
this.queueDidChange(descriptor.integrationId);
197+
198+
if (changed) {
199+
this.fireChange(descriptor.integrationId);
200+
}
196201
await this.storeConfigured();
197202
}
198203

199-
private async removeConfigured(id: IntegrationIds, options?: { cloud?: boolean; domain?: string }): Promise<void> {
200-
const descriptors = this.configured
201-
.get(id)
202-
?.filter(d =>
203-
options?.cloud === true
204-
? !(d.cloud === true && d.domain === options?.domain)
205-
: options?.cloud === false
206-
? !(d.cloud === false && d.domain === options?.domain)
207-
: d.domain !== options?.domain,
208-
);
209-
210-
if (descriptors != null && descriptors.length === 0) {
211-
this.configured.delete(id);
204+
private async removeConfigured(
205+
id: IntegrationIds,
206+
options: { cloud: boolean | undefined; domain: string | undefined },
207+
): Promise<void> {
208+
let changed = false;
209+
const descriptors = [];
210+
211+
for (const d of this.configured.get(id) ?? []) {
212+
if (
213+
d.domain === options.domain &&
214+
(options?.cloud == null ||
215+
(options?.cloud === true && d.cloud === true) ||
216+
(options?.cloud === false && d.cloud === false))
217+
) {
218+
changed = true;
219+
continue;
220+
}
221+
222+
descriptors.push(d);
223+
}
224+
225+
this.configured.set(id, descriptors);
226+
227+
if (changed) {
228+
this.fireChange(undefined, id);
212229
}
213230

214-
this.configured.set(id, descriptors ?? []);
215-
this.queueDidChange(id);
216231
await this.storeConfigured();
217232
}
218233

@@ -300,7 +315,7 @@ export class ConfiguredIntegrationService implements Disposable {
300315
JSON.stringify(session),
301316
);
302317

303-
await this.addConfigured({
318+
await this.addOrUpdateConfigured({
304319
integrationId: id,
305320
domain: isSelfHostedIntegrationId(id) ? session.domain : undefined,
306321
expiresAt: session.expiresAt,
@@ -327,7 +342,7 @@ export class ConfiguredIntegrationService implements Disposable {
327342
configured.length === 0 ||
328343
!configured.some(c => c.domain === domain && c.integrationId === id)
329344
) {
330-
await this.addConfigured({
345+
await this.addOrUpdateConfigured({
331346
integrationId: id,
332347
domain: domain,
333348
expiresAt: storedSession.expiresAt,
@@ -373,16 +388,26 @@ export class ConfiguredIntegrationService implements Disposable {
373388
return descriptor.domain;
374389
}
375390

376-
private changedIds = new Set<IntegrationIds>();
377-
private debouncedFireDidChange?: () => void;
378-
private queueDidChange(id: IntegrationIds) {
379-
this.debouncedFireDidChange ??= debounce(() => {
380-
this._onDidChange.fire({ ids: [...this.changedIds] });
381-
this.changedIds.clear();
382-
}, 300);
383-
384-
this.changedIds.add(id);
385-
this.debouncedFireDidChange();
391+
private _addedIds = new Set<IntegrationIds>();
392+
private _removedIds = new Set<IntegrationIds>();
393+
private _fireChangeDebounced?: () => void;
394+
private fireChange(added?: IntegrationIds, removed?: IntegrationIds) {
395+
this._fireChangeDebounced ??= debounce(() => {
396+
const added = [...this._addedIds];
397+
this._addedIds.clear();
398+
const removed = [...this._removedIds];
399+
this._removedIds.clear();
400+
401+
this._onDidChange.fire({ added: added, removed: removed });
402+
}, 250);
403+
404+
if (added != null) {
405+
this._addedIds.add(added);
406+
}
407+
if (removed != null) {
408+
this._removedIds.add(removed);
409+
}
410+
this._fireChangeDebounced();
386411
}
387412
}
388413

src/plus/integrations/integrationService.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,15 @@ export interface IntegrationConnectionChangeEvent extends ConnectionStateChangeE
6666
}
6767

6868
export class IntegrationService implements Disposable {
69+
get onDidChange(): Event<ConfiguredIntegrationsChangeEvent> {
70+
return this.configuredIntegrationService.onDidChange;
71+
}
72+
6973
private readonly _onDidChangeConnectionState = new EventEmitter<ConnectionStateChangeEvent>();
7074
get onDidChangeConnectionState(): Event<ConnectionStateChangeEvent> {
7175
return this._onDidChangeConnectionState.event;
7276
}
7377

74-
private readonly _onDidSyncCloudIntegrations = new EventEmitter<void>();
75-
get onDidSyncCloudIntegrations(): Event<void> {
76-
return this._onDidSyncCloudIntegrations.event;
77-
}
78-
79-
get onDidChangeConfiguredIntegrations(): Event<ConfiguredIntegrationsChangeEvent> {
80-
return this.configuredIntegrationService.onDidChange;
81-
}
82-
8378
private readonly _connectedCache = new Set<string>();
8479
private readonly _disposable: Disposable;
8580
private _integrations = new Map<IntegrationKey, Integration>();
@@ -1047,7 +1042,6 @@ export class IntegrationService implements Disposable {
10471042
});
10481043
}
10491044

1050-
this._onDidSyncCloudIntegrations.fire();
10511045
return connectedIntegrations;
10521046
}
10531047
}

src/views/launchpadView.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,9 @@ export class LaunchpadView extends ViewBase<'launchpad', LaunchpadViewNode, Laun
243243
protected override onVisibilityChanged(e: TreeViewVisibilityChangeEvent): void {
244244
if (this._disposable == null) {
245245
this._disposable = Disposable.from(
246+
this.container.integrations.onDidChange(() => this.refresh(), this),
246247
this.container.integrations.onDidChangeConnectionState(() => this.refresh(), this),
247248
this.container.launchpad.onDidRefresh(() => this.refresh(), this),
248-
this.container.integrations.onDidSyncCloudIntegrations(() => this.refresh(), this),
249249
);
250250
}
251251

src/webviews/commitDetails/commitDetailsWebview.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ export class CommitDetailsWebviewProvider
214214
configuration.onDidChangeAny(this.onAnyConfigurationChanged, this),
215215
onDidChangeContext(this.onContextChanged, this),
216216
this.container.subscription.onDidChange(this.onSubscriptionChanged, this),
217-
container.integrations.onDidChangeConfiguredIntegrations(this.onIntegrationsChanged, this),
217+
container.integrations.onDidChange(this.onIntegrationsChanged, this),
218218
);
219219
}
220220

src/webviews/home/homeWebview.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ export class HomeWebviewProvider implements WebviewProvider<State, State, HomeWe
169169
: emptyDisposable,
170170
this.container.subscription.onDidChange(this.onSubscriptionChanged, this),
171171
onDidChangeContext(this.onContextChanged, this),
172-
this.container.integrations.onDidChangeConfiguredIntegrations(this.onIntegrationsChanged, this),
172+
this.container.integrations.onDidChange(this.onIntegrationsChanged, this),
173173
this.container.walkthrough.onDidChangeProgress(this.onWalkthroughProgressChanged, this),
174174
configuration.onDidChange(this.onDidChangeConfig, this),
175175
this.container.launchpad.onDidChange(this.onLaunchpadChanged, this),

0 commit comments

Comments
 (0)