2.3 KB76 lines
Blame
1/**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8import type {Logger} from 'isl-server/src/logger';
9import type {Disposable, Event} from 'vscode';
10import type {SaplingResourceGroup, VSCodeRepo} from './VSCodeRepo';
11
12import {
13 EventEmitter,
14 ThemeIcon,
15 Uri,
16 window,
17 type FileDecoration,
18 type FileDecorationProvider,
19} from 'vscode';
20
21export default class SaplingFileDecorationProvider implements FileDecorationProvider {
22 private readonly _onDidChangeDecorations = new EventEmitter<Uri[]>();
23 readonly onDidChangeFileDecorations: Event<Uri[]> = this._onDidChangeDecorations.event;
24
25 private disposables: Disposable[] = [];
26 private decorations = new Map<string, FileDecoration>();
27
28 constructor(
29 private repository: VSCodeRepo,
30 private logger: Logger,
31 ) {
32 this.disposables.push(
33 window?.registerFileDecorationProvider?.(this),
34 repository.repo.subscribeToUncommittedChanges(this.onDidRunStatus.bind(this)),
35 repository.repo.onChangeConflictState(this.onDidRunStatus.bind(this)),
36 );
37 this.onDidRunStatus();
38 }
39
40 private onDidRunStatus(): void {
41 const newDecorations = new Map<string, FileDecoration>();
42
43 const resourceGroups = this.repository.getResourceGroups() ?? {};
44 for (const key of Object.keys(resourceGroups) as (keyof typeof resourceGroups)[]) {
45 this.collectDecorationData(resourceGroups[key], newDecorations);
46 }
47
48 const uris = new Set([...this.decorations.keys()].concat([...newDecorations.keys()]));
49 this.decorations = newDecorations;
50 this._onDidChangeDecorations.fire([...uris.values()].map(value => Uri.parse(value, true)));
51 }
52
53 private collectDecorationData(
54 group: SaplingResourceGroup,
55 bucket: Map<string, FileDecoration>,
56 ): void {
57 for (const r of group.resourceStates) {
58 const decoration = r.decorations;
59 if (decoration) {
60 bucket.set(r.resourceUri.toString(), {
61 badge: r.status,
62 color: decoration.iconPath instanceof ThemeIcon ? decoration.iconPath.color : undefined,
63 });
64 }
65 }
66 }
67
68 provideFileDecoration(uri: Uri): FileDecoration | undefined {
69 return this.decorations.get(uri.toString());
70 }
71
72 dispose(): void {
73 this.disposables.forEach(d => d?.dispose());
74 }
75}
76