UNPKG

4.08 kBPlain TextView Raw
1// *****************************************************************************
2// Copyright (C) 2019 TypeFox and others.
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License v. 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0.
7//
8// This Source Code may also be made available under the following Secondary
9// Licenses when the conditions for such availability set forth in the Eclipse
10// Public License v. 2.0 are satisfied: GNU General Public License, version 2
11// with the GNU Classpath Exception which is available at
12// https://www.gnu.org/software/classpath/license.html.
13//
14// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15// *****************************************************************************
16
17import { injectable } from 'inversify';
18import { CancellationToken } from '../common/cancellation';
19import { ProgressClient } from '../common/progress-service-protocol';
20import { ProgressMessage, ProgressUpdate } from '../common/message-service-protocol';
21import { Deferred } from '../common/promise-util';
22import { Event, Emitter } from '../common/event';
23
24export interface LocationProgress {
25 show: boolean;
26}
27
28@injectable()
29export class ProgressLocationService implements ProgressClient {
30
31 protected emitters = new Map<string, Emitter<LocationProgress>[]>();
32 protected lastEvents = new Map<string, LocationProgress>();
33
34 getProgress(locationId: string): LocationProgress | undefined {
35 return this.lastEvents.get(locationId);
36 }
37 onProgress(locationId: string): Event<LocationProgress> {
38 const emitter = this.addEmitter(locationId);
39 return emitter.event;
40 }
41 protected addEmitter(locationId: string): Emitter<LocationProgress> {
42 const emitter = new Emitter<LocationProgress>();
43 const list = this.emitters.get(locationId) || [];
44 list.push(emitter);
45 this.emitters.set(locationId, list);
46 return emitter;
47 }
48
49 protected readonly progressByLocation = new Map<string, Set<string>>();
50
51 async showProgress(progressId: string, message: ProgressMessage, cancellationToken: CancellationToken): Promise<string | undefined> {
52 const locationId = this.getLocationId(message);
53 const result = new Deferred<string | undefined>();
54 cancellationToken.onCancellationRequested(() => {
55 this.processEvent(progressId, locationId, 'done');
56 result.resolve(ProgressMessage.Cancel);
57 });
58 this.processEvent(progressId, locationId, 'start');
59 return result.promise;
60 }
61 protected processEvent(progressId: string, locationId: string, event: 'start' | 'done'): void {
62 const progressSet = this.progressByLocation.get(locationId) || new Set<string>();
63 if (event === 'start') {
64 progressSet.add(progressId);
65 } else {
66 progressSet.delete(progressId);
67 }
68 this.progressByLocation.set(locationId, progressSet);
69 const show = !!progressSet.size;
70 this.fireEvent(locationId, show);
71 }
72 protected fireEvent(locationId: string, show: boolean): void {
73 const lastEvent = this.lastEvents.get(locationId);
74 const shouldFire = !lastEvent || lastEvent.show !== show;
75 if (shouldFire) {
76 this.lastEvents.set(locationId, { show });
77 this.getOrCreateEmitters(locationId).forEach(e => e.fire({ show }));
78 }
79 }
80 protected getOrCreateEmitters(locationId: string): Emitter<LocationProgress>[] {
81 let emitters = this.emitters.get(locationId);
82 if (!emitters) {
83 emitters = [this.addEmitter(locationId)];
84 }
85 return emitters;
86 }
87
88 protected getLocationId(message: ProgressMessage): string {
89 return message.options && message.options.location || 'unknownLocation';
90 }
91
92 async reportProgress(progressId: string, update: ProgressUpdate, message: ProgressMessage, cancellationToken: CancellationToken): Promise<void> {
93 /* NOOP */
94 }
95
96}