@@ -18,14 +18,15 @@ import { binarySearch } from '../../../../base/common/arrays.js';
1818import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js' ;
1919import { IContextKey , IContextKeyService , RawContextKey } from '../../../../platform/contextkey/common/contextkey.js' ;
2020import { IExtensionService } from '../../../services/extensions/common/extensions.js' ;
21- import { derivedObservableWithCache , derivedOpts , IObservable , ISettableObservable , latestChangedValue , observableFromEventOpts , observableValue } from '../../../../base/common/observable.js' ;
21+ import { autorun , derivedObservableWithCache , derivedOpts , IObservable , ISettableObservable , latestChangedValue , observableFromEventOpts , observableValue , runOnChange } from '../../../../base/common/observable.js' ;
2222import { IEditorService } from '../../../services/editor/common/editorService.js' ;
2323import { EditorResourceAccessor } from '../../../common/editor.js' ;
2424import { EditorInput } from '../../../common/editor/editorInput.js' ;
2525import { IQuickInputService , IQuickPickItem , IQuickPickSeparator } from '../../../../platform/quickinput/common/quickInput.js' ;
2626import { ThemeIcon } from '../../../../base/common/themables.js' ;
2727import { Codicon } from '../../../../base/common/codicons.js' ;
2828import { localize } from '../../../../nls.js' ;
29+ import { observableConfigValue } from '../../../../platform/observable/common/platformObservableUtils.js' ;
2930
3031function getProviderStorageKey ( provider : ISCMProvider ) : string {
3132 return `${ provider . providerId } :${ provider . label } ${ provider . rootUri ? `:${ provider . rootUri . toString ( ) } ` : '' } ` ;
@@ -42,6 +43,7 @@ function getRepositoryName(workspaceContextService: IWorkspaceContextService, re
4243
4344export const RepositoryContextKeys = {
4445 RepositorySortKey : new RawContextKey < ISCMRepositorySortKey > ( 'scmRepositorySortKey' , ISCMRepositorySortKey . DiscoveryTime ) ,
46+ RepositoryPinned : new RawContextKey < boolean > ( 'scmRepositoryPinned' , false )
4547} ;
4648
4749export type RepositoryQuickPickItem = IQuickPickItem & { repository : 'auto' | ISCMRepository } ;
@@ -204,16 +206,20 @@ export class SCMViewService implements ISCMViewService {
204206 private readonly _activeEditorRepositoryObs : IObservable < ISCMRepository | undefined > ;
205207
206208 /**
207- * The focused repository takes precedence over the active editor repository when the observable
208- * values are updated in the same transaction (or during the initial read of the observable value).
209+ * The focused repository takes precedence over the active editor repository when the observable
210+ * values are updated in the same transaction (or during the initial read of the observable value).
209211 */
210212 private readonly _activeRepositoryObs : IObservable < ISCMRepository | undefined > ;
211213 private readonly _activeRepositoryPinnedObs : ISettableObservable < ISCMRepository | undefined > ;
212214 private readonly _focusedRepositoryObs : IObservable < ISCMRepository | undefined > ;
213215
216+ private readonly _selectionModeConfig : IObservable < 'multiple' | 'single' > ;
217+
214218 private _repositoriesSortKey : ISCMRepositorySortKey ;
215219 private _sortKeyContextKey : IContextKey < ISCMRepositorySortKey > ;
216220
221+ private _repositoryPinnedContextKey : IContextKey < boolean > ;
222+
217223 constructor (
218224 @ISCMService private readonly scmService : ISCMService ,
219225 @IContextKeyService contextKeyService : IContextKeyService ,
@@ -226,6 +232,8 @@ export class SCMViewService implements ISCMViewService {
226232 ) {
227233 this . menus = instantiationService . createInstance ( SCMMenus ) ;
228234
235+ this . _selectionModeConfig = observableConfigValue < 'multiple' | 'single' > ( 'scm.repositories.selectionMode' , 'multiple' , this . configurationService ) ;
236+
229237 this . _focusedRepositoryObs = observableFromEventOpts < ISCMRepository | undefined > (
230238 {
231239 owner : this ,
@@ -253,7 +261,7 @@ export class SCMViewService implements ISCMViewService {
253261 return lastValue ;
254262 }
255263
256- return Object . create ( repository ) ;
264+ return repository ;
257265 } ) ;
258266
259267 this . _activeRepositoryPinnedObs = observableValue < ISCMRepository | undefined > ( this , undefined ) ;
@@ -269,8 +277,33 @@ export class SCMViewService implements ISCMViewService {
269277 return activeRepositoryPinned ?? activeRepository ;
270278 } ) ;
271279
280+ this . disposables . add ( autorun ( reader => {
281+ const selectionMode = this . _selectionModeConfig . read ( undefined ) ;
282+ const activeRepository = this . activeRepository . read ( reader ) ;
283+
284+ if ( selectionMode === 'single' && activeRepository ) {
285+ this . visibleRepositories = [ activeRepository ] ;
286+ }
287+ } ) ) ;
288+
289+ this . disposables . add ( runOnChange ( this . _selectionModeConfig , selectionMode => {
290+ if ( selectionMode === 'single' && this . visibleRepositories . length > 1 ) {
291+ const repository = this . visibleRepositories [ 0 ] ;
292+ this . visibleRepositories = [ repository ] ;
293+ }
294+ } ) ) ;
295+
272296 try {
273297 this . previousState = JSON . parse ( storageService . get ( 'scm:view:visibleRepositories' , StorageScope . WORKSPACE , '' ) ) ;
298+
299+ // If previously there were multiple visible repositories but the
300+ // view mode is `single`, only restore the first visible repository.
301+ if ( this . previousState && this . previousState . visible . length > 1 && this . _selectionModeConfig . get ( ) === 'single' ) {
302+ this . previousState = {
303+ ...this . previousState ,
304+ visible : [ this . previousState . visible [ 0 ] ]
305+ } ;
306+ }
274307 } catch {
275308 // noop
276309 }
@@ -279,6 +312,9 @@ export class SCMViewService implements ISCMViewService {
279312 this . _sortKeyContextKey = RepositoryContextKeys . RepositorySortKey . bindTo ( contextKeyService ) ;
280313 this . _sortKeyContextKey . set ( this . _repositoriesSortKey ) ;
281314
315+ this . _repositoryPinnedContextKey = RepositoryContextKeys . RepositoryPinned . bindTo ( contextKeyService ) ;
316+ this . _repositoryPinnedContextKey . set ( ! ! this . _activeRepositoryPinnedObs . get ( ) ) ;
317+
282318 scmService . onDidAddRepository ( this . onDidAddRepository , this , this . disposables ) ;
283319 scmService . onDidRemoveRepository ( this . onDidRemoveRepository , this , this . disposables ) ;
284320
@@ -314,19 +350,24 @@ export class SCMViewService implements ISCMViewService {
314350 if ( index === - 1 ) {
315351 // This repository is not part of the previous state which means that it
316352 // was either manually closed in the previous session, or the repository
317- // was added after the previous session.In this case, we should select all
318- // of the repositories.
353+ // was added after the previous session. In this case, we should select
354+ // all of the repositories.
319355 const added : ISCMRepository [ ] = [ ] ;
320356
321357 this . insertRepositoryView ( this . _repositories , repositoryView ) ;
322- this . _repositories . forEach ( ( repositoryView , index ) => {
323- if ( repositoryView . selectionIndex === - 1 ) {
324- added . push ( repositoryView . repository ) ;
325- }
326- repositoryView . selectionIndex = index ;
327- } ) ;
328358
329- this . _onDidChangeRepositories . fire ( { added, removed : Iterable . empty ( ) } ) ;
359+ if ( this . _selectionModeConfig . get ( ) === 'multiple' || ! this . _repositories . find ( r => r . selectionIndex !== - 1 ) ) {
360+ // Multiple selection mode or single selection mode (select first repository)
361+ this . _repositories . forEach ( ( repositoryView , index ) => {
362+ if ( repositoryView . selectionIndex === - 1 ) {
363+ added . push ( repositoryView . repository ) ;
364+ }
365+ repositoryView . selectionIndex = index ;
366+ } ) ;
367+
368+ this . _onDidChangeRepositories . fire ( { added, removed : Iterable . empty ( ) } ) ;
369+ }
370+
330371 this . didSelectRepository = false ;
331372 return ;
332373 }
@@ -352,10 +393,18 @@ export class SCMViewService implements ISCMViewService {
352393 }
353394 }
354395
355- const maxSelectionIndex = this . getMaxSelectionIndex ( ) ;
356- this . insertRepositoryView ( this . _repositories , { ...repositoryView , selectionIndex : maxSelectionIndex + 1 } ) ;
357- this . _onDidChangeRepositories . fire ( { added : [ repositoryView . repository ] , removed } ) ;
396+ if ( this . _selectionModeConfig . get ( ) === 'multiple' || ! this . _repositories . find ( r => r . selectionIndex !== - 1 ) ) {
397+ // Multiple selection mode or single selection mode (select first repository)
398+ const maxSelectionIndex = this . getMaxSelectionIndex ( ) ;
399+ this . insertRepositoryView ( this . _repositories , { ...repositoryView , selectionIndex : maxSelectionIndex + 1 } ) ;
400+ this . _onDidChangeRepositories . fire ( { added : [ repositoryView . repository ] , removed } ) ;
401+ } else {
402+ // Single selection mode (add subsequent repository)
403+ this . insertRepositoryView ( this . _repositories , repositoryView ) ;
404+ this . _onDidChangeRepositories . fire ( { added : Iterable . empty ( ) , removed } ) ;
405+ }
358406
407+ // Focus repository if nothing is focused
359408 if ( ! this . _repositories . find ( r => r . focused ) ) {
360409 this . focus ( repository ) ;
361410 }
@@ -410,7 +459,11 @@ export class SCMViewService implements ISCMViewService {
410459 }
411460
412461 if ( visible ) {
413- this . visibleRepositories = [ ...this . visibleRepositories , repository ] ;
462+ if ( this . _selectionModeConfig . get ( ) === 'single' ) {
463+ this . visibleRepositories = [ repository ] ;
464+ } else if ( this . _selectionModeConfig . get ( ) === 'multiple' ) {
465+ this . visibleRepositories = [ ...this . visibleRepositories , repository ] ;
466+ }
414467 } else {
415468 const index = this . visibleRepositories . indexOf ( repository ) ;
416469
@@ -445,6 +498,7 @@ export class SCMViewService implements ISCMViewService {
445498
446499 pinActiveRepository ( repository : ISCMRepository | undefined ) : void {
447500 this . _activeRepositoryPinnedObs . set ( repository , undefined ) ;
501+ this . _repositoryPinnedContextKey . set ( ! ! repository ) ;
448502 }
449503
450504 private compareRepositories ( op1 : ISCMRepositoryView , op2 : ISCMRepositoryView ) : number {
0 commit comments