Skip to content

Commit

Permalink
Use ScmTreeWidget in both commit details and in the diff widget
Browse files Browse the repository at this point in the history
Signed-off-by: Nigel Westbury <nigelipse@miegel.org>
  • Loading branch information
westbury committed Jul 14, 2020
1 parent a1ea230 commit 7b92322
Show file tree
Hide file tree
Showing 22 changed files with 1,252 additions and 723 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Breaking Changes:
<a name="1_4_0_deprecate_languages"></a>
- [[languages]](#1_4_0_deprecate_languages) `@theia/languages` extension is deprecated, use VS Code extensions to provide language smartness:
https://code.visualstudio.com/api/language-extensions/language-server-extension-guide [#8112](https://github.com/eclipse-theia/theia/pull/8112)
- [git] the changes in the commit details (opened from the history view) and in the diff view (opened with 'Compare With...' on a folder's context menu) are now switchable between 'list' and 'tree' modes

## v1.3.0

Expand Down
157 changes: 131 additions & 26 deletions packages/git/src/browser/diff/git-diff-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
import { CommandRegistry, Command, MenuModelRegistry, SelectionService, MessageService } from '@theia/core/lib/common';
import { FrontendApplication, AbstractViewContribution } from '@theia/core/lib/browser';
import { WidgetManager } from '@theia/core/lib/browser/widget-manager';
import { EditorManager } from '@theia/editor/lib/browser';
import { injectable, inject } from 'inversify';
import { GitDiffWidget, GIT_DIFF } from './git-diff-widget';
import { GitCommitDetailWidget } from '../history/git-commit-detail-widget';
import { GitDiffTreeModel } from './git-diff-tree-model';
import { ScmService } from '@theia/scm/lib/browser/scm-service';
import { open, OpenerService } from '@theia/core/lib/browser';
import { NavigatorContextMenu, FileNavigatorContribution } from '@theia/navigator/lib/browser/navigator-contribution';
Expand All @@ -31,14 +34,39 @@ import { GIT_RESOURCE_SCHEME } from '../git-resource';
import { Git, Repository } from '../../common';
import { WorkspaceRootUriAwareCommandHandler } from '@theia/workspace/lib/browser/workspace-commands';
import { WorkspaceService } from '@theia/workspace/lib/browser';
import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
import { TabBarToolbarContribution, TabBarToolbarRegistry, TabBarToolbarItem } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
import { Emitter } from '@theia/core/lib/common/event';

export namespace GitDiffCommands {
export const OPEN_FILE_DIFF: Command = {
id: 'git-diff:open-file-diff',
category: 'Git Diff',
label: 'Compare With...'
};
export const TREE_VIEW_MODE = {
id: 'git.viewmode.tree',
tooltip: 'Toggle to Tree View',
iconClass: 'codicon codicon-list-tree',
label: 'Toggle to Tree View',
};
export const LIST_VIEW_MODE = {
id: 'git.viewmode.list',
tooltip: 'Toggle to List View',
iconClass: 'codicon codicon-list-flat',
label: 'Toggle to List View',
};
export const PREVIOUS_CHANGE = {
id: 'git.navigate-changes.previous',
tooltip: 'Toggle to List View',
iconClass: 'fa fa-arrow-left',
label: 'Previous Change',
};
export const NEXT_CHANGE = {
id: 'git.navigate-changes.next',
tooltip: 'Toggle to List View',
iconClass: 'fa fa-arrow-right',
label: 'Next Change',
};
}

export namespace ScmNavigatorMoreToolbarGroups {
Expand All @@ -48,6 +76,9 @@ export namespace ScmNavigatorMoreToolbarGroups {
@injectable()
export class GitDiffContribution extends AbstractViewContribution<GitDiffWidget> implements TabBarToolbarContribution {

@inject(EditorManager)
protected readonly editorManager: EditorManager;

@inject(CommandRegistry)
protected readonly commandRegistry: CommandRegistry;

Expand Down Expand Up @@ -88,33 +119,52 @@ export class GitDiffContribution extends AbstractViewContribution<GitDiffWidget>
isVisible: uri => !!this.findGitRepository(uri),
isEnabled: uri => !!this.findGitRepository(uri),
execute: async fileUri => {
await this.quickOpenService.chooseTagsAndBranches(
async (fromRevision, toRevision) => {
const uri = fileUri.toString();
const fileStat = await this.fileSystem.getFileStat(uri);
const options: Git.Options.Diff = {
uri,
range: {
fromRevision
}
};
if (fileStat) {
if (fileStat.isDirectory) {
this.showWidget(options);
} else {
const fromURI = fileUri.withScheme(GIT_RESOURCE_SCHEME).withQuery(fromRevision);
const toURI = fileUri;
const diffUri = DiffUris.encode(fromURI, toURI);
if (diffUri) {
open(this.openerService, diffUri).catch(e => {
this.notifications.error(e.message);
});
const repository = this.findGitRepository(fileUri);
if (repository) {
await this.quickOpenService.chooseTagsAndBranches(
async (fromRevision, toRevision) => {
const uri = fileUri.toString();
const fileStat = await this.fileSystem.getFileStat(uri);
const diffOptions: Git.Options.Diff = {
uri,
range: {
fromRevision
}
};
if (fileStat) {
if (fileStat.isDirectory) {
this.showWidget({ rootUri: repository.localUri, diffOptions });
} else {
const fromURI = fileUri.withScheme(GIT_RESOURCE_SCHEME).withQuery(fromRevision);
const toURI = fileUri;
const diffUri = DiffUris.encode(fromURI, toURI);
if (diffUri) {
open(this.openerService, diffUri).catch(e => {
this.notifications.error(e.message);
});
}
}
}
}
}, this.findGitRepository(fileUri));
}, repository);
}
}
}));
commands.registerCommand(GitDiffCommands.PREVIOUS_CHANGE, {
execute: widget => {
if (widget instanceof GitDiffWidget) {
widget.goToPreviousChange();
}
},
isVisible: widget => widget instanceof GitDiffWidget,
});
commands.registerCommand(GitDiffCommands.NEXT_CHANGE, {
execute: widget => {
if (widget instanceof GitDiffWidget) {
widget.goToNextChange();
}
},
isVisible: widget => widget instanceof GitDiffWidget,
});
}

registerToolbarItems(registry: TabBarToolbarRegistry): void {
Expand All @@ -124,7 +174,62 @@ export class GitDiffContribution extends AbstractViewContribution<GitDiffWidget>
tooltip: GitDiffCommands.OPEN_FILE_DIFF.label,
group: ScmNavigatorMoreToolbarGroups.SCM,
});
}

const viewModeEmitter = new Emitter<void>();
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
const extractDiffWidget = (widget: any) => {
if (widget instanceof GitDiffWidget) {
return widget;
}
};
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
const extractCommitDetailWidget = (widget: any) => {
const ref = widget ? widget : this.editorManager.currentEditor;
if (ref instanceof GitCommitDetailWidget) {
return ref;
}
return undefined;
};
const registerToggleViewItem = (command: Command, mode: 'tree' | 'list') => {
const id = command.id;
const item: TabBarToolbarItem = {
id,
command: id,
tooltip: command.label,
onDidChange: viewModeEmitter.event
};
this.commandRegistry.registerCommand({ id, iconClass: command && command.iconClass }, {
execute: widget => {
const widgetWithChanges = extractDiffWidget(widget) || extractCommitDetailWidget(widget);
if (widgetWithChanges) {
widgetWithChanges.viewMode = mode;
viewModeEmitter.fire();
}
},
isVisible: widget => {
const widgetWithChanges = extractDiffWidget(widget) || extractCommitDetailWidget(widget);
if (widgetWithChanges) {
return widgetWithChanges.viewMode !== mode;
}
return false;
},
});
registry.registerItem(item);
};
registerToggleViewItem(GitDiffCommands.TREE_VIEW_MODE, 'tree');
registerToggleViewItem(GitDiffCommands.LIST_VIEW_MODE, 'list');

registry.registerItem({
id: GitDiffCommands.PREVIOUS_CHANGE.id,
command: GitDiffCommands.PREVIOUS_CHANGE.id,
tooltip: GitDiffCommands.PREVIOUS_CHANGE.label,
});
registry.registerItem({
id: GitDiffCommands.NEXT_CHANGE.id,
command: GitDiffCommands.NEXT_CHANGE.id,
tooltip: GitDiffCommands.NEXT_CHANGE.label,
});
}

