import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState, } from 'react'; import { relationId } from '../bundled'; import RelationSvg from '../MonacoDiffEditorRelation/RelationSvg'; import { IRelation, RelationTypeEnum } from '../types'; import createEditor from './createEditor'; import './index.scss'; export interface CreateRelationsProps { fromRev: string; toRev: string; fromContent: string; toContent: string; relations: IRelation[]; onRelationsChange?: (relations: IRelation[]) => void; onFromRevChange?: (rev: string) => void; onToRevChange?: (rev: string) => void; } export interface ICreateRelationsRef { layout: () => void; } export interface ICommonRef { relations: IRelation[]; onRelationsChange?: (relations: IRelation[]) => void; setFromRange: (range: [number, number]) => void; setToRange: (range: [number, number]) => void; } const options = [ { label: 'Current content', rev: '', }, { label: 'HEAD', rev: 'HEAD', }, ]; const CreateRelations = forwardRef( ( { fromRev, toRev, fromContent, toContent, relations, onRelationsChange, onFromRevChange, onToRevChange, }, ref ) => { const [fromRange, setFromRange] = useState<[number, number]>([0, 0]); const [toRange, setToRange] = useState<[number, number]>([0, 0]); const fromEditorElRef = useRef(null); const toEditorElRef = useRef(null); const relationSvgElRef = useRef(null); const fromEditorRef = useRef( null ); const toEditorRef = useRef( null ); const relationSvgRef = useRef(null); const commonRef = useRef({ relations, onRelationsChange, setFromRange, setToRange, }); const addRelation = () => { onRelationsChange?.([ ...relations, { id: relationId(), fromRange, toRange, type: RelationTypeEnum.relate, }, ]); }; useImperativeHandle(ref, () => ({ layout: () => { fromEditorRef.current?.layout(); toEditorRef.current?.layout(); }, })); useEffect(() => { commonRef.current = { relations, onRelationsChange, setFromRange, setToRange, }; }, [relations, onRelationsChange, setFromRange, setToRange]); useEffect(() => { fromEditorRef.current = createEditor(fromEditorElRef.current); toEditorRef.current = createEditor(toEditorElRef.current); }, []); useEffect(() => { const onDidChangeCursorSelection = () => { if (!fromEditorRef.current || !toEditorRef.current) { return; } const fromSelection = fromEditorRef.current.getSelection(); const toSelection = toEditorRef.current.getSelection(); const fromStartLine = fromSelection!.getStartPosition().lineNumber; const fromEndLine = fromSelection!.getEndPosition().lineNumber; const toStartLine = toSelection!.getStartPosition().lineNumber; const toEndLine = toSelection!.getEndPosition().lineNumber; commonRef.current.setFromRange([fromStartLine, fromEndLine]); commonRef.current.setToRange([toStartLine, toEndLine]); }; const fromDisposable = fromEditorRef.current?.onDidChangeCursorSelection( onDidChangeCursorSelection ); const toDisposable = toEditorRef.current?.onDidChangeCursorSelection( onDidChangeCursorSelection ); return () => { fromDisposable?.dispose(); toDisposable?.dispose(); }; }, []); useEffect(() => { fromEditorRef.current?.setValue(fromContent); }, [fromContent]); useEffect(() => { toEditorRef.current?.setValue(toContent); }, [toContent]); useEffect(() => { if (!relationSvgElRef.current) return; relationSvgRef.current = new RelationSvg( { getOriginalEditor() { return fromEditorRef.current; }, getModifiedEditor() { return fromEditorRef.current; }, } as any, { getOriginalEditor() { return toEditorRef.current; }, getModifiedEditor() { return toEditorRef.current; }, } as any, [], relationSvgElRef.current, { fromContainerDomNode: fromEditorRef.current!.getContainerDomNode(), toContainerDomNode: toEditorRef.current!.getContainerDomNode(), options({ id, type }) { if (type === RelationTypeEnum.temp) { return null; } return ( ); }, } ); }, []); useEffect(() => { const relationsWithAdding = [ ...relations, { fromRange, toRange, type: RelationTypeEnum.temp }, ]; relationSvgRef.current?.setRelations(relationsWithAdding); relationSvgRef.current?.renderLinks(); }, [relations, fromRange, toRange]); return (
Revision:
    {options.map(option => { return (
  • ); })}
Revision:
    {options.map(option => { return (
  • ); })}
From L { setFromRange?.([Number(e.target.value), fromRange?.[1]]); }} value={fromRange?.[0]} /> -L { setFromRange?.([fromRange?.[0], Number(e.target.value)]); }} value={fromRange?.[1]} /> to L { setToRange?.([Number(e.target.value), toRange?.[1]]); }} value={toRange?.[0]} /> -L { setToRange?.([toRange?.[0], Number(e.target.value)]); }} value={toRange?.[1]} />
); } ); export default CreateRelations;