From 08d2d1220780bc090860ad9e3fbeb4007fbe3679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=A1=A8=E5=93=A5?= Date: Thu, 12 Jan 2023 17:04:56 +0800 Subject: [PATCH] fix: create diff and merge editor as needed (#2135) * fix: create diff and merge editor as needed * refactor: add editor open type enum (#2139) * fix: test case * chore: fix e2e test * chore: fix editor e2e test Co-authored-by: kuiwu --- .../variables/debug-variables.contribution.ts | 3 +- .../__tests__/browser/editor-service.test.ts | 9 +- .../__tests__/browser/editor.feature.test.ts | 11 +- .../__tests__/browser/test-providers.ts | 7 +- packages/editor/src/browser/diff/index.ts | 4 +- .../editor/src/browser/editor.override.ts | 6 +- packages/editor/src/browser/editor.view.tsx | 40 +- packages/editor/src/browser/history/index.ts | 7 +- .../merge-editor/merge-editor.contribution.ts | 6 +- .../src/browser/workbench-editor.service.ts | 444 ++++++++++-------- packages/editor/src/common/editor.ts | 9 +- .../src/browser/welcome/contribution.ts | 3 +- .../src/browser/vsx-extension.contribution.ts | 3 +- .../browser/main.thread.editor.test.ts | 6 +- .../src/browser/extension.contribution.ts | 4 +- .../sumi-browser/contribution/editor.ts | 6 +- .../src/browser/vscode/api/main.thread.doc.ts | 3 +- .../browser/vscode/api/main.thread.editor.ts | 61 ++- .../vscode/contributes/customEditors.tsx | 9 +- .../vscode/contributes/walkthroughs.tsx | 4 +- .../__tests__/browser/contribution.test.ts | 13 +- .../src/browser/file-scheme.contribution.ts | 13 +- .../src/browser/file-tree-contribution.ts | 8 +- .../src/browser/keymaps.contribution.ts | 4 +- packages/markdown/src/browser/contribution.ts | 4 +- .../src/browser/preference-contribution.ts | 3 +- packages/scm/src/browser/dirty-diff/index.ts | 4 +- .../src/browser/testing.contribution.ts | 3 +- .../webview/src/browser/webview.service.ts | 3 +- tools/playwright/src/tests/editor.test.ts | 6 +- tools/playwright/src/text-editor.ts | 1 - 31 files changed, 392 insertions(+), 315 deletions(-) diff --git a/packages/debug/src/browser/view/variables/debug-variables.contribution.ts b/packages/debug/src/browser/view/variables/debug-variables.contribution.ts index e08a00dd58..4a996274da 100644 --- a/packages/debug/src/browser/view/variables/debug-variables.contribution.ts +++ b/packages/debug/src/browser/view/variables/debug-variables.contribution.ts @@ -13,6 +13,7 @@ import { MenuContribution, IMenuRegistry, MenuId } from '@opensumi/ide-core-brow import { CommandService, CUSTOM_EDITOR_SCHEME, IExtensionProps, URI } from '@opensumi/ide-core-common'; import { BrowserEditorContribution, + EditorOpenType, IResource, ResourceService, WorkbenchEditorService, @@ -156,7 +157,7 @@ export class VariablesPanelContribution implements BrowserEditorContribution, Me disableNavigate: true, preview: true, forceOpenType: { - type: 'component', + type: EditorOpenType.component, componentId: HEX_EDITOR_EDITOR_ID, }, }, diff --git a/packages/editor/__tests__/browser/editor-service.test.ts b/packages/editor/__tests__/browser/editor-service.test.ts index 273b53bf12..23a48d2887 100644 --- a/packages/editor/__tests__/browser/editor-service.test.ts +++ b/packages/editor/__tests__/browser/editor-service.test.ts @@ -10,6 +10,7 @@ import { BrowserEditorContribution, EditorGroupChangeEvent, CodeEditorDidVisibleEvent, + EditorOpenType, } from '@opensumi/ide-editor/lib/browser'; import { EditorComponentRegistryImpl } from '@opensumi/ide-editor/lib/browser/component'; import { isEditStack, isEOLStack } from '@opensumi/ide-editor/lib/browser/doc-model/editor-is-fn'; @@ -247,14 +248,14 @@ describe('workbench editor service tests', () => { await editorService.open(testComponentUri); expect(editorService.editorGroups[0].currentOpenType).toBeDefined(); - expect(editorService.editorGroups[0].currentOpenType!.type).toBe('component'); + expect(editorService.editorGroups[0].currentOpenType!.type).toBe(EditorOpenType.component); expect(listener).toBeCalled(); await editorService.closeAll(); - await editorService.open(testComponentUri, { preview: false, forceOpenType: { type: 'code' } }); + await editorService.open(testComponentUri, { preview: false, forceOpenType: { type: EditorOpenType.code } }); expect(editorService.editorGroups[0].currentOpenType).toBeDefined(); - expect(editorService.editorGroups[0].currentOpenType!.type).toBe('code'); + expect(editorService.editorGroups[0].currentOpenType!.type).toBe(EditorOpenType.code); // 测试 getState 方法 expect(editorService.editorGroups[0].getState()).toEqual({ @@ -287,7 +288,7 @@ describe('workbench editor service tests', () => { new CodeEditorDidVisibleEvent({ groupName: editorService.currentEditorGroup.name, editorId: editorService.currentEditorGroup.codeEditor.getId(), - type: 'code', + type: EditorOpenType.code, }), ); diff --git a/packages/editor/__tests__/browser/editor.feature.test.ts b/packages/editor/__tests__/browser/editor.feature.test.ts index 3fb98bc90f..8bff43805f 100644 --- a/packages/editor/__tests__/browser/editor.feature.test.ts +++ b/packages/editor/__tests__/browser/editor.feature.test.ts @@ -13,6 +13,7 @@ import { IEditorGroup, EditorGroupChangeEvent, EditorGroupCloseEvent, + EditorOpenType, } from '@opensumi/ide-editor/lib/browser'; import { EditorFeatureRegistryImpl } from '@opensumi/ide-editor/lib/browser/feature'; import { FormattingSelector } from '@opensumi/ide-editor/lib/browser/format/formatterSelect'; @@ -199,7 +200,7 @@ describe('editor history test', () => { new EditorGroupChangeEvent({ group: testEditorGroup, newOpenType: { - type: 'code', + type: EditorOpenType.code, }, oldOpenType: null, newResource: { @@ -305,10 +306,10 @@ describe('editor history test', () => { new EditorGroupChangeEvent({ group: testEditorGroup, newOpenType: { - type: 'code', + type: EditorOpenType.code, }, oldOpenType: { - type: 'code', + type: EditorOpenType.code, }, newResource: { uri: testUri2, @@ -355,10 +356,10 @@ describe('editor history test', () => { new EditorGroupChangeEvent({ group: testEditorGroup, newOpenType: { - type: 'code', + type: EditorOpenType.code, }, oldOpenType: { - type: 'code', + type: EditorOpenType.code, }, newResource: { uri: testUri3, diff --git a/packages/editor/__tests__/browser/test-providers.ts b/packages/editor/__tests__/browser/test-providers.ts index 4fbf4c3f2b..755552b49b 100644 --- a/packages/editor/__tests__/browser/test-providers.ts +++ b/packages/editor/__tests__/browser/test-providers.ts @@ -4,6 +4,7 @@ import { IEditorDocumentModelContentProvider, IEditorComponentResolver, IEditorComponent, + EditorOpenType, } from '@opensumi/ide-editor/lib/browser'; export const doNotClose: string[] = []; @@ -39,7 +40,7 @@ export const TestEditorDocumentProvider: IEditorDocumentModelContentProvider = { export const TestResourceResolver: IEditorComponentResolver = (resource: IResource, results) => { results.push({ - type: 'code', + type: EditorOpenType.code, }); }; @@ -47,7 +48,7 @@ export const TestResourceResolver2: IEditorComponentResolver = (resource: IResou if (resource.uri.authority === 'component') { results.push({ componentId: 'test-v-component', - type: 'component', + type: EditorOpenType.component, weight: 100, }); return; @@ -55,7 +56,7 @@ export const TestResourceResolver2: IEditorComponentResolver = (resource: IResou if (resource.uri.authority === 'diff') { results.push({ componentId: 'test-v-component', - type: 'diff', + type: EditorOpenType.diff, }); return; } diff --git a/packages/editor/src/browser/diff/index.ts b/packages/editor/src/browser/diff/index.ts index ef8f2920ed..d91a85d994 100644 --- a/packages/editor/src/browser/diff/index.ts +++ b/packages/editor/src/browser/diff/index.ts @@ -3,7 +3,7 @@ import { URI, Domain, WithEventBus, OnEvent } from '@opensumi/ide-core-browser'; import { LabelService } from '@opensumi/ide-core-browser/lib/services'; import { IResourceProvider, IDiffResource, ResourceService, ResourceDecorationChangeEvent } from '../../common'; -import { BrowserEditorContribution, EditorComponentRegistry } from '../types'; +import { BrowserEditorContribution, EditorComponentRegistry, EditorOpenType } from '../types'; // diff URI: // diff://?name=tabName&original=uri1&modified=uri2 @@ -74,7 +74,7 @@ export class DefaultDiffEditorContribution implements BrowserEditorContribution registerEditorComponent(registry: EditorComponentRegistry) { registry.registerEditorComponentResolver('diff', (resource: IDiffResource, results) => { results.push({ - type: 'diff', + type: EditorOpenType.diff, }); }); } diff --git a/packages/editor/src/browser/editor.override.ts b/packages/editor/src/browser/editor.override.ts index acee1d3b75..f89b2c749b 100644 --- a/packages/editor/src/browser/editor.override.ts +++ b/packages/editor/src/browser/editor.override.ts @@ -11,7 +11,7 @@ import { IStandaloneThemeService } from '@opensumi/monaco-editor-core/esm/vs/edi import { ContextViewService } from '@opensumi/monaco-editor-core/esm/vs/platform/contextview/browser/contextViewService'; /* istanbul ignore file */ -import { WorkbenchEditorService } from '../common'; +import { EditorOpenType, WorkbenchEditorService } from '../common'; import { BrowserCodeEditor } from './editor-collection.service'; import { WorkbenchEditorServiceImpl } from './workbench-editor.service'; @@ -60,12 +60,12 @@ export class MonacoCodeService extends AbstractCodeEditorService { !new URI(source.getModel()?.uri).isEqual(input.resource) ) { for (const visibleGroup of this.workbenchEditorService.editorGroups) { - if (visibleGroup.currentOpenType?.type === 'code') { + if (visibleGroup.currentOpenType?.type === EditorOpenType.code) { if (visibleGroup.currentEditor?.monacoEditor === source) { visibleGroup.pinPreviewed(visibleGroup.currentResource?.uri); break; } - } else if (visibleGroup.currentOpenType?.type === 'diff') { + } else if (visibleGroup.currentOpenType?.type === EditorOpenType.diff) { if ( visibleGroup.diffEditor!.modifiedEditor.monacoEditor === source || visibleGroup.diffEditor!.originalEditor.monacoEditor === source diff --git a/packages/editor/src/browser/editor.view.tsx b/packages/editor/src/browser/editor.view.tsx index 6f68149917..b97864e0e0 100644 --- a/packages/editor/src/browser/editor.view.tsx +++ b/packages/editor/src/browser/editor.view.tsx @@ -44,6 +44,7 @@ import { EditorSide, IEditorComponent, CodeEditorDidVisibleEvent, + EditorOpenType, } from './types'; import { EditorGroup, WorkbenchEditorServiceImpl } from './workbench-editor.service'; @@ -213,8 +214,6 @@ export const EditorGridView = ({ grid }: { grid: EditorGrid }) => { }; const cachedEditor: { [key: string]: HTMLDivElement } = {}; -const cachedDiffEditor: { [key: string]: HTMLDivElement } = {}; -const cachedMergeEditor: { [key: string]: HTMLDivElement } = {}; /** * 默认的 editor empty component @@ -343,27 +342,12 @@ export const EditorGroupBody = observer(({ group }: { group: EditorGroup }) => { group.createEditor(container); } } + if (diffEditorRef.current) { - if (cachedDiffEditor[group.name]) { - cachedDiffEditor[group.name].remove(); - diffEditorRef.current.appendChild(cachedDiffEditor[group.name]); - } else { - const container = document.createElement('div'); - diffEditorRef.current.appendChild(container); - cachedDiffEditor[group.name] = container; - group.createDiffEditor(container); - } + group.attachDiffEditorDom(diffEditorRef.current); } if (mergeEditorRef.current) { - if (cachedMergeEditor[group.name]) { - cachedMergeEditor[group.name].remove(); - mergeEditorRef.current.appendChild(cachedMergeEditor[group.name]); - } else { - const container = document.createElement('div'); - mergeEditorRef.current.appendChild(container); - cachedMergeEditor[group.name] = container; - group.createMergeEditor(container); - } + group.attachMergeEditorDom(mergeEditorRef.current); } }, [codeEditorRef.current, diffEditorRef.current, mergeEditorRef.current]); @@ -401,19 +385,19 @@ export const EditorGroupBody = observer(({ group }: { group: EditorGroup }) => { ); React.useEffect(() => { - if (group.currentOpenType?.type === 'code') { + if (group.currentOpenType?.type === EditorOpenType.code) { eventBus.fire( new CodeEditorDidVisibleEvent({ groupName: group.name, - type: 'code', + type: EditorOpenType.code, editorId: group.codeEditor.getId(), }), ); - } else if (group.currentOpenType?.type === 'diff') { + } else if (group.currentOpenType?.type === EditorOpenType.diff) { eventBus.fire( new CodeEditorDidVisibleEvent({ groupName: group.name, - type: 'diff', + type: EditorOpenType.diff, editorId: group.diffEditor.modifiedEditor.getId(), }), ); @@ -465,7 +449,7 @@ export const EditorGroupBody = observer(({ group }: { group: EditorGroup }) => {
{components} @@ -474,19 +458,19 @@ export const EditorGroupBody = observer(({ group }: { group: EditorGroup }) => { className={classnames({ [styles.kt_editor_code_editor]: true, [styles.kt_editor_component]: true, - [styles.kt_hidden]: !group.currentOpenType || group.currentOpenType.type !== 'code', + [styles.kt_hidden]: !group.currentOpenType || group.currentOpenType.type !== EditorOpenType.code, })} ref={codeEditorRef} />
diff --git a/packages/editor/src/browser/history/index.ts b/packages/editor/src/browser/history/index.ts index 67a98ae690..88c9da20f3 100644 --- a/packages/editor/src/browser/history/index.ts +++ b/packages/editor/src/browser/history/index.ts @@ -11,7 +11,7 @@ import { } from '@opensumi/ide-core-browser'; import { WorkbenchEditorService } from '../../common'; -import { EditorSelectionChangeEvent, EditorGroupChangeEvent, EditorGroupCloseEvent } from '../types'; +import { EditorSelectionChangeEvent, EditorGroupChangeEvent, EditorGroupCloseEvent, EditorOpenType } from '../types'; const HistoryPositionLineThreshold = 7; const HardMaxStateLength = 200; // 超过200个过后,会缩减至100个, 防止反复缩减 @@ -89,7 +89,10 @@ export class EditorHistoryService extends WithEventBus { @OnEvent(EditorGroupChangeEvent) onEditorGroupChangeEvent(e: EditorGroupChangeEvent) { - if (e.payload.newOpenType && (e.payload.newOpenType.type === 'code' || e.payload.newOpenType.type === 'diff')) { + if ( + e.payload.newOpenType && + (e.payload.newOpenType.type === EditorOpenType.code || e.payload.newOpenType.type === EditorOpenType.diff) + ) { const selections = e.payload.group.currentEditor!.getSelections(); if (selections && selections.length > 0) { this.onNewState( diff --git a/packages/editor/src/browser/merge-editor/merge-editor.contribution.ts b/packages/editor/src/browser/merge-editor/merge-editor.contribution.ts index 08fc53874b..ab87c47393 100644 --- a/packages/editor/src/browser/merge-editor/merge-editor.contribution.ts +++ b/packages/editor/src/browser/merge-editor/merge-editor.contribution.ts @@ -1,8 +1,8 @@ import { Autowired } from '@opensumi/di'; -import { Disposable, Domain } from '@opensumi/ide-core-browser'; +import { Domain } from '@opensumi/ide-core-browser'; import { ResourceService } from '../../common'; -import { BrowserEditorContribution, EditorComponentRegistry, IEditor, IEditorFeatureRegistry } from '../types'; +import { BrowserEditorContribution, EditorComponentRegistry, EditorOpenType } from '../types'; import { MergeEditorResourceProvider } from './merge-editor.provider'; @@ -18,7 +18,7 @@ export class MergeEditorContribution implements BrowserEditorContribution { registerEditorComponent(registry: EditorComponentRegistry) { registry.registerEditorComponentResolver('mergeEditor', (_, results) => { results.push({ - type: 'mergeEditor', + type: EditorOpenType.mergeEditor, }); }); } diff --git a/packages/editor/src/browser/workbench-editor.service.ts b/packages/editor/src/browser/workbench-editor.service.ts index 33d2a7e871..c6b6a7a1b0 100644 --- a/packages/editor/src/browser/workbench-editor.service.ts +++ b/packages/editor/src/browser/workbench-editor.service.ts @@ -99,6 +99,7 @@ import { RegisterEditorComponentEvent, AskSaveResult, IMergeEditorResource, + EditorOpenType, } from './types'; import { UntitledDocumentIdCounter } from './untitled-resource'; @@ -731,12 +732,18 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { private resourceOpenHistory: URI[] = []; private _domNode: MaybeNull = null; + private _diffEditorDomNode: MaybeNull = null; + private _diffEditorDomNodeAttached = false; + private _mergeEditorDomNode: MaybeNull = null; + private _mergeEditorDomNodeAttached = false; private codeEditorReady = new ReadyEvent(); private diffEditorReady = new ReadyEvent(); + private diffEditorDomReady = new ReadyEvent(); private mergeEditorReady = new ReadyEvent(); + private mergeEditorDomReady = new ReadyEvent(); private _restoringState = false; @@ -776,6 +783,22 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { ); } + attachDiffEditorDom(domNode: HTMLElement | null | undefined) { + if (!this._diffEditorDomNodeAttached) { + this._diffEditorDomNode = domNode; + this.diffEditorDomReady.ready(); + this._diffEditorDomNodeAttached = true; + } + } + + attachMergeEditorDom(domNode: HTMLElement | null | undefined) { + if (!this._mergeEditorDomNodeAttached) { + this._mergeEditorDomNode = domNode; + this.mergeEditorDomReady.ready(); + this._mergeEditorDomNodeAttached = true; + } + } + attachToDom(domNode: HTMLElement | null | undefined) { this._domNode = domNode; if (domNode) { @@ -799,7 +822,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { @debounce(100) doLayoutEditors() { if (this.codeEditor) { - if (this.currentOpenType && this.currentOpenType.type === 'code') { + if (this.currentOpenType && this.currentOpenType.type === EditorOpenType.code) { this.codeEditor.layout(); this._codeEditorPendingLayout = false; } else { @@ -807,7 +830,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { } } if (this.diffEditor) { - if (this.currentOpenType && this.currentOpenType.type === 'diff') { + if (this.currentOpenType && this.currentOpenType.type === EditorOpenType.diff) { this.diffEditor.layout(); this._diffEditorPendingLayout = false; } else { @@ -815,7 +838,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { } } if (this.mergeEditor) { - if (this.currentOpenType && this.currentOpenType.type === 'mergeEditor') { + if (this.currentOpenType && this.currentOpenType.type === EditorOpenType.mergeEditor) { // this.mergeEditor.layout(); this._mergeEditorPendingLayout = false; } else { @@ -1005,9 +1028,9 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { get currentEditor(): IEditor | null { if (this.currentOpenType) { - if (this.currentOpenType.type === 'code') { + if (this.currentOpenType.type === EditorOpenType.code) { return this.codeEditor; - } else if (this.currentOpenType.type === 'diff') { + } else if (this.currentOpenType.type === EditorOpenType.diff) { return this.diffEditor.modifiedEditor; } else { return null; @@ -1023,11 +1046,11 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { get currentFocusedEditor() { if (this.currentOpenType) { - if (this.currentOpenType.type === 'code') { + if (this.currentOpenType.type === EditorOpenType.code) { if (this.codeEditor.monacoEditor.hasWidgetFocus()) { return this.codeEditor; } - } else if (this.currentOpenType.type === 'diff') { + } else if (this.currentOpenType.type === EditorOpenType.diff) { if (this.diffEditor.modifiedEditor.monacoEditor.hasTextFocus()) { return this.diffEditor.modifiedEditor; } else if (this.diffEditor.originalEditor.monacoEditor.hasTextFocus()) { @@ -1045,7 +1068,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { get currentCodeEditor(): ICodeEditor | null { if (this.currentOpenType) { - if (this.currentOpenType.type === 'code') { + if (this.currentOpenType.type === EditorOpenType.code) { return this.codeEditor; } else { return null; @@ -1073,7 +1096,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { ); this.toDispose.push( this.codeEditor.onSelectionsChanged((e) => { - if (this.currentOpenType && this.currentOpenType.type === 'code') { + if (this.currentOpenType && this.currentOpenType.type === EditorOpenType.code) { this.eventBus.fire( new EditorSelectionChangeEvent({ group: this, @@ -1088,7 +1111,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { ); this.toDispose.push( this.codeEditor.onVisibleRangesChanged((e) => { - if (this.currentOpenType && this.currentOpenType.type === 'code') { + if (this.currentOpenType && this.currentOpenType.type === EditorOpenType.code) { this.eventBus.fire( new EditorVisibleChangeEvent({ group: this, @@ -1102,7 +1125,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { ); this.toDispose.push( this.codeEditor.onConfigurationChanged(() => { - if (this.currentOpenType && this.currentOpenType.type === 'code') { + if (this.currentOpenType && this.currentOpenType.type === EditorOpenType.code) { this.eventBus.fire( new EditorConfigurationChangedEvent({ group: this, @@ -1116,7 +1139,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { this.eventBus.fire( new CodeEditorDidVisibleEvent({ groupName: this.name, - type: 'code', + type: EditorOpenType.code, editorId: this.codeEditor.getId(), }), ); @@ -1152,7 +1175,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { this.eventBus.fire( new CodeEditorDidVisibleEvent({ groupName: this.name, - type: 'diff', + type: EditorOpenType.diff, editorId: this.diffEditor.modifiedEditor.getId(), }), ); @@ -1160,7 +1183,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { this.eventBus.fire( new CodeEditorDidVisibleEvent({ groupName: this.name, - type: 'diff', + type: EditorOpenType.diff, editorId: this.diffEditor.originalEditor.getId(), }), ); @@ -1170,7 +1193,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { private addDiffEditorEventListeners(editor: IEditor, side?: 'modified' | 'original') { this.toDispose.push( editor.onSelectionsChanged((e) => { - if (this.currentOpenType && this.currentOpenType.type === 'diff') { + if (this.currentOpenType && this.currentOpenType.type === EditorOpenType.diff) { this.eventBus.fire( new EditorSelectionChangeEvent({ group: this, @@ -1187,7 +1210,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { this.toDispose.push( editor.onVisibleRangesChanged((e) => { - if (this.currentOpenType && this.currentOpenType.type === 'diff') { + if (this.currentOpenType && this.currentOpenType.type === EditorOpenType.diff) { this.eventBus.fire( new EditorVisibleChangeEvent({ group: this, @@ -1202,7 +1225,7 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { this.toDispose.push( editor.onConfigurationChanged(() => { - if (this.currentOpenType && this.currentOpenType.type === 'diff') { + if (this.currentOpenType && this.currentOpenType.type === EditorOpenType.diff) { this.eventBus.fire( new EditorConfigurationChangedEvent({ group: this, @@ -1469,188 +1492,225 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { } } - private async displayResourceComponent(resource: IResource, options: IResourceOpenOptions) { - if (options.revealRangeInCenter === undefined) { - options.revealRangeInCenter = true; - } + private async openCodeEditor(resource: IResource, options: IResourceOpenOptions) { + const documentRef = await this.getDocumentModelRef(resource.uri); + this.resolveTabChanged(resource, this.currentResource); + await this.codeEditorReady.onceReady(async () => { + await this.codeEditor.open(documentRef); - const _resource = resource; - const result = await this.resolveOpenType(resource, options); - if (result) { - const { activeOpenType, openTypes } = result; - - this.availableOpenTypes = openTypes; - - if (options.preserveFocus) { - options.focus = false; + if (options.range) { + const range = new monaco.Range( + options.range.startLineNumber!, + options.range.startColumn!, + options.range.endLineNumber!, + options.range.endColumn!, + ); + // 这里使用 setTimeout 在下一次事件循环时将编辑器滚动到指定位置 + // 原因是在打开新文件的情况下 + // setModel 后立即调用 revealRangeInCenter 编辑器无法获取到 viewport 宽高 + // 导致无法正确计算滚动位置 + this.codeEditor.monacoEditor.setSelection(range); + if (options.revealRangeInCenter) { + setTimeout(() => { + this.codeEditor.monacoEditor.revealRangeInCenter(range, 1); + }); + } } - if (activeOpenType.type === 'code') { - const documentRef = await this.getDocumentModelRef(resource.uri); - this.resolveTabChanged(_resource, this.currentResource); - await this.codeEditorReady.onceReady(async () => { - this.codeEditor.open(documentRef); - - if (options.range) { - const range = new monaco.Range( - options.range.startLineNumber!, - options.range.startColumn!, - options.range.endLineNumber!, - options.range.endColumn!, - ); - // 这里使用 setTimeout 在下一次事件循环时将编辑器滚动到指定位置 - // 原因是在打开新文件的情况下 - // setModel 后立即调用 revealRangeInCenter 编辑器无法获取到 viewport 宽高 - // 导致无法正确计算滚动位置 - this.codeEditor.monacoEditor.setSelection(range); - if (options.revealRangeInCenter) { - setTimeout(() => { - this.codeEditor.monacoEditor.revealRangeInCenter(range, 1); - }); + // 同上 + queueMicrotask(() => { + if (options.scrollTop) { + this.codeEditor.monacoEditor.setScrollTop(options.scrollTop!); + } + if (options.scrollLeft) { + this.codeEditor.monacoEditor.setScrollLeft(options.scrollLeft!); + } + }); + + if (options.focus) { + this._domNode?.focus(); + // monaco 编辑器的 focus 多了一步检查,由于此时其实对应编辑器的 dom 的 display 为 none (需要等 React 下一次渲染才会改变为 block), + // 会引起 document.activeElement !== editor.textArea.domNode,进而会导致focus失败 + // 需要等待真正 append 之后再 + const disposer = this.eventBus.on(CodeEditorDidVisibleEvent, (e) => { + if (e.payload.groupName === this.name && e.payload.type === EditorOpenType.code) { + disposer.dispose(); + // 此处必须多做一些检查以免不必要的 focus + if (this.disposed) { + return; + } + if (this !== this.workbenchEditorService.currentEditorGroup) { + return; + } + if (this.currentEditor === this.codeEditor && this.codeEditor.currentUri?.isEqual(resource.uri)) { + try { + this.codeEditor.focus(); + } catch (e) { + // noop + } } } + }); + } + }); + + // 可能在diff Editor中修改导致为脏 + if (documentRef.instance!.dirty) { + this.pinPreviewed(resource.uri); + } + } + + private async openDiffEditor(resource: IResource, options: IResourceOpenOptions) { + if (!this.diffEditor) { + await this.diffEditorDomReady.onceReady(() => { + const container = document.createElement('div'); + this._diffEditorDomNode?.appendChild(container); + this.createDiffEditor(container); + }); + } - // 同上 - queueMicrotask(() => { - if (options.scrollTop) { - this.codeEditor.monacoEditor.setScrollTop(options.scrollTop!); + const diffResource = resource as IDiffResource; + const [original, modified] = await Promise.all([ + this.getDocumentModelRef(diffResource.metadata!.original), + this.getDocumentModelRef(diffResource.metadata!.modified), + ]); + await this.diffEditorReady.onceReady(async () => { + await this.diffEditor.compare(original, modified, options, resource.uri); + if (options.focus) { + this._domNode?.focus(); + // 理由见上方 codeEditor.focus 部分 + + const disposer = this.eventBus.on(CodeEditorDidVisibleEvent, (e) => { + if (e.payload.groupName === this.name && e.payload.type === EditorOpenType.diff) { + disposer.dispose(); + if (this.disposed) { + return; } - if (options.scrollLeft) { - this.codeEditor.monacoEditor.setScrollLeft(options.scrollLeft!); + if (this !== this.workbenchEditorService.currentEditorGroup) { + return; } - }); - - if (options.focus) { - this._domNode?.focus(); - // monaco 编辑器的 focus 多了一步检查,由于此时其实对应编辑器的 dom 的 display 为 none (需要等 React 下一次渲染才会改变为 block), - // 会引起 document.activeElement !== editor.textArea.domNode,进而会导致focus失败 - // 需要等待真正 append 之后再 - const disposer = this.eventBus.on(CodeEditorDidVisibleEvent, (e) => { - if (e.payload.groupName === this.name && e.payload.type === 'code') { - disposer.dispose(); - // 此处必须多做一些检查以免不必要的 focus - if (this.disposed) { - return; - } - if (this !== this.workbenchEditorService.currentEditorGroup) { - return; - } - if (this.currentEditor === this.codeEditor && this.codeEditor.currentUri?.isEqual(resource.uri)) { - try { - this.codeEditor.focus(); - } catch (e) { - // noop - } - } + if (this.currentEditor === this.diffEditor.modifiedEditor) { + try { + this.diffEditor.focus(); + } catch (e) { + // noop } - }); + } } }); - // 可能在diff Editor中修改导致为脏 - if (documentRef.instance!.dirty) { - this.pinPreviewed(resource.uri); + } + }); + } + + private async openMergeEditor(resource: IResource) { + const { metadata } = resource as IMergeEditorResource; + if (!metadata) { + return; + } + + if (!this.mergeEditor) { + await this.mergeEditorDomReady.onceReady(() => { + const container = document.createElement('div'); + this._mergeEditorDomNode?.appendChild(container); + this.createMergeEditor(container); + }); + } + + const { ancestor, input1, input2, output } = metadata; + const input1Data = MergeEditorInputData.from(input1); + const input2Data = MergeEditorInputData.from(input2); + + const [ancestorRef, input1Ref, outputRef, input2Ref] = await Promise.all([ + this.getDocumentModelRef(URI.parse(ancestor)), + this.getDocumentModelRef(input1Data.uri), + this.getDocumentModelRef(URI.parse(output)), + this.getDocumentModelRef(input2Data.uri), + ]); + + await this.mergeEditorReady.onceReady(async () => { + await this.mergeEditor.open({ + ancestor: { + uri: URI.parse(metadata.ancestor), + textModel: ancestorRef.instance.getMonacoModel(), + }, + input1: input1Data.setTextModel(input1Ref.instance.getMonacoModel()), + input2: input2Data.setTextModel(input2Ref.instance.getMonacoModel()), + output: { + uri: URI.parse(metadata.output), + textModel: outputRef.instance.getMonacoModel(), + }, + }); + }); + } + + private async openCustomEditor(resource: IResource, componentId?: string) { + const component = this.editorComponentRegistry.getEditorComponent(componentId as string); + const initialProps = this.editorComponentRegistry.getEditorInitialProps(componentId as string); + if (!component) { + throw new Error('Cannot find Editor Component with id: ' + componentId); + } else { + this.activateComponentsProps.set(component, initialProps); + if (component.renderMode === EditorComponentRenderMode.ONE_PER_RESOURCE) { + const openedResources = this.activeComponents.get(component) || []; + const index = openedResources.findIndex((r) => r.uri.toString() === resource.uri.toString()); + if (index === -1) { + openedResources.push(resource); } - } else if (activeOpenType.type === 'diff') { - const diffResource = resource as IDiffResource; - const [original, modified] = await Promise.all([ - this.getDocumentModelRef(diffResource.metadata!.original), - this.getDocumentModelRef(diffResource.metadata!.modified), - ]); - await this.diffEditorReady.onceReady(async () => { - await this.diffEditor.compare(original, modified, options, resource.uri); - if (options.focus) { - this._domNode?.focus(); - // 理由见上方 codeEditor.focus 部分 - - const disposer = this.eventBus.on(CodeEditorDidVisibleEvent, (e) => { - if (e.payload.groupName === this.name && e.payload.type === 'diff') { - disposer.dispose(); - if (this.disposed) { - return; - } - if (this !== this.workbenchEditorService.currentEditorGroup) { - return; - } - if (this.currentEditor === this.diffEditor.modifiedEditor) { - try { - this.diffEditor.focus(); - } catch (e) { - // noop - } - } - } - }); + this.activeComponents.set(component, openedResources); + } else if (component.renderMode === EditorComponentRenderMode.ONE_PER_GROUP) { + this.activeComponents.set(component, [resource]); + } else if (component.renderMode === EditorComponentRenderMode.ONE_PER_WORKBENCH) { + const promises: Promise[] = []; + this.workbenchEditorService.editorGroups.forEach((g) => { + if (g === this) { + return; } - }); - } else if (activeOpenType.type === 'component') { - const component = this.editorComponentRegistry.getEditorComponent(activeOpenType.componentId as string); - const initialProps = this.editorComponentRegistry.getEditorInitialProps(activeOpenType.componentId as string); - if (!component) { - throw new Error('Cannot find Editor Component with id: ' + activeOpenType.componentId); - } else { - this.activateComponentsProps.set(component, initialProps); - if (component.renderMode === EditorComponentRenderMode.ONE_PER_RESOURCE) { - const openedResources = this.activeComponents.get(component) || []; - const index = openedResources.findIndex((r) => r.uri.toString() === resource.uri.toString()); - if (index === -1) { - openedResources.push(resource); - } - this.activeComponents.set(component, openedResources); - } else if (component.renderMode === EditorComponentRenderMode.ONE_PER_GROUP) { - this.activeComponents.set(component, [resource]); - } else if (component.renderMode === EditorComponentRenderMode.ONE_PER_WORKBENCH) { - const promises: Promise[] = []; - this.workbenchEditorService.editorGroups.forEach((g) => { - if (g === this) { - return; - } - const r = g.resources.find((r) => r.uri.isEqual(resource.uri)); - if (r) { - promises.push(g.close(r.uri)); - } - }); - await Promise.all(promises).catch(getDebugLogger().error); - this.activeComponents.set(component, [resource]); + const r = g.resources.find((r) => r.uri.isEqual(resource.uri)); + if (r) { + promises.push(g.close(r.uri)); } - } - // 打开非编辑器的component时需要手动触发 - this._onCurrentEditorCursorChange.fire({ - position: null, - selectionLength: 0, }); - } else if (activeOpenType.type === 'mergeEditor') { - const { metadata } = resource as IMergeEditorResource; - if (!metadata) { - return; - } + await Promise.all(promises).catch(getDebugLogger().error); + this.activeComponents.set(component, [resource]); + } + } + // 打开非编辑器的component时需要手动触发 + this._onCurrentEditorCursorChange.fire({ + position: null, + selectionLength: 0, + }); + } - const { ancestor, input1, input2, output } = metadata; - const input1Data = MergeEditorInputData.from(input1); - const input2Data = MergeEditorInputData.from(input2); - - const [ancestorRef, input1Ref, outputRef, input2Ref] = await Promise.all([ - this.getDocumentModelRef(URI.parse(ancestor)), - this.getDocumentModelRef(input1Data.uri), - this.getDocumentModelRef(URI.parse(output)), - this.getDocumentModelRef(input2Data.uri), - ]); - - await this.mergeEditorReady.onceReady(async () => { - await this.mergeEditor.open({ - ancestor: { - uri: URI.parse(metadata.ancestor), - textModel: ancestorRef.instance.getMonacoModel(), - }, - input1: input1Data.setTextModel(input1Ref.instance.getMonacoModel()), - input2: input2Data.setTextModel(input2Ref.instance.getMonacoModel()), - output: { - uri: URI.parse(metadata.output), - textModel: outputRef.instance.getMonacoModel(), - }, - }); - }); - } else { - return; // other type not handled + private async displayResourceComponent(resource: IResource, options: IResourceOpenOptions) { + if (options.revealRangeInCenter === undefined) { + options.revealRangeInCenter = true; + } + + const _resource = resource; + const result = await this.resolveOpenType(resource, options); + if (result) { + const { activeOpenType, openTypes } = result; + this.availableOpenTypes = openTypes; + + if (options.preserveFocus) { + options.focus = false; + } + + switch (activeOpenType.type) { + case EditorOpenType.code: + await this.openCodeEditor(resource, options); + break; + case EditorOpenType.diff: + await this.openDiffEditor(resource, options); + break; + case EditorOpenType.mergeEditor: + await this.openMergeEditor(resource); + break; + case EditorOpenType.component: + await this.openCustomEditor(resource, activeOpenType.componentId); + break; + default: + return; } this.resolveTabChanged(_resource, this.currentResource); @@ -1658,9 +1718,9 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { this.notifyBodyChanged(); if ( - (this._codeEditorPendingLayout && activeOpenType.type === 'code') || - (this._diffEditorPendingLayout && activeOpenType.type === 'diff') || - (this._mergeEditorPendingLayout && activeOpenType.type === 'mergeEditor') + (!this._codeEditorPendingLayout && activeOpenType.type === EditorOpenType.code) || + (!this._diffEditorPendingLayout && activeOpenType.type === EditorOpenType.diff) || + (!this._mergeEditorPendingLayout && activeOpenType.type === EditorOpenType.mergeEditor) ) { this.doLayoutEditors(); } @@ -2002,10 +2062,10 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { focus() { this.gainFocus(); - if (this.currentOpenType && this.currentOpenType.type === 'code') { + if (this.currentOpenType && this.currentOpenType.type === EditorOpenType.code) { this.codeEditor.focus(); } - if (this.currentOpenType && this.currentOpenType.type === 'diff') { + if (this.currentOpenType && this.currentOpenType.type === EditorOpenType.diff) { this.diffEditor.focus(); } } @@ -2035,15 +2095,15 @@ export class EditorGroup extends WithEventBus implements IGridEditorGroup { } isCodeEditorMode() { - return !!this.currentOpenType && this.currentOpenType.type === 'code'; + return !!this.currentOpenType && this.currentOpenType.type === EditorOpenType.code; } isDiffEditorMode() { - return !!this.currentOpenType && this.currentOpenType.type === 'diff'; + return !!this.currentOpenType && this.currentOpenType.type === EditorOpenType.diff; } isComponentMode() { - return !!this.currentOpenType && this.currentOpenType.type === 'component'; + return !!this.currentOpenType && this.currentOpenType.type === EditorOpenType.component; } async restoreState(state: IEditorGroupState) { @@ -2227,5 +2287,5 @@ function findSuitableOpenType( } function openTypeSimilar(a: IEditorOpenType, b: IEditorOpenType) { - return a.type === b.type && (a.type !== 'component' || a.componentId === b.componentId); + return a.type === b.type && (a.type !== EditorOpenType.component || a.componentId === b.componentId); } diff --git a/packages/editor/src/common/editor.ts b/packages/editor/src/common/editor.ts index db60035852..0821877912 100644 --- a/packages/editor/src/common/editor.ts +++ b/packages/editor/src/common/editor.ts @@ -668,9 +668,16 @@ export enum IEditorPriority { default = 'default', } +export enum EditorOpenType { + code = 'code', + diff = 'diff', + mergeEditor = 'mergeEditor', + component = 'component', +} + // 定义一个resource如何被打开 export interface IEditorOpenType { - type: 'code' | 'diff' | 'mergeEditor' | 'component'; + type: EditorOpenType; componentId?: string; diff --git a/packages/electron-basic/src/browser/welcome/contribution.ts b/packages/electron-basic/src/browser/welcome/contribution.ts index b43cf12df5..f6b24667f6 100644 --- a/packages/electron-basic/src/browser/welcome/contribution.ts +++ b/packages/electron-basic/src/browser/welcome/contribution.ts @@ -5,6 +5,7 @@ import { BrowserEditorContribution, EditorComponentRegistry, EditorComponentRenderMode, + EditorOpenType, } from '@opensumi/ide-editor/lib/browser'; import { IWorkspaceService } from '@opensumi/ide-workspace'; @@ -31,7 +32,7 @@ export class WelcomeContribution implements BrowserEditorContribution, ClientApp }); registry.registerEditorComponentResolver('welcome', (resource, results) => { results.push({ - type: 'component', + type: EditorOpenType.component, componentId: 'welcome', }); }); diff --git a/packages/extension-manager/src/browser/vsx-extension.contribution.ts b/packages/extension-manager/src/browser/vsx-extension.contribution.ts index bd601e61ff..0b2ac40869 100644 --- a/packages/extension-manager/src/browser/vsx-extension.contribution.ts +++ b/packages/extension-manager/src/browser/vsx-extension.contribution.ts @@ -4,6 +4,7 @@ import { Domain, localize, replaceLocalizePlaceholder, URI } from '@opensumi/ide import { BrowserEditorContribution, EditorComponentRegistry, + EditorOpenType, IResource, ResourceService, } from '@opensumi/ide-editor/lib/browser'; @@ -81,7 +82,7 @@ export class VSXExtensionContribution editorComponentRegistry.registerEditorComponentResolver(EXTENSION_SCHEME, (_, __, resolve) => { resolve?.([ { - type: 'component', + type: EditorOpenType.component, componentId: EXTENSIONS_DETAIL_COMPONENT_ID, }, ]); diff --git a/packages/extension/__tests__/browser/main.thread.editor.test.ts b/packages/extension/__tests__/browser/main.thread.editor.test.ts index 86e8f37f9e..7016e27d8c 100644 --- a/packages/extension/__tests__/browser/main.thread.editor.test.ts +++ b/packages/extension/__tests__/browser/main.thread.editor.test.ts @@ -38,7 +38,7 @@ import { BaseFileSystemEditorDocumentProvider } from '@opensumi/ide-editor/lib/b import { FileSystemResourceProvider } from '@opensumi/ide-editor/lib/browser/fs-resource/fs-resource'; import { LanguageService } from '@opensumi/ide-editor/lib/browser/language/language.service'; import { ResourceServiceImpl } from '@opensumi/ide-editor/lib/browser/resource.service'; -import { EditorComponentRegistry } from '@opensumi/ide-editor/lib/browser/types'; +import { EditorComponentRegistry, EditorOpenType } from '@opensumi/ide-editor/lib/browser/types'; import { EditorGroupChangeEvent, EditorVisibleChangeEvent, @@ -293,9 +293,9 @@ describe('MainThreadEditor Test Suites', () => { const ref = await editorDocModelService.createModelReference( URI.file(path.join(__dirname, 'main.thread.output.test.ts')), ); - await group.codeEditor.open(ref); + group.codeEditor.open(ref); const openType: IEditorOpenType = { - type: 'code', + type: EditorOpenType.code, componentId: 'test-v-component', title: 'test-file', }; diff --git a/packages/extension/src/browser/extension.contribution.ts b/packages/extension/src/browser/extension.contribution.ts index bfb5db6549..546188d6d0 100644 --- a/packages/extension/src/browser/extension.contribution.ts +++ b/packages/extension/src/browser/extension.contribution.ts @@ -36,7 +36,7 @@ import { StatusBarEntryAccessor, } from '@opensumi/ide-core-browser/lib/services/status-bar-service'; import { IResourceOpenOptions, WorkbenchEditorService } from '@opensumi/ide-editor'; -import { IEditorOpenType } from '@opensumi/ide-editor/lib/common/editor'; +import { EditorOpenType, IEditorOpenType } from '@opensumi/ide-editor/lib/common/editor'; import { IWindowDialogService } from '@opensumi/ide-overlay'; import { IWebviewService } from '@opensumi/ide-webview'; @@ -348,7 +348,7 @@ export class ExtensionCommandContribution implements CommandContribution { id === 'default' ? undefined : { - type: 'component', + type: EditorOpenType.component, componentId: `${CUSTOM_EDITOR_SCHEME}-${id}`, }; return this.doOpenWith(uri, columnAndOptions, undefined, openType); diff --git a/packages/extension/src/browser/sumi-browser/contribution/editor.ts b/packages/extension/src/browser/sumi-browser/contribution/editor.ts index ad2e693360..0bbf1f60fd 100644 --- a/packages/extension/src/browser/sumi-browser/contribution/editor.ts +++ b/packages/extension/src/browser/sumi-browser/contribution/editor.ts @@ -1,7 +1,7 @@ import { Injectable, Autowired } from '@opensumi/di'; import { IDisposable, Disposable, URI, Schemes } from '@opensumi/ide-core-common'; import { ResourceService } from '@opensumi/ide-editor'; -import { EditorComponentRegistry } from '@opensumi/ide-editor/lib/browser'; +import { EditorComponentRegistry, EditorOpenType } from '@opensumi/ide-editor/lib/browser'; import { IMainLayoutService } from '@opensumi/ide-main-layout'; import { IIconService, IconType } from '@opensumi/ide-theme'; @@ -76,7 +76,7 @@ export class EditorBrowserContributionRunner extends AbstractSumiBrowserContribu } if (shouldShow) { results.push({ - type: 'component', + type: EditorOpenType.component, componentId: viewContribution.id, title: viewContribution.title || '预览', weight: viewContribution.priority || 10, @@ -93,7 +93,7 @@ export class EditorBrowserContributionRunner extends AbstractSumiBrowserContribu } } results.push({ - type: 'component', + type: EditorOpenType.component, componentId: viewContribution.id, title: viewContribution.title || viewContribution.id, weight: viewContribution.priority || 10, diff --git a/packages/extension/src/browser/vscode/api/main.thread.doc.ts b/packages/extension/src/browser/vscode/api/main.thread.doc.ts index 7e6e790ac1..5b36302693 100644 --- a/packages/extension/src/browser/vscode/api/main.thread.doc.ts +++ b/packages/extension/src/browser/vscode/api/main.thread.doc.ts @@ -27,6 +27,7 @@ import { IEditorDocumentModelContentProvider, EditorDocumentModelOptionChangedEvent, EditorDocumentModelWillSaveEvent, + EditorOpenType, } from '@opensumi/ide-editor/lib/browser'; import { UntitledDocumentIdCounter } from '@opensumi/ide-editor/lib/browser/untitled-resource'; import { IFileServiceClient } from '@opensumi/ide-file-service'; @@ -288,7 +289,7 @@ export class MainThreadExtensionDocumentData extends WithEventBus implements IMa return; } results.push({ - type: 'code', + type: EditorOpenType.code, readonly: true, }); }), diff --git a/packages/extension/src/browser/vscode/api/main.thread.editor.ts b/packages/extension/src/browser/vscode/api/main.thread.editor.ts index 53257c9dbd..d0140e5a4b 100644 --- a/packages/extension/src/browser/vscode/api/main.thread.editor.ts +++ b/packages/extension/src/browser/vscode/api/main.thread.editor.ts @@ -24,6 +24,7 @@ import { EditorConfigurationChangedEvent, EditorGroupIndexChangedEvent, IDiffResource, + EditorOpenType, } from '@opensumi/ide-editor/lib/browser'; import { IMonacoImplEditor, @@ -202,14 +203,14 @@ export class MainThreadEditorService extends WithEventBus implements IMainThread return group.currentEditor as IMonacoImplEditor; } if ( - group.currentOpenType?.type === 'diff' && + group.currentOpenType?.type === EditorOpenType.diff && id === getTextEditorId(group, (currentResource as IDiffResource).metadata!.original, 'original') ) { return group.diffEditor.originalEditor; } if ( - group.currentOpenType?.type === 'diff' && + group.currentOpenType?.type === EditorOpenType.diff && id === getTextEditorId(group, (currentResource as IDiffResource).metadata!.modified, 'modified') ) { return group.diffEditor.modifiedEditor; @@ -232,7 +233,10 @@ export class MainThreadEditorService extends WithEventBus implements IMainThread !openTypeEquals(payload.newOpenType, payload.oldOpenType) ) { const change: IEditorChangeDTO = {}; - if (payload.newOpenType && (payload.newOpenType.type === 'code' || payload.newOpenType.type === 'diff')) { + if ( + payload.newOpenType && + (payload.newOpenType.type === EditorOpenType.code || payload.newOpenType.type === EditorOpenType.diff) + ) { const editor = payload.group.currentEditor as IMonacoImplEditor; if (!editor.currentDocumentModel) { // noop @@ -240,7 +244,7 @@ export class MainThreadEditorService extends WithEventBus implements IMainThread // noop } else { change.created = []; - if (payload.newOpenType.type === 'diff') { + if (payload.newOpenType.type === EditorOpenType.diff) { const diffOriginalEditor = payload.group.diffEditor.originalEditor; const diffMorifidedEditor = payload.group.diffEditor.modifiedEditor; @@ -291,9 +295,12 @@ export class MainThreadEditorService extends WithEventBus implements IMainThread change.actived = getTextEditorId(payload.group, payload.newResource!.uri); } } - if (payload.oldOpenType && (payload.oldOpenType.type === 'code' || payload.oldOpenType.type === 'diff')) { + if ( + payload.oldOpenType && + (payload.oldOpenType.type === EditorOpenType.code || payload.oldOpenType.type === EditorOpenType.diff) + ) { change.removed = []; - if (payload.oldOpenType.type === 'diff') { + if (payload.oldOpenType.type === EditorOpenType.diff) { change.removed.push( getTextEditorId(payload.group, (payload.oldResource as IDiffResource).metadata!.original, 'original'), ); @@ -320,11 +327,11 @@ export class MainThreadEditorService extends WithEventBus implements IMainThread let side: string | undefined; const isDiffOriginal = - this.editorService.currentEditorGroup.currentOpenType?.type === 'diff' && + this.editorService.currentEditorGroup.currentOpenType?.type === EditorOpenType.diff && this.editorService.currentEditorGroup.diffEditor.originalEditor.currentUri?.isEqual(uri); const isDiffMorified = - this.editorService.currentEditorGroup.currentOpenType?.type === 'diff' && + this.editorService.currentEditorGroup.currentOpenType?.type === EditorOpenType.diff && this.editorService.currentEditorGroup.diffEditor.modifiedEditor.currentUri?.isEqual(uri); if (isDiffOriginal) { @@ -465,7 +472,7 @@ export class MainThreadEditorService extends WithEventBus implements IMainThread } async $openResource(uri: string, options: IResourceOpenOptions): Promise { - options.forceOpenType = { type: 'code' }; + options.forceOpenType = { type: EditorOpenType.code }; options.focus = true; options = { ...options, @@ -543,22 +550,24 @@ export class MainThreadEditorService extends WithEventBus implements IMainThread if (!diffChanges) { return Promise.resolve([]); } - return Promise.resolve(diffChanges.map((change) => [ - change.originalStartLineNumber, - change.originalEndLineNumber, - change.modifiedStartLineNumber, - change.modifiedEndLineNumber, - change.charChanges?.map((charChange) => ([ - charChange.originalStartLineNumber, - charChange.originalStartColumn, - charChange.originalEndLineNumber, - charChange.originalEndColumn, - charChange.modifiedStartLineNumber, - charChange.modifiedStartColumn, - charChange.modifiedEndLineNumber, - charChange.modifiedEndColumn, - ])), - ])); + return Promise.resolve( + diffChanges.map((change) => [ + change.originalStartLineNumber, + change.originalEndLineNumber, + change.modifiedStartLineNumber, + change.modifiedEndLineNumber, + change.charChanges?.map((charChange) => [ + charChange.originalStartLineNumber, + charChange.originalStartColumn, + charChange.originalEndLineNumber, + charChange.originalEndColumn, + charChange.modifiedStartLineNumber, + charChange.modifiedStartColumn, + charChange.modifiedEndLineNumber, + charChange.modifiedEndColumn, + ]), + ]), + ); } const dirtyDiffContribution = codeEditor.getContribution('editor.contrib.dirtydiff'); @@ -636,7 +645,7 @@ function isEditor(openType: MaybeNull): boolean { if (!openType) { return false; } - return openType.type === 'code' || openType.type === 'diff'; + return openType.type === EditorOpenType.code || openType.type === EditorOpenType.diff; } function isGroupEditorState(group: IEditorGroup) { diff --git a/packages/extension/src/browser/vscode/contributes/customEditors.tsx b/packages/extension/src/browser/vscode/contributes/customEditors.tsx index c2808f87d3..e055a1ac45 100644 --- a/packages/extension/src/browser/vscode/contributes/customEditors.tsx +++ b/packages/extension/src/browser/vscode/contributes/customEditors.tsx @@ -10,7 +10,12 @@ import { ILogger, match, } from '@opensumi/ide-core-common'; -import { EditorComponentRegistry, IEditorPriority, ReactEditorComponent } from '@opensumi/ide-editor/lib/browser'; +import { + EditorComponentRegistry, + EditorOpenType, + IEditorPriority, + ReactEditorComponent, +} from '@opensumi/ide-editor/lib/browser'; import { IWebviewService } from '@opensumi/ide-webview'; import { WebviewMounter } from '@opensumi/ide-webview/lib/browser/editor-webview'; @@ -94,7 +99,7 @@ export class CustomEditorContributionPoint extends VSCodeContributePoint { resolve([ { - type: 'component', + type: EditorOpenType.component, componentId: this.toComponentId(description.id), }, ]); diff --git a/packages/file-scheme/__tests__/browser/contribution.test.ts b/packages/file-scheme/__tests__/browser/contribution.test.ts index 39dd9db177..d3b7a22b5f 100644 --- a/packages/file-scheme/__tests__/browser/contribution.test.ts +++ b/packages/file-scheme/__tests__/browser/contribution.test.ts @@ -2,6 +2,7 @@ import { PreferenceService, URI } from '@opensumi/ide-core-browser'; import { BrowserEditorContribution, EditorComponentRegistry, + EditorOpenType, IEditorOpenType, IResource, } from '@opensumi/ide-editor/lib/browser'; @@ -67,20 +68,20 @@ describe('contribution test', () => { // plain text let openTypes: IEditorOpenType[]; openTypes = await registry.resolveEditorComponent(createMockResource('file:///foo/1.txt')); - expect(openTypes[0].type).toBe('code'); + expect(openTypes[0].type).toBe(EditorOpenType.code); // known custom language openTypes = await registry.resolveEditorComponent(createMockResource('file:///foo/1.js')); - expect(openTypes[0].type).toBe('code'); + expect(openTypes[0].type).toBe(EditorOpenType.code); // unknown language but with text type mockFileService.getFileType.mockReturnValueOnce('text'); openTypes = await registry.resolveEditorComponent(createMockResource('file:///foo/1.rs')); - expect(openTypes[0].type).toBe('code'); + expect(openTypes[0].type).toBe(EditorOpenType.code); }); it('should fallback to LARGE_FILE_PREVENT_COMPONENT_ID if file is too large', async () => { mockFileService.getFileStat.mockReturnValueOnce({ size: 4 * 1024 * 1024 * 1024 + 1 }); const openTypes = await registry.resolveEditorComponent(createMockResource('file:///foo/2.js')); - expect(openTypes[0].type).toBe('component'); + expect(openTypes[0].type).toBe(EditorOpenType.component); expect(openTypes[0].componentId).toBe('large-file-prevent'); }); @@ -88,10 +89,10 @@ describe('contribution test', () => { mockFileService.getFileType.mockReturnValueOnce('video').mockReturnValueOnce('image'); let openTypes: IEditorOpenType[]; openTypes = await registry.resolveEditorComponent(createMockResource('file:///foo/video.mp4')); - expect(openTypes[0].type).toBe('component'); + expect(openTypes[0].type).toBe(EditorOpenType.component); expect(openTypes[0].componentId).toBe('video-preview'); openTypes = await registry.resolveEditorComponent(createMockResource('file:///foo/image.jpg')); - expect(openTypes[0].type).toBe('component'); + expect(openTypes[0].type).toBe(EditorOpenType.component); expect(openTypes[0].componentId).toBe('image-preview'); }); }); diff --git a/packages/file-scheme/src/browser/file-scheme.contribution.ts b/packages/file-scheme/src/browser/file-scheme.contribution.ts index 882abb0688..b256fab67e 100644 --- a/packages/file-scheme/src/browser/file-scheme.contribution.ts +++ b/packages/file-scheme/src/browser/file-scheme.contribution.ts @@ -6,6 +6,7 @@ import { EditorComponentRegistry, BrowserEditorContribution, IEditorDocumentModelContentRegistry, + EditorOpenType, } from '@opensumi/ide-editor/lib/browser'; import { UntitledSchemeResourceProvider, @@ -107,7 +108,7 @@ export class FileSystemEditorComponentContribution implements BrowserEditorContr (resource: IResource, results: IEditorOpenType[]) => { if (results.length === 0) { results.push({ - type: 'component', + type: EditorOpenType.component, componentId: EXTERNAL_OPEN_COMPONENT_ID, }); } @@ -122,14 +123,14 @@ export class FileSystemEditorComponentContribution implements BrowserEditorContr if (type === 'image') { results.push({ - type: 'component', + type: EditorOpenType.component, componentId: IMAGE_PREVIEW_COMPONENT_ID, }); } if (type === 'video') { results.push({ - type: 'component', + type: EditorOpenType.component, componentId: VIDEO_PREVIEW_COMPONENT_ID, }); } @@ -141,12 +142,12 @@ export class FileSystemEditorComponentContribution implements BrowserEditorContr if (stat && (stat.size || 0) > maxSize && !(metadata || {}).noPrevent) { results.push({ - type: 'component', + type: EditorOpenType.component, componentId: LARGE_FILE_PREVENT_COMPONENT_ID, }); } else { results.push({ - type: 'code', + type: EditorOpenType.code, title: localize('editorOpenType.code'), }); } @@ -160,7 +161,7 @@ export class FileSystemEditorComponentContribution implements BrowserEditorContr (_resource: IResource, _results: IEditorOpenType[], resolve: (results: IEditorOpenType[]) => void) => { resolve([ { - type: 'code', + type: EditorOpenType.code, priority: 'default', }, ]); diff --git a/packages/file-tree-next/src/browser/file-tree-contribution.ts b/packages/file-tree-next/src/browser/file-tree-contribution.ts index 1218656327..1ed41b1df7 100644 --- a/packages/file-tree-next/src/browser/file-tree-contribution.ts +++ b/packages/file-tree-next/src/browser/file-tree-contribution.ts @@ -44,7 +44,7 @@ import { import { IProgressService } from '@opensumi/ide-core-browser/lib/progress'; import { Domain } from '@opensumi/ide-core-common/lib/di-helper'; import { IDecorationsService } from '@opensumi/ide-decoration'; -import { IEditorOpenType, WorkbenchEditorService } from '@opensumi/ide-editor'; +import { EditorOpenType, IEditorOpenType, WorkbenchEditorService } from '@opensumi/ide-editor'; import { EXPLORER_CONTAINER_ID } from '@opensumi/ide-explorer/lib/browser/explorer-contribution'; import { IMainLayoutService, IViewsRegistry, MainLayoutContribution } from '@opensumi/ide-main-layout'; import { ViewContentGroups } from '@opensumi/ide-main-layout/lib/browser/views-registry'; @@ -598,10 +598,10 @@ export class FileTreeContribution const items: QuickOpenItem[] = []; const compareType = (o: IEditorOpenType, t: IEditorOpenType) => { - if (t.type === 'code') { - return o.type === 'code'; + if (t.type === EditorOpenType.code) { + return o.type === EditorOpenType.code; } - if (t.type === 'component' && o.type === 'component') { + if (t.type === EditorOpenType.component && o.type === EditorOpenType.component) { return o.componentId === t.componentId; } return false; diff --git a/packages/keymaps/src/browser/keymaps.contribution.ts b/packages/keymaps/src/browser/keymaps.contribution.ts index 800a89f6e6..e37bff2068 100644 --- a/packages/keymaps/src/browser/keymaps.contribution.ts +++ b/packages/keymaps/src/browser/keymaps.contribution.ts @@ -21,7 +21,7 @@ import { } from '@opensumi/ide-core-browser'; import { MenuContribution, IMenuRegistry, MenuId } from '@opensumi/ide-core-browser/lib/menu/next'; import { ResourceService, IResourceProvider, IResource } from '@opensumi/ide-editor'; -import { BrowserEditorContribution, EditorComponentRegistry } from '@opensumi/ide-editor/lib/browser'; +import { BrowserEditorContribution, EditorComponentRegistry, EditorOpenType } from '@opensumi/ide-editor/lib/browser'; import { IFileServiceClient } from '@opensumi/ide-file-service/lib/common'; import { QuickPickItem, QuickPickService } from '@opensumi/ide-quick-open'; @@ -163,7 +163,7 @@ export class KeymapsContribution editorComponentRegistry.registerEditorComponentResolver(KEYMAPS_SCHEME, (_, __, resolve) => { resolve!([ { - type: 'component', + type: EditorOpenType.component, componentId: KEYMAPS_PREVIEW_COMPONENT_ID, }, ]); diff --git a/packages/markdown/src/browser/contribution.ts b/packages/markdown/src/browser/contribution.ts index da681de90b..465f4bf385 100644 --- a/packages/markdown/src/browser/contribution.ts +++ b/packages/markdown/src/browser/contribution.ts @@ -1,7 +1,7 @@ import { Autowired } from '@opensumi/di'; import { PreferenceService } from '@opensumi/ide-core-browser'; import { Domain, localize, Schemes } from '@opensumi/ide-core-common'; -import { BrowserEditorContribution, EditorComponentRegistry } from '@opensumi/ide-editor/lib/browser'; +import { BrowserEditorContribution, EditorComponentRegistry, EditorOpenType } from '@opensumi/ide-editor/lib/browser'; import { IMarkdownService } from '../common'; @@ -27,7 +27,7 @@ export class EmbeddedMarkdownEditorContribution implements BrowserEditorContribu componentRegistry.registerEditorComponentResolver(Schemes.file, (resource, results) => { if (resource.uri.path.ext === '.md') { results.push({ - type: 'component', + type: EditorOpenType.component, componentId: MARKDOWN_EDITOR_COMPONENT_ID, title: localize('editorOpenType.preview'), weight: this.preferenceService.get('application.preferMarkdownPreview') ? 10 : -1, diff --git a/packages/preferences/src/browser/preference-contribution.ts b/packages/preferences/src/browser/preference-contribution.ts index 806f0be2ff..da2a033ccb 100644 --- a/packages/preferences/src/browser/preference-contribution.ts +++ b/packages/preferences/src/browser/preference-contribution.ts @@ -36,6 +36,7 @@ import { ResourceService, IResourceProvider, IResource } from '@opensumi/ide-edi import { BrowserEditorContribution, EditorComponentRegistry, + EditorOpenType, IEditor, IEditorFeatureRegistry, IResourceOpenResult, @@ -416,7 +417,7 @@ export class PreferenceContribution editorComponentRegistry.registerEditorComponentResolver(PREF_SCHEME, (_, __, resolve) => { resolve([ { - type: 'component', + type: EditorOpenType.component, componentId: PREF_PREVIEW_COMPONENT_ID, }, ]); diff --git a/packages/scm/src/browser/dirty-diff/index.ts b/packages/scm/src/browser/dirty-diff/index.ts index b18b603165..970110ff15 100644 --- a/packages/scm/src/browser/dirty-diff/index.ts +++ b/packages/scm/src/browser/dirty-diff/index.ts @@ -8,7 +8,7 @@ import { } from '@opensumi/ide-core-browser'; import { IEventBus, CommandService, positionToRange } from '@opensumi/ide-core-common'; import { WorkbenchEditorService } from '@opensumi/ide-editor'; -import { EditorGroupChangeEvent, IEditorFeatureRegistry } from '@opensumi/ide-editor/lib/browser'; +import { EditorGroupChangeEvent, EditorOpenType, IEditorFeatureRegistry } from '@opensumi/ide-editor/lib/browser'; import { IEditorDocumentModel } from '@opensumi/ide-editor/lib/browser'; import { IMonacoImplEditor } from '@opensumi/ide-editor/lib/browser/editor-collection.service'; import type { ICodeEditor as IMonacoCodeEditor, ITextModel } from '@opensumi/ide-monaco/lib/browser/monaco-api/types'; @@ -158,7 +158,7 @@ export class DirtyDiffWorkbenchController extends Disposable implements IDirtyDi const models = this.editorService.editorGroups // only interested in code editor widgets - .filter((editorGroup) => editorGroup.currentOpenType && editorGroup.currentOpenType.type === 'code') + .filter((editorGroup) => editorGroup.currentOpenType && editorGroup.currentOpenType.type === EditorOpenType.code) // set model registry and map to models .map((editorGroup) => { const currentEditor = editorGroup.currentEditor as IMonacoImplEditor; diff --git a/packages/testing/src/browser/testing.contribution.ts b/packages/testing/src/browser/testing.contribution.ts index 6324b624f3..2ad735743a 100644 --- a/packages/testing/src/browser/testing.contribution.ts +++ b/packages/testing/src/browser/testing.contribution.ts @@ -30,6 +30,7 @@ import { EditorComponentRegistry, ResourceService, IResource, + EditorOpenType, } from '@opensumi/ide-editor/lib/browser'; import { IEditor } from '@opensumi/ide-editor/lib/common'; import { IFileServiceClient } from '@opensumi/ide-file-service'; @@ -450,7 +451,7 @@ export class TestingContribution componentRegistry.registerEditorComponentResolver(TEST_DATA_SCHEME, (_, results) => { results.push({ - type: 'component', + type: EditorOpenType.component, componentId: MARKDOWN_EDITOR_COMPONENT_ID, weight: 10, }); diff --git a/packages/webview/src/browser/webview.service.ts b/packages/webview/src/browser/webview.service.ts index f584ea3bb0..4ea7924357 100644 --- a/packages/webview/src/browser/webview.service.ts +++ b/packages/webview/src/browser/webview.service.ts @@ -20,6 +20,7 @@ import { EditorComponentRenderMode, EditorPreferences, EditorGroupChangeEvent, + EditorOpenType, } from '@opensumi/ide-editor/lib/browser'; import { LIGHT, DARK, HIGH_CONTRAST_DARK, HIGH_CONTRAST_LIGHT, ITheme } from '@opensumi/ide-theme'; import { getColorRegistry } from '@opensumi/ide-theme/lib/common/color-registry'; @@ -431,7 +432,7 @@ export class EditorWebviewComponent (resource, results) => { if (resource.uri.path.toString() === this.id) { results.push({ - type: 'component', + type: EditorOpenType.component, componentId, }); } diff --git a/tools/playwright/src/tests/editor.test.ts b/tools/playwright/src/tests/editor.test.ts index 20281932d4..c9664f4078 100644 --- a/tools/playwright/src/tests/editor.test.ts +++ b/tools/playwright/src/tests/editor.test.ts @@ -95,14 +95,12 @@ console.log(a);`, await copyPath?.click(); editor = await app.openEditor(OpenSumiTextEditor, explorer, 'editor3.js'); await editor.addTextToNewLineAfterLineByLineNumber(1, 'File Path: '); - // cause of https://github.com/microsoft/playwright/issues/8114 - // we can just using keypress to fake the paste feature let editorMenu = await editor.openLineContextMenuByLineNumber(2); expect(await editorMenu?.isOpen()).toBeTruthy(); let paste = await editorMenu?.menuItemByName('Paste'); await paste?.click(); await app.page.waitForTimeout(200); - expect(await editor.numberOfLines()).toBe(5); + expect(await editor.numberOfLines()).toBe(2); expect( await editor.textContentOfLineContainingText( `File Path: ${workspace.workspace.resolve('editor3.js').codeUri.fsPath.toString()}`, @@ -118,7 +116,7 @@ console.log(a);`, paste = await editorMenu?.menuItemByName('Paste'); await paste?.click(); await app.page.waitForTimeout(200); - expect(await editor.numberOfLines()).toBe(6); + expect(await editor.numberOfLines()).toBe(3); expect(await editor.textContentOfLineContainingText('File Relative Path: editor3.js')).toBeTruthy(); }); diff --git a/tools/playwright/src/text-editor.ts b/tools/playwright/src/text-editor.ts index 7479886762..0762e1db2c 100644 --- a/tools/playwright/src/text-editor.ts +++ b/tools/playwright/src/text-editor.ts @@ -220,7 +220,6 @@ export class OpenSumiTextEditor extends OpenSumiEditor { if (!lineNode) { throw new Error(`Couldn't retrieve lines of text editor ${this.tabSelector}`); } - return lineNode.asElement(); }