diff --git a/packages/scm/src/browser/scm-frontend-module.ts b/packages/scm/src/browser/scm-frontend-module.ts index a0f5ebd31e2fd..51b9e67b62280 100644 --- a/packages/scm/src/browser/scm-frontend-module.ts +++ b/packages/scm/src/browser/scm-frontend-module.ts @@ -44,6 +44,7 @@ import { ScmTreeLabelProvider } from './scm-tree-label-provider'; import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; import { LabelProviderContribution } from '@theia/core/lib/browser/label-provider'; +import { bindScmPreferences } from './scm-preferences'; export default new ContainerModule(bind => { bind(ScmContextKeyService).toSelf().inSingletonScope(); @@ -115,6 +116,8 @@ export default new ContainerModule(bind => { bind(ScmTreeLabelProvider).toSelf().inSingletonScope(); bind(LabelProviderContribution).toService(ScmTreeLabelProvider); + + bindScmPreferences(bind); }); export function createFileChangeTreeContainer(parent: interfaces.Container): Container { diff --git a/packages/scm/src/browser/scm-preferences.ts b/packages/scm/src/browser/scm-preferences.ts new file mode 100644 index 0000000000000..14c46cad5b9e8 --- /dev/null +++ b/packages/scm/src/browser/scm-preferences.ts @@ -0,0 +1,61 @@ +/******************************************************************************** + * Copyright (C) 2020 Ericsson and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { interfaces } from 'inversify'; +import { + createPreferenceProxy, + PreferenceProxy, + PreferenceService, + PreferenceSchema, + PreferenceContribution +} from '@theia/core/lib/browser/preferences'; + +export const scmPreferenceSchema: PreferenceSchema = { + type: 'object', + properties: { + 'scm.defaultViewMode': { + type: 'string', + enum: ['tree', 'list'], + enumDescriptions: [ + 'Show the repository changes as a tree.', + 'Show the repository changes as a list.' + ], + description: 'Controls the default source control view mode.', + default: 'list' + } + } +}; + +export interface ScmConfiguration { + 'scm.defaultViewMode': 'tree' | 'list' +} + +export const ScmPreferences = Symbol('ScmPreferences'); +export type ScmPreferences = PreferenceProxy; + +export function createScmPreferences(preferences: PreferenceService): ScmPreferences { + return createPreferenceProxy(preferences, scmPreferenceSchema); +} + +export function bindScmPreferences(bind: interfaces.Bind): void { + bind(ScmPreferences).toDynamicValue((ctx: interfaces.Context) => { + const preferences = ctx.container.get(PreferenceService); + return createScmPreferences(preferences); + }).inSingletonScope(); + + bind(PreferenceContribution).toConstantValue({ schema: scmPreferenceSchema }); +} + diff --git a/packages/scm/src/browser/scm-widget.tsx b/packages/scm/src/browser/scm-widget.tsx index 282145d66e84b..507f14a666cfb 100644 --- a/packages/scm/src/browser/scm-widget.tsx +++ b/packages/scm/src/browser/scm-widget.tsx @@ -20,12 +20,14 @@ import { Message } from '@phosphor/messaging'; import { injectable, inject, postConstruct } from 'inversify'; import { DisposableCollection } from '@theia/core/lib/common/disposable'; import { - BaseWidget, Widget, StatefulWidget, Panel, PanelLayout, MessageLoop} from '@theia/core/lib/browser'; + BaseWidget, Widget, StatefulWidget, Panel, PanelLayout, MessageLoop, PreferenceChangeEvent +} from '@theia/core/lib/browser'; import { ScmCommitWidget } from './scm-commit-widget'; import { ScmAmendWidget } from './scm-amend-widget'; import { ScmNoRepositoryWidget } from './scm-no-repository-widget'; import { ScmService } from './scm-service'; import { ScmTreeWidget } from './scm-tree-widget'; +import { ScmPreferences, ScmConfiguration } from './scm-preferences'; @injectable() export class ScmWidget extends BaseWidget implements StatefulWidget { @@ -39,6 +41,7 @@ export class ScmWidget extends BaseWidget implements StatefulWidget { @inject(ScmTreeWidget) protected readonly resourceWidget: ScmTreeWidget; @inject(ScmAmendWidget) protected readonly amendWidget: ScmAmendWidget; @inject(ScmNoRepositoryWidget) protected readonly noRepositoryWidget: ScmNoRepositoryWidget; + @inject(ScmPreferences) protected readonly scmPreferences: ScmPreferences; set viewMode(mode: 'tree' | 'flat') { this.resourceWidget.viewMode = mode; @@ -60,7 +63,7 @@ export class ScmWidget extends BaseWidget implements StatefulWidget { const layout = new PanelLayout(); this.layout = layout; this.panel = new Panel({ - layout: new PanelLayout ({ + layout: new PanelLayout({ }) }); this.panel.node.tabIndex = -1; @@ -74,12 +77,27 @@ export class ScmWidget extends BaseWidget implements StatefulWidget { this.refresh(); this.toDispose.push(this.scmService.onDidChangeSelectedRepository(() => this.refresh())); + this.updateViewMode(this.scmPreferences.get('scm.defaultViewMode')); + this.toDispose.push(this.scmPreferences.onPreferenceChanged((e: PreferenceChangeEvent) => { + if (e.preferenceName === 'scm.defaultViewMode') { + this.updateViewMode(e.newValue!); + } + })); + } get containerLayout(): PanelLayout { return this.panel.layout as PanelLayout; } + /** + * Updates the view mode based on the preference value. + * @param preference the view mode preference. + */ + protected updateViewMode(preference: 'tree' | 'list'): void { + this.viewMode = preference === 'tree' ? 'tree' : 'flat'; + } + protected readonly toDisposeOnRefresh = new DisposableCollection(); protected refresh(): void { this.toDisposeOnRefresh.dispose();