protected findGitRepository(uri: URI): Repository | undefined {
const repo = this.scmService.findRepository(uri);
Expand All @@ -134,7 +239,7 @@ export class GitDiffContribution extends AbstractViewContribution<GitDiffWidget>
return undefined;
}

async showWidget(options: Git.Options.Diff): Promise<GitDiffWidget> {
async showWidget(options: GitDiffTreeModel.Options): Promise<GitDiffWidget> {
const widget = await this.widget;
await widget.setContent(options);
return this.openView({
Expand Down
29 changes: 24 additions & 5 deletions packages/git/src/browser/diff/git-diff-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,42 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { interfaces } from 'inversify';
import { interfaces, Container } from 'inversify';
import { GitDiffContribution } from './git-diff-contribution';
import { WidgetFactory, bindViewContribution } from '@theia/core/lib/browser';
import { WidgetFactory, bindViewContribution, TreeModel } from '@theia/core/lib/browser';
import { GitDiffWidget, GIT_DIFF } from './git-diff-widget';
import { GitDiffHeaderWidget } from './git-diff-header-widget';
import { GitDiffTreeModel } from './git-diff-tree-model';
import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar';

import { ScmTreeModel } from '@theia/scm/lib/browser/scm-tree-model';
import { createScmTreeContainer } from '@theia/scm/lib/browser/scm-frontend-module';
import { GitResourceOpener } from './git-resource-opener';
import { GitOpenerInPrimaryArea } from './git-opener-in-primary-area';
import '../../../src/browser/style/diff.css';

export function bindGitDiffModule(bind: interfaces.Bind): void {

bind(GitDiffWidget).toSelf();
bind(WidgetFactory).toDynamicValue(ctx => ({
id: GIT_DIFF,
createWidget: () => ctx.container.get<GitDiffWidget>(GitDiffWidget)
}));
createWidget: () => {
const child = createGitDiffWidgetContainer(ctx.container);
return child.get(GitDiffWidget);
}
})).inSingletonScope();

bindViewContribution(bind, GitDiffContribution);
bind(TabBarToolbarContribution).toService(GitDiffContribution);

}

export function createGitDiffWidgetContainer(parent: interfaces.Container): Container {
const child = createScmTreeContainer(parent);
child.bind(TreeModel).toService(GitDiffTreeModel);

child.bind(GitDiffHeaderWidget).toSelf();
child.bind(GitDiffTreeModel).toSelf();
child.bind(GitResourceOpener).to(GitOpenerInPrimaryArea);
child.bind(ScmTreeModel).toService(GitDiffTreeModel);
return child;
}
Loading

0 comments on commit 7b92322

Please sign in to comment.