/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; import { ISCMService, ISCMProvider, ISCMInput, ISCMRepository, IInputValidator } from './scm'; import { ILogService } from 'vs/platform/log/common/log'; class SCMInput implements ISCMInput { private _value = ''; get value(): string { return this._value; } set value(value: string) { if (value === this._value) { return; } this._value = value; this._onDidChange.fire(value); } private readonly _onDidChange = new Emitter(); readonly onDidChange: Event = this._onDidChange.event; private _placeholder = ''; get placeholder(): string { return this._placeholder; } set placeholder(placeholder: string) { this._placeholder = placeholder; this._onDidChangePlaceholder.fire(placeholder); } private readonly _onDidChangePlaceholder = new Emitter(); readonly onDidChangePlaceholder: Event = this._onDidChangePlaceholder.event; private _visible = true; get visible(): boolean { return this._visible; } set visible(visible: boolean) { this._visible = visible; this._onDidChangeVisibility.fire(visible); } private readonly _onDidChangeVisibility = new Emitter(); readonly onDidChangeVisibility: Event = this._onDidChangeVisibility.event; private _validateInput: IInputValidator = () => Promise.resolve(undefined); get validateInput(): IInputValidator { return this._validateInput; } set validateInput(validateInput: IInputValidator) { this._validateInput = validateInput; this._onDidChangeValidateInput.fire(); } private readonly _onDidChangeValidateInput = new Emitter(); readonly onDidChangeValidateInput: Event = this._onDidChangeValidateInput.event; constructor(readonly repository: ISCMRepository) { } } class SCMRepository implements ISCMRepository { private _selected = false; get selected(): boolean { return this._selected; } private readonly _onDidChangeSelection = new Emitter(); readonly onDidChangeSelection: Event = this._onDidChangeSelection.event; readonly input: ISCMInput = new SCMInput(this); constructor( public readonly provider: ISCMProvider, private disposable: IDisposable ) { } setSelected(selected: boolean): void { if (this._selected === selected) { return; } this._selected = selected; this._onDidChangeSelection.fire(selected); } dispose(): void { this.disposable.dispose(); this.provider.dispose(); } } export class SCMService implements ISCMService { declare readonly _serviceBrand: undefined; private _providerIds = new Set(); private _repositories: ISCMRepository[] = []; get repositories(): ISCMRepository[] { return [...this._repositories]; } private _selectedRepository: ISCMRepository | undefined; private readonly _onDidSelectRepository = new Emitter(); readonly onDidSelectRepository: Event = this._onDidSelectRepository.event; private readonly _onDidAddProvider = new Emitter(); readonly onDidAddRepository: Event = this._onDidAddProvider.event; private readonly _onDidRemoveProvider = new Emitter(); readonly onDidRemoveRepository: Event = this._onDidRemoveProvider.event; constructor(@ILogService private readonly logService: ILogService) { } registerSCMProvider(provider: ISCMProvider): ISCMRepository { this.logService.trace('SCMService#registerSCMProvider'); if (this._providerIds.has(provider.id)) { throw new Error(`SCM Provider ${provider.id} already exists.`); } this._providerIds.add(provider.id); const disposable = toDisposable(() => { const index = this._repositories.indexOf(repository); if (index < 0) { return; } selectedDisposable.dispose(); this._providerIds.delete(provider.id); this._repositories.splice(index, 1); this._onDidRemoveProvider.fire(repository); if (this._selectedRepository === repository) { this.select(this._repositories[0]); } }); const repository = new SCMRepository(provider, disposable); const selectedDisposable = Event.map(Event.filter(repository.onDidChangeSelection, selected => selected), _ => repository)(this.select, this); this._repositories.push(repository); this._onDidAddProvider.fire(repository); if (!this._selectedRepository) { repository.setSelected(true); } return repository; } private select(repository: ISCMRepository | undefined): void { if (this._selectedRepository) { this._selectedRepository.setSelected(false); } this._selectedRepository = repository; this._onDidSelectRepository.fire(this._selectedRepository); } }