Path: blob/main/extensions/copilot/test/simulation/workbench/components/diffEditor.tsx
13399 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import type * as monaco from 'monaco-editor';6import * as React from 'react';7import { IDiagnosticComparison, IRange } from '../../shared/sharedTypes';8import { monacoModule } from '../utils/utils';9import { DraggableBottomBorder } from './draggableBottomBorder';10import { createDiagnosticDecorations } from './editor';11import { rangeToMonacoRange } from './monacoUtils';1213type Props = {14original: string;15modified: string;16languageId: string;17diagnostics?: IDiagnosticComparison;18selections?: {19before: IRange | undefined;20after: IRange | undefined;21};22};2324const LINE_HEIGHT = 19;2526export const DiffEditor = (({ original, modified, languageId, diagnostics, selections }: Props) => {2728const containerRef = React.useRef<HTMLDivElement | null>(null);29const [diffEditor, setDiffEditor] = React.useState<monaco.editor.IStandaloneDiffEditor | null>(null);30const [height, setHeight] = React.useState<number>(300);31const [altPressed, setAltPressed] = React.useState(false);3233const monaco = monacoModule.value;3435React.useEffect(() => {36if (!containerRef.current) {37return;38}3940const myEditor = monaco.editor.createDiffEditor(containerRef.current, {41automaticLayout: true,42lineHeight: LINE_HEIGHT,43minimap: { enabled: false },44readOnly: true,45renderLineHighlight: 'none',46scrollBeyondLastLine: false,47overviewRulerLanes: 0,48ignoreTrimWhitespace: false,49diffWordWrap: 'off',50scrollbar: {51alwaysConsumeMouseWheel: true, // setting to false allows scrolling in window when scroll reaches end of the editor52}53});54setDiffEditor(myEditor);5556return () => {57const model = myEditor.getModel();58if (model) {59const { original, modified } = model;60original.dispose();61modified.dispose();62}63myEditor.dispose();64};65}, []);6667React.useEffect(() => {68if (diffEditor) {69let model = diffEditor.getModel();70if (model) {71const { original: originalModel, modified: modifiedModel } = model;72originalModel.setValue(original);73monaco.editor.setModelLanguage(originalModel, languageId);74modifiedModel.setValue(modified);75monaco.editor.setModelLanguage(modifiedModel, languageId);76} else {77const model1 = monaco.editor.createModel(original, languageId);78const model2 = monaco.editor.createModel(modified, languageId);79model = { original: model1, modified: model2 };80diffEditor.setModel(model);81}8283if (diagnostics) {84diffEditor.getModifiedEditor().createDecorationsCollection().set(createDiagnosticDecorations(diagnostics.after, model.modified));85diffEditor.getOriginalEditor().createDecorationsCollection().set(createDiagnosticDecorations(diagnostics.before, model.original));86}8788if (selections) {89if (selections.before) {90const mselection = rangeToMonacoRange(selections.before);91diffEditor.getOriginalEditor().setSelection(mselection);92}93if (selections.after) {94const mselection = rangeToMonacoRange(selections.after);95diffEditor.getModifiedEditor().setSelection(mselection);96}97}9899// Navigate to first diff100diffEditor.onDidUpdateDiff(() => {101if (diffEditor === null) { return; }102103const changes = diffEditor.getLineChanges();104if (changes === null || changes.length === 0) {105return;106}107108const change = changes[0];109diffEditor.getModifiedEditor().revealLinesInCenter(change.modifiedStartLineNumber, change.modifiedEndLineNumber);110});111}112}, [diffEditor, original, modified, languageId, diagnostics, selections]);113114React.useEffect(() => {115const handleKeyDown = (e: KeyboardEvent) => {116if (e.altKey) {117setAltPressed(true);118}119};120121const handleKeyUp = (e: KeyboardEvent) => {122if (!e.altKey) {123setAltPressed(false);124}125};126127window.addEventListener('keydown', handleKeyDown);128window.addEventListener('keyup', handleKeyUp);129return () => {130window.removeEventListener('keydown', handleKeyDown);131window.removeEventListener('keyup', handleKeyUp);132};133}, []);134135const handleWheel = (e: React.WheelEvent) => {136if (altPressed) {137e.preventDefault();138e.stopPropagation();139}140};141142return (143<div>144<div className='file-editor-container' style={{ height: `${height}px`, position: 'relative' }} ref={containerRef}>145<div146className='overlay'147style={{148position: 'absolute', top: 0, left: 0, right: 0, bottom: 0,149pointerEvents: altPressed ? 'auto' : 'none',150backgroundColor: 'transparent',151zIndex: 1000152}}153onWheel={handleWheel}154/>155</div>156<DraggableBottomBorder height={height} setHeight={setHeight} />157</div>158);159});160161162