diff --git a/src/commandsAndMenu.tsx b/src/commandsAndMenu.tsx index 4bf08f340..2bb5f8887 100644 --- a/src/commandsAndMenu.tsx +++ b/src/commandsAndMenu.tsx @@ -755,25 +755,48 @@ export function addCommands( label: trans.__('Open File'), caption: trans.__('Open file from its diff view'), execute: async _ => { - const widget = app.contextMenuHitTest((node: HTMLElement) => { + const domNode = app.contextMenuHitTest((node: HTMLElement) => { const nodeId = node.dataset.id; return nodeId && nodeId.substring(0, 8) === 'git-diff'; }); - if (!widget) { + if (!domNode) { return; } - const filename = widget.title; - const file = gitModel.status.files.find( - fileStatus => `${gitModel.pathRepository}/${fileStatus.to}` === filename + const matches = toArray(shell.widgets('main')).filter( + widget => widget.id === domNode.dataset.id ); - if (!file) { + + if (matches.length === 0) { return; } - commands.execute(ContextCommandIDs.gitFileOpen, { - files: [file] - } as CommandArguments.IGitContextAction as any); + const diffModel = ( + ((matches[0] as MainAreaWidget).content as Panel) + .widgets[0] as Git.Diff.IDiffWidget + ).model; + + const filename = diffModel.filename; + + if ( + diffModel.reference.source === Git.Diff.SpecialRef.INDEX || + diffModel.reference.source === Git.Diff.SpecialRef.WORKING || + diffModel.challenger.source === Git.Diff.SpecialRef.INDEX || + diffModel.challenger.source === Git.Diff.SpecialRef.WORKING + ) { + const file = gitModel.status.files.find( + fileStatus => fileStatus.from === filename + ); + if (file) { + commands.execute(ContextCommandIDs.gitFileOpen, { + files: [file] + } as any); + } + } else { + commands.execute('docmanager:open', { + path: gitModel.getRelativeFilePath(filename) + }); + } } }); diff --git a/src/components/diff/NotebookDiff.ts b/src/components/diff/NotebookDiff.ts index df48ceefe..5680aa7d8 100644 --- a/src/components/diff/NotebookDiff.ts +++ b/src/components/diff/NotebookDiff.ts @@ -175,6 +175,13 @@ export class NotebookDiff extends Panel implements Git.Diff.IDiffWidget { return this._model.hasConflict; } + /** + * Diff model + */ + get model(): Git.Diff.IModel { + return this._model; + } + /** * Nbdime notebook widget. */ diff --git a/src/components/diff/PlainTextDiff.ts b/src/components/diff/PlainTextDiff.ts index 18d67b29c..5c0d31fad 100644 --- a/src/components/diff/PlainTextDiff.ts +++ b/src/components/diff/PlainTextDiff.ts @@ -80,6 +80,13 @@ export class PlainTextDiff extends Widget implements Git.Diff.IDiffWidget { return true; } + /** + * Diff model + */ + get model(): Git.Diff.IModel { + return this._model; + } + /** * Promise which fulfills when the widget is ready. */ diff --git a/src/tokens.ts b/src/tokens.ts index 091311d2a..df1d92545 100644 --- a/src/tokens.ts +++ b/src/tokens.ts @@ -568,20 +568,24 @@ export namespace Git { */ export interface IDiffWidget extends Widget { /** - * Refresh the diff widget - * - * Note: Update the content and recompute the diff - */ - refresh(): Promise; - /** - * Checks if the conflicted file has been resolved. + * Diff model */ - isFileResolved: boolean; + readonly model: Git.Diff.IModel; /** * Gets the file model of a resolved merge conflict, * and rejects if unable to retrieve */ getResolvedFile(): Promise>; + /** + * Checks if the conflicted file has been resolved. + */ + readonly isFileResolved: boolean; + /** + * Refresh the diff widget + * + * Note: Update the content and recompute the diff + */ + refresh(): Promise; } /**