addons/vscode/extension/SaplingFileDecorationProvider.tsblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import type {Logger} from 'isl-server/src/logger';
b69ab319import type {Disposable, Event} from 'vscode';
b69ab3110import type {SaplingResourceGroup, VSCodeRepo} from './VSCodeRepo';
b69ab3111
b69ab3112import {
b69ab3113 EventEmitter,
b69ab3114 ThemeIcon,
b69ab3115 Uri,
b69ab3116 window,
b69ab3117 type FileDecoration,
b69ab3118 type FileDecorationProvider,
b69ab3119} from 'vscode';
b69ab3120
b69ab3121export default class SaplingFileDecorationProvider implements FileDecorationProvider {
b69ab3122 private readonly _onDidChangeDecorations = new EventEmitter<Uri[]>();
b69ab3123 readonly onDidChangeFileDecorations: Event<Uri[]> = this._onDidChangeDecorations.event;
b69ab3124
b69ab3125 private disposables: Disposable[] = [];
b69ab3126 private decorations = new Map<string, FileDecoration>();
b69ab3127
b69ab3128 constructor(
b69ab3129 private repository: VSCodeRepo,
b69ab3130 private logger: Logger,
b69ab3131 ) {
b69ab3132 this.disposables.push(
b69ab3133 window?.registerFileDecorationProvider?.(this),
b69ab3134 repository.repo.subscribeToUncommittedChanges(this.onDidRunStatus.bind(this)),
b69ab3135 repository.repo.onChangeConflictState(this.onDidRunStatus.bind(this)),
b69ab3136 );
b69ab3137 this.onDidRunStatus();
b69ab3138 }
b69ab3139
b69ab3140 private onDidRunStatus(): void {
b69ab3141 const newDecorations = new Map<string, FileDecoration>();
b69ab3142
b69ab3143 const resourceGroups = this.repository.getResourceGroups() ?? {};
b69ab3144 for (const key of Object.keys(resourceGroups) as (keyof typeof resourceGroups)[]) {
b69ab3145 this.collectDecorationData(resourceGroups[key], newDecorations);
b69ab3146 }
b69ab3147
b69ab3148 const uris = new Set([...this.decorations.keys()].concat([...newDecorations.keys()]));
b69ab3149 this.decorations = newDecorations;
b69ab3150 this._onDidChangeDecorations.fire([...uris.values()].map(value => Uri.parse(value, true)));
b69ab3151 }
b69ab3152
b69ab3153 private collectDecorationData(
b69ab3154 group: SaplingResourceGroup,
b69ab3155 bucket: Map<string, FileDecoration>,
b69ab3156 ): void {
b69ab3157 for (const r of group.resourceStates) {
b69ab3158 const decoration = r.decorations;
b69ab3159 if (decoration) {
b69ab3160 bucket.set(r.resourceUri.toString(), {
b69ab3161 badge: r.status,
b69ab3162 color: decoration.iconPath instanceof ThemeIcon ? decoration.iconPath.color : undefined,
b69ab3163 });
b69ab3164 }
b69ab3165 }
b69ab3166 }
b69ab3167
b69ab3168 provideFileDecoration(uri: Uri): FileDecoration | undefined {
b69ab3169 return this.decorations.get(uri.toString());
b69ab3170 }
b69ab3171
b69ab3172 dispose(): void {
b69ab3173 this.disposables.forEach(d => d?.dispose());
b69ab3174 }
b69ab3175}