Merge from vscode cfbd1999769f4f08dce29629fb92fdc0fac53829

This commit is contained in:
ADS Merger
2020-08-06 07:08:52 +00:00
parent 9c67832880
commit 540046ba00
362 changed files with 7588 additions and 6584 deletions

View File

@@ -42,6 +42,7 @@ export class SCMStatusController implements IWorkbenchContribution {
) {
this.focusedProviderContextKey = contextKeyService.createKey<string | undefined>('scmProvider', undefined);
this.scmService.onDidAddRepository(this.onDidAddRepository, this, this.disposables);
this.scmService.onDidRemoveRepository(this.onDidRemoveRepository, this, this.disposables);
const onDidChangeSCMCountBadge = Event.filter(configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.countBadge'));
onDidChangeSCMCountBadge(this.renderActivityCount, this, this.disposables);
@@ -123,14 +124,22 @@ export class SCMStatusController implements IWorkbenchContribution {
this.focusRepository(repository);
}
private onDidRemoveRepository(repository: ISCMRepository): void {
if (this.focusedRepository !== repository) {
return;
}
this.focusRepository(this.scmService.repositories[0]);
}
private focusRepository(repository: ISCMRepository | undefined): void {
if (this.focusedRepository === repository) {
return;
}
this.focusDisposable.dispose();
this.focusedRepository = repository;
this.focusedProviderContextKey.set(repository && repository.provider.id);
this.focusDisposable.dispose();
if (repository && repository.provider.onDidChangeStatusBarCommands) {
this.focusDisposable = repository.provider.onDidChangeStatusBarCommands(() => this.renderStatusBar(repository));

View File

@@ -74,14 +74,10 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
win: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G },
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G },
mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KEY_G },
handler: accessor => {
handler: async accessor => {
const viewsService = accessor.get(IViewsService);
if (viewsService.isViewVisible(VIEW_PANE_ID)) {
viewsService.closeView(VIEW_PANE_ID);
} else {
viewsService.openView(VIEW_PANE_ID);
}
const view = await viewsService.openView(VIEW_PANE_ID);
view?.focus();
}
});
@@ -167,6 +163,11 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
type: 'string',
markdownDescription: localize('inputFontFamily', "Controls the font for the input message. Use `default` for the workbench user interface font family, `editor` for the `#editor.fontFamily#`'s value, or a custom font family."),
default: 'default'
},
'scm.alwaysShowRepositories': {
type: 'boolean',
markdownDescription: localize('alwaysShowRepository', "Controls whether repositories should always be visible in the SCM view."),
default: false
}
}
});

View File

@@ -27,7 +27,7 @@ import { IThemeService, LIGHT, registerThemingParticipant, IFileIconTheme } from
import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, connectPrimaryMenu } from './util';
import { attachBadgeStyler } from 'vs/platform/theme/common/styler';
import { WorkbenchCompressibleObjectTree, IOpenEvent } from 'vs/platform/list/browser/listService';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IConfigurationService, ConfigurationTarget, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
import { disposableTimeout, ThrottledDelayer } from 'vs/base/common/async';
import { ITreeNode, ITreeFilter, ITreeSorter, ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/tree';
import { ResourceTree, IResourceNode } from 'vs/base/common/resourceTree';
@@ -76,8 +76,6 @@ import { Command } from 'vs/editor/common/modes';
import { renderCodicons, Codicon } from 'vs/base/common/codicons';
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { domEvent } from 'vs/base/browser/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
type TreeElement = ISCMRepository | ISCMInput | ISCMResourceGroup | IResourceNode<ISCMResource, ISCMResourceGroup> | ISCMResource;
@@ -273,7 +271,6 @@ class InputRenderer implements ICompressibleTreeRenderer<ISCMInput, FuzzyScore,
constructor(
private outerLayout: ISCMLayout,
private updateHeight: (input: ISCMInput, height: number) => void,
private focusTree: () => void,
@IInstantiationService private instantiationService: IInstantiationService,
) { }
@@ -286,10 +283,6 @@ class InputRenderer implements ICompressibleTreeRenderer<ISCMInput, FuzzyScore,
const inputWidget = this.instantiationService.createInstance(SCMInputWidget, inputElement);
disposables.add(inputWidget);
const onKeyDown = Event.map(domEvent(container, 'keydown'), e => new StandardKeyboardEvent(e));
const onEscape = Event.filter(onKeyDown, e => e.keyCode === KeyCode.Escape);
disposables.add(onEscape(this.focusTree));
return { inputWidget, disposable: Disposable.None, templateDisposable: disposables };
}
@@ -299,7 +292,6 @@ class InputRenderer implements ICompressibleTreeRenderer<ISCMInput, FuzzyScore,
const disposables = new DisposableStore();
const input = node.element;
templateData.inputWidget.input = input;
disposables.add({ dispose: () => templateData.inputWidget.input = undefined });
// Remember widget
this.inputWidgets.set(input, templateData.inputWidget);
@@ -354,6 +346,22 @@ class InputRenderer implements ICompressibleTreeRenderer<ISCMInput, FuzzyScore,
getRenderedInputWidget(input: ISCMInput): SCMInputWidget | undefined {
return this.inputWidgets.get(input);
}
getFocusedInput(): ISCMInput | undefined {
for (const [input, inputWidget] of this.inputWidgets) {
if (inputWidget.hasFocus()) {
return input;
}
}
return undefined;
}
clearValidation(): void {
for (const [, inputWidget] of this.inputWidgets) {
inputWidget.clearValidation();
}
}
}
interface ResourceGroupTemplate {
@@ -486,22 +494,12 @@ class ResourceRenderer implements ICompressibleTreeRenderer<ISCMResource | IReso
const elementDisposables = new DisposableStore();
const resourceOrFolder = node.element;
const theme = this.themeService.getColorTheme();
const iconResource = ResourceTree.isResourceNode(resourceOrFolder) ? resourceOrFolder.element : resourceOrFolder;
const icon = iconResource && (theme.type === LIGHT ? iconResource.decorations.icon : iconResource.decorations.iconDark);
const uri = ResourceTree.isResourceNode(resourceOrFolder) ? resourceOrFolder.uri : resourceOrFolder.sourceUri;
const fileKind = ResourceTree.isResourceNode(resourceOrFolder) ? FileKind.FOLDER : FileKind.FILE;
const viewModel = this.viewModelProvider();
const [matches, descriptionMatches] = splitMatches(uri, node.filterData);
template.fileLabel.setFile(uri, {
fileDecorations: { colors: false, badges: !icon },
hidePath: viewModel.mode === ViewModelMode.Tree,
fileKind,
matches,
descriptionMatches
});
const tooltip = !ResourceTree.isResourceNode(resourceOrFolder) && resourceOrFolder.decorations.tooltip || '';
template.actionBar.clear();
template.actionBar.context = resourceOrFolder;
@@ -525,17 +523,31 @@ class ResourceRenderer implements ICompressibleTreeRenderer<ISCMResource | IReso
toggleClass(template.element, 'faded', resourceOrFolder.decorations.faded);
}
const tooltip = !ResourceTree.isResourceNode(resourceOrFolder) && resourceOrFolder.decorations.tooltip || '';
const render = () => {
const theme = this.themeService.getColorTheme();
const icon = iconResource && (theme.type === LIGHT ? iconResource.decorations.icon : iconResource.decorations.iconDark);
if (icon) {
template.decorationIcon.style.display = '';
template.decorationIcon.style.backgroundImage = `url('${icon}')`;
template.decorationIcon.title = tooltip;
} else {
template.decorationIcon.style.display = 'none';
template.decorationIcon.style.backgroundImage = '';
template.decorationIcon.title = '';
}
template.fileLabel.setFile(uri, {
fileDecorations: { colors: false, badges: !icon },
hidePath: viewModel.mode === ViewModelMode.Tree,
fileKind,
matches,
descriptionMatches
});
if (icon) {
template.decorationIcon.style.display = '';
template.decorationIcon.style.backgroundImage = `url('${icon}')`;
template.decorationIcon.title = tooltip;
} else {
template.decorationIcon.style.display = 'none';
template.decorationIcon.style.backgroundImage = '';
template.decorationIcon.title = '';
}
};
elementDisposables.add(this.themeService.onDidColorThemeChange(render));
render();
template.element.setAttribute('data-tooltip', tooltip);
template.elementDisposables = elementDisposables;
@@ -863,6 +875,7 @@ class ViewModel {
private items: IRepositoryItem[] = [];
private visibilityDisposables = new DisposableStore();
private scrollTop: number | undefined;
private alwaysShowRepositories = false;
private firstVisible = true;
private repositoryCollapseStates: Map<ISCMRepository, boolean> | undefined;
private disposables = new DisposableStore();
@@ -881,6 +894,16 @@ class ViewModel {
this._onDidChangeRepositoryCollapseState.event,
Event.signal(Event.filter(this.tree.onDidChangeCollapseState, e => isSCMRepository(e.node.element)))
);
configurationService.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.disposables);
this.onDidChangeConfiguration();
}
private onDidChangeConfiguration(e?: IConfigurationChangeEvent): void {
if (!e || e.affectsConfiguration('scm.alwaysShowRepositories')) {
this.alwaysShowRepositories = this.configurationService.getValue<boolean>('scm.alwaysShowRepositories');
this.refresh();
}
}
private _onDidSpliceRepositories({ start, deleteCount, toInsert }: ISplice<ISCMRepository>): void {
@@ -993,7 +1016,9 @@ class ViewModel {
}
private refresh(item?: IRepositoryItem | IGroupItem): void {
if (this.items.length === 1 && (!item || isRepositoryItem(item))) {
const focusedInput = this.inputRenderer.getFocusedInput();
if (!this.alwaysShowRepositories && (this.items.length === 1 && (!item || isRepositoryItem(item)))) {
this.tree.setChildren(null, this.render(this.items[0]).children);
} else if (item) {
this.tree.setChildren(item.element, this.render(item).children);
@@ -1001,6 +1026,14 @@ class ViewModel {
this.tree.setChildren(null, this.items.map(item => this.render(item)));
}
if (focusedInput) {
const inputWidget = this.inputRenderer.getRenderedInputWidget(focusedInput);
if (inputWidget) {
inputWidget.focus();
}
}
this._onDidChangeRepositoryCollapseState.fire();
}
@@ -1084,7 +1117,11 @@ class ViewModel {
}
getViewActions(): IAction[] {
if (this.repositories.elements.length !== 1) {
if (this.repositories.elements.length === 0) {
return [];
}
if (this.alwaysShowRepositories || this.repositories.elements.length !== 1) {
return [];
}
@@ -1099,7 +1136,7 @@ class ViewModel {
const viewAction = new SCMViewSubMenuAction(this);
if (this.repositories.elements.length !== 1) {
if (this.alwaysShowRepositories || this.repositories.elements.length !== 1) {
return Array.isArray(viewAction.actions) ? viewAction.actions : viewAction.actions();
}
@@ -1114,7 +1151,11 @@ class ViewModel {
}
getViewActionsContext(): any {
if (this.repositories.elements.length !== 1) {
if (this.repositories.elements.length === 0) {
return [];
}
if (this.alwaysShowRepositories || this.repositories.elements.length !== 1) {
return undefined;
}
@@ -1186,36 +1227,41 @@ class SCMViewSubMenuAction extends SubmenuAction {
}
}
abstract class SCMViewModeAction extends Action {
constructor(id: string, label: string, private viewModel: ViewModel, private viewMode: ViewModelMode) {
super(id, label);
export class ToggleViewModeAction extends Action {
this.checked = this.viewModel.mode === this.viewMode;
static readonly ID = 'workbench.scm.action.toggleViewMode';
static readonly LABEL = localize('toggleViewMode', "Toggle View Mode");
constructor(id: string = ToggleViewModeAction.ID, label: string = ToggleViewModeAction.LABEL, private viewModel: ViewModel, private mode?: ViewModelMode) {
super(id, label);
this._register(this.viewModel.onDidChangeMode(this.onDidChangeMode, this));
this.onDidChangeMode(this.viewModel.mode);
}
async run(): Promise<void> {
if (this.viewMode !== this.viewModel.mode) {
this.checked = !this.checked;
this.viewModel.mode = this.viewMode;
if (typeof this.mode === 'undefined') {
this.viewModel.mode = this.viewModel.mode === ViewModelMode.List ? ViewModelMode.Tree : ViewModelMode.List;
} else {
this.viewModel.mode = this.mode;
}
}
}
class SCMViewModeListAction extends SCMViewModeAction {
static readonly ID = 'workbench.scm.action.viewModeList';
static readonly LABEL = localize('viewModeList', "View as List");
constructor(viewModel: ViewModel) {
super(SCMViewModeListAction.ID, SCMViewModeListAction.LABEL, viewModel, ViewModelMode.List);
private onDidChangeMode(mode: ViewModelMode): void {
const iconClass = mode === ViewModelMode.List ? 'codicon-list-tree' : 'codicon-list-flat';
this.class = `scm-action toggle-view-mode ${iconClass}`;
this.checked = this.viewModel.mode === this.mode;
}
}
class SCMViewModeTreeAction extends SCMViewModeAction {
static readonly ID = 'workbench.scm.action.viewModeTree';
static readonly LABEL = localize('viewModeTree', "View as Tree");
class SCMViewModeListAction extends ToggleViewModeAction {
constructor(viewModel: ViewModel) {
super(SCMViewModeTreeAction.ID, SCMViewModeTreeAction.LABEL, viewModel, ViewModelMode.Tree);
super('workbench.scm.action.viewModeList', localize('viewModeList', "View as List"), viewModel, ViewModelMode.List);
}
}
class SCMViewModeTreeAction extends ToggleViewModeAction {
constructor(viewModel: ViewModel) {
super('workbench.scm.action.viewModeTree', localize('viewModeTree', "View as Tree"), viewModel, ViewModelMode.Tree);
}
}
@@ -1294,6 +1340,10 @@ class SCMInputWidget extends Disposable {
}
set input(input: ISCMInput | undefined) {
if (input === this.input) {
return;
}
this.validationDisposable.dispose();
removeClass(this.editorContainer, 'synthetic-focus');
@@ -1433,7 +1483,8 @@ class SCMInputWidget extends Disposable {
wrappingStrategy: 'advanced',
wrappingIndent: 'none',
padding: { top: 3, bottom: 3 },
quickSuggestions: false
quickSuggestions: false,
scrollbar: { alwaysConsumeMouseWheel: false }
};
const codeEditorWidgetOptions: ICodeEditorWidgetOptions = {
@@ -1492,6 +1543,10 @@ class SCMInputWidget extends Disposable {
addClass(this.editorContainer, 'synthetic-focus');
}
hasFocus(): boolean {
return this.inputEditor.hasWidgetFocus();
}
private renderValidation(): void {
this.validationDisposable.dispose();
@@ -1532,7 +1587,12 @@ class SCMInputWidget extends Disposable {
return this.defaultInputFontFamily;
}
clearValidation(): void {
this.validationDisposable.dispose();
}
dispose(): void {
this.input = undefined;
this.repositoryDisposables.dispose();
this.validationDisposable.dispose();
super.dispose();
@@ -1582,6 +1642,7 @@ export class SCMViewPane extends ViewPane {
private listLabels!: ResourceLabels;
private menus!: SCMMenus;
private inputRenderer!: InputRenderer;
private toggleViewModelModeAction: ToggleViewModeAction | undefined;
constructor(
options: IViewPaneOptions,
@@ -1612,7 +1673,7 @@ export class SCMViewPane extends ViewPane {
this.listContainer = append(container, $('.scm-view.show-file-icons'));
const updateActionsVisibility = () => toggleClass(this.listContainer, 'show-actions', this.configurationService.getValue<boolean>('scm.alwaysShowActions'));
Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.alwaysShowActions'))(updateActionsVisibility);
this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.alwaysShowActions'))(updateActionsVisibility));
updateActionsVisibility();
const updateProviderCountVisibility = () => {
@@ -1620,7 +1681,7 @@ export class SCMViewPane extends ViewPane {
toggleClass(this.listContainer, 'hide-provider-counts', value === 'hidden');
toggleClass(this.listContainer, 'auto-provider-counts', value === 'auto');
};
Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.providerCountBadge'))(updateProviderCountVisibility);
this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.providerCountBadge'))(updateProviderCountVisibility));
updateProviderCountVisibility();
const repositories = new SimpleSequence(this.scmService.repositories, this.scmService.onDidAddRepository, this.scmService.onDidRemoveRepository);
@@ -1631,7 +1692,7 @@ export class SCMViewPane extends ViewPane {
this._register(repositories.onDidSplice(() => this.updateActions()));
this.inputRenderer = this.instantiationService.createInstance(InputRenderer, this.layoutCache, (input, height) => this.tree.updateElementHeight(input, height), () => this.tree.domFocus());
this.inputRenderer = this.instantiationService.createInstance(InputRenderer, this.layoutCache, (input, height) => this.tree.updateElementHeight(input, height));
const delegate = new ProviderListDelegate(this.inputRenderer);
const actionViewItemProvider = (action: IAction) => this.getActionViewItem(action);
@@ -1678,6 +1739,7 @@ export class SCMViewPane extends ViewPane {
this._register(this.tree.onDidOpen(this.open, this));
this._register(this.tree.onContextMenu(this.onListContextMenu, this));
this._register(this.tree.onDidScroll(this.inputRenderer.clearValidation, this.inputRenderer));
this._register(this.tree);
let viewMode = this.configurationService.getValue<'tree' | 'list'>('scm.defaultViewMode') === 'list' ? ViewModelMode.List : ViewModelMode.Tree;
@@ -1697,8 +1759,12 @@ export class SCMViewPane extends ViewPane {
this._register(this.themeService.onDidFileIconThemeChange(this.updateIndentStyles, this));
this._register(this.viewModel.onDidChangeMode(this.onDidChangeMode, this));
this.toggleViewModelModeAction = new ToggleViewModeAction(ToggleViewModeAction.ID, ToggleViewModeAction.LABEL, this.viewModel);
this._register(this.toggleViewModelModeAction);
this._register(this.onDidChangeBodyVisibility(this.viewModel.setVisible, this.viewModel));
this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.alwaysShowRepositories'))(this.updateActions, this));
this.updateActions();
}
@@ -1740,15 +1806,22 @@ export class SCMViewPane extends ViewPane {
}
getActions(): IAction[] {
const result = [];
if (this.toggleViewModelModeAction) {
result.push(this.toggleViewModelModeAction);
}
if (!this.viewModel) {
return [];
return result;
}
if (this.viewModel.repositories.elements.length < 2) {
return this.viewModel.getViewActions();
return [...result, ...this.viewModel.getViewActions()];
}
return [
...result,
new SCMCollapseAction(this.viewModel),
...this.viewModel.getViewActions()
];