Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update DirtyDiffWidget change model when changes change
  • Loading branch information
colin-grant-work committed Mar 26, 2025
commit e2cf80c424ee1d55915521a7e0521245a0c47b17
2 changes: 1 addition & 1 deletion packages/monaco/src/browser/monaco-editor-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ export class MonacoEditorProvider {
fixedOverflowWidgets: true,
minimap: { enabled: false },
renderSideBySide: false,
readOnly: true,
readOnly: false,
renderIndicators: false,
diffAlgorithm: 'advanced',
stickyScroll: { enabled: false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class ScmDecorationsService {
const previousLines = ContentLines.fromString(previousContent);
const currentLines = ContentLines.fromTextEditorDocument(editor.document);
const dirtyDiff = this.diffComputer.computeDirtyDiff(ContentLines.arrayLike(previousLines), ContentLines.arrayLike(currentLines));
const update = <DirtyDiffUpdate>{ editor, previousRevisionUri: uri, ...dirtyDiff };
const update = { editor, previousRevisionUri: uri, ...dirtyDiff } satisfies DirtyDiffUpdate;
this.decorator.applyDecorations(update);
this.onDirtyDiffUpdateEmitter.fire(update);
} finally {
Expand Down
6 changes: 5 additions & 1 deletion packages/scm/src/browser/dirty-diff/dirty-diff-navigator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ export class DirtyDiffController implements Disposable {
handleDirtyDiffUpdate(dirtyDiff: DirtyDiffUpdate): void {
if (dirtyDiff.editor === this.editor) {
this.dirtyDiff = dirtyDiff;
if (this.widget) {
this.widget.changes = dirtyDiff.changes ;
}
}
}

Expand Down Expand Up @@ -209,7 +212,8 @@ export class DirtyDiffController implements Disposable {
protected createWidget(): DirtyDiffWidget | undefined {
const { widgetFactory, editor, changes, previousRevisionUri } = this;
if (widgetFactory && editor instanceof MonacoEditor && changes?.length && previousRevisionUri) {
const widget = widgetFactory({ editor, previousRevisionUri, changes });
const widget = widgetFactory({ editor, previousRevisionUri });
widget.changes = changes;
widget.onDidClose(() => {
this.widget = undefined;
});
Expand Down
57 changes: 32 additions & 25 deletions packages/scm/src/browser/dirty-diff/dirty-diff-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export const DirtyDiffWidgetProps = Symbol('DirtyDiffWidgetProps');
export interface DirtyDiffWidgetProps {
readonly editor: MonacoEditor;
readonly previousRevisionUri: URI;
readonly changes: readonly Change[];
}

export const DirtyDiffWidgetFactory = Symbol('DirtyDiffWidgetFactory');
Expand All @@ -50,6 +49,7 @@ export class DirtyDiffWidget implements Disposable {
protected index: number = -1;
private peekView: DirtyDiffPeekView;
private diffEditorPromise: Promise<MonacoDiffEditor>;
protected _changes?: readonly Change[];

constructor(
@inject(DirtyDiffWidgetProps) protected readonly props: DirtyDiffWidgetProps,
Expand All @@ -66,6 +66,14 @@ export class DirtyDiffWidget implements Disposable {
this.diffEditorPromise = this.peekView.create();
}

get changes(): readonly Change[] {
return this._changes ?? [];
}

set changes(changes: readonly Change[]) {
this.handleChangedChanges(changes);
}

get editor(): MonacoEditor {
return this.props.editor;
}
Expand All @@ -78,10 +86,6 @@ export class DirtyDiffWidget implements Disposable {
return this.props.previousRevisionUri;
}

get changes(): readonly Change[] {
return this.props.changes;
}

get currentChange(): Change | undefined {
return this.changes[this.index];
}
Expand All @@ -90,6 +94,16 @@ export class DirtyDiffWidget implements Disposable {
return this.index;
}

protected handleChangedChanges(updated: readonly Change[]): void {
if (this.currentChange) {
const {previousRange: {start, end}} = this.currentChange;
this.index = updated.findIndex(candidate => candidate.previousRange.start === start && candidate.previousRange.end === end);
} else {
this.index = -1;
}
this._changes = updated;
}

async showChange(index: number): Promise<void> {
await this.checkCreated();
if (index >= 0 && index < this.changes.length) {
Expand All @@ -99,23 +113,20 @@ export class DirtyDiffWidget implements Disposable {
}

async showNextChange(): Promise<void> {
await this.checkCreated();
const index = this.index;
const length = this.changes.length;
if (length > 0 && (index < 0 || length > 1)) {
this.index = index < 0 ? 0 : cycle(index, 1, length);
this.showCurrentChange();
}
const editor = await this.checkCreated();
editor.diffNavigator.next();
this.updateIndex(editor);
}

async showPreviousChange(): Promise<void> {
await this.checkCreated();
const index = this.index;
const length = this.changes.length;
if (length > 0 && (index < 0 || length > 1)) {
this.index = index < 0 ? length - 1 : cycle(index, -1, length);
this.showCurrentChange();
}
const editor = await this.checkCreated();
editor.diffNavigator.previous();
this.updateIndex(editor);
}

protected updateIndex(editor: MonacoDiffEditor): void {
const line = editor.cursor.line;
this.index = this.changes.findIndex(candidate => candidate.currentRange.start <= line && candidate.currentRange.end >= line);
}

async getContentWithSelectedChanges(predicate: (change: Change, index: number, changes: readonly Change[]) => boolean): Promise<string> {
Expand Down Expand Up @@ -174,15 +185,11 @@ export class DirtyDiffWidget implements Disposable {
return Math.min(changeHeightInLines + /* padding */ 8, Math.floor(editorHeightInLines / 3));
}

protected async checkCreated(): Promise<void> {
await this.diffEditorPromise;
protected async checkCreated(): Promise<MonacoDiffEditor> {
return this.diffEditorPromise;
}
}

function cycle(index: number, offset: -1 | 1, length: number): number {
return (index + offset + length) % length;
}

// adapted from https://github.com/microsoft/vscode/blob/823d54f86ee13eb357bc6e8e562e89d793f3c43b/extensions/git/src/staging.ts
function applyChanges(changes: readonly Change[], original: monaco.editor.ITextModel, modified: monaco.editor.ITextModel): string {
const result: string[] = [];
Expand Down
2 changes: 2 additions & 0 deletions packages/scm/src/browser/scm-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ export class ScmContribution extends AbstractViewContribution<ScmWidget> impleme
execute: widget => {
if (widget instanceof EditorWidget && widget.editor instanceof MonacoDiffEditor) {
widget.editor.diffNavigator.next();
widget.activate();
} else {
this.dirtyDiffNavigator.gotoNextChange();
}
Expand All @@ -219,6 +220,7 @@ export class ScmContribution extends AbstractViewContribution<ScmWidget> impleme
execute: widget => {
if (widget instanceof EditorWidget && widget.editor instanceof MonacoDiffEditor) {
widget.editor.diffNavigator.previous();
widget.activate();
} else {
this.dirtyDiffNavigator.gotoPreviousChange();
}
Expand Down