@theia/plugin-ext 1.77.0-next.7 → 1.77.0-next.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/character-classifier.js.map +1 -1
- package/lib/common/plugin-api-rpc.d.ts +2 -0
- package/lib/common/plugin-api-rpc.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc.js.map +1 -1
- package/lib/common/plugin-protocol.d.ts +9 -0
- package/lib/common/plugin-protocol.d.ts.map +1 -1
- package/lib/common/plugin-protocol.js +19 -1
- package/lib/common/plugin-protocol.js.map +1 -1
- package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
- package/lib/hosted/browser/hosted-plugin.js +4 -2
- package/lib/hosted/browser/hosted-plugin.js.map +1 -1
- package/lib/hosted/browser/hosted-plugin.spec.d.ts +2 -0
- package/lib/hosted/browser/hosted-plugin.spec.d.ts.map +1 -0
- package/lib/hosted/browser/hosted-plugin.spec.js +59 -0
- package/lib/hosted/browser/hosted-plugin.spec.js.map +1 -0
- package/lib/hosted/browser/worker/worker-main.js +2 -1
- package/lib/hosted/browser/worker/worker-main.js.map +1 -1
- package/lib/hosted/browser-only/browser-only-plugin-paths-service.js +1 -1
- package/lib/hosted/browser-only/browser-only-plugin-paths-service.js.map +1 -1
- package/lib/hosted/browser-only/browser-only-plugin-paths-service.spec.js +2 -1
- package/lib/hosted/browser-only/browser-only-plugin-paths-service.spec.js.map +1 -1
- package/lib/hosted/node/hosted-plugin-localization-service.js +2 -2
- package/lib/hosted/node/hosted-plugin-localization-service.js.map +1 -1
- package/lib/hosted/node/hosted-plugin-process.js +1 -1
- package/lib/hosted/node/hosted-plugin-process.js.map +1 -1
- package/lib/hosted/node/plugin-deployer-handler-impl.js +1 -1
- package/lib/hosted/node/plugin-deployer-handler-impl.js.map +1 -1
- package/lib/hosted/node/plugin-ext-hosted-backend-module.js +2 -1
- package/lib/hosted/node/plugin-ext-hosted-backend-module.js.map +1 -1
- package/lib/hosted/node/plugin-host-proxy.d.ts.map +1 -1
- package/lib/hosted/node/plugin-host-proxy.js +10 -6
- package/lib/hosted/node/plugin-host-proxy.js.map +1 -1
- package/lib/hosted/node/plugin-host-rpc.js +1 -1
- package/lib/hosted/node/plugin-host-rpc.js.map +1 -1
- package/lib/hosted/node/plugin-host.js +2 -1
- package/lib/hosted/node/plugin-host.js.map +1 -1
- package/lib/hosted/node/plugin-reader.js +6 -6
- package/lib/hosted/node/plugin-reader.js.map +1 -1
- package/lib/hosted/node/plugin-reader.spec.js +4 -3
- package/lib/hosted/node/plugin-reader.spec.js.map +1 -1
- package/lib/hosted/node/plugin-require-override.d.ts.map +1 -1
- package/lib/hosted/node/plugin-require-override.js +3 -1
- package/lib/hosted/node/plugin-require-override.js.map +1 -1
- package/lib/hosted/node/plugin-require-override.spec.d.ts +2 -0
- package/lib/hosted/node/plugin-require-override.spec.d.ts.map +1 -0
- package/lib/hosted/node/plugin-require-override.spec.js +40 -0
- package/lib/hosted/node/plugin-require-override.spec.js.map +1 -0
- package/lib/hosted/node/scanners/file-plugin-uri-factory.js +1 -1
- package/lib/hosted/node/scanners/file-plugin-uri-factory.js.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.js +2 -2
- package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.spec.js +5 -4
- package/lib/hosted/node/scanners/scanner-theia.spec.js.map +1 -1
- package/lib/hosted/node-electron/scanner-theia-electron.js +1 -1
- package/lib/hosted/node-electron/scanner-theia-electron.js.map +1 -1
- package/lib/main/browser/commands.js +1 -1
- package/lib/main/browser/commands.js.map +1 -1
- package/lib/main/browser/comments/comment-thread-widget.js +3 -2
- package/lib/main/browser/comments/comment-thread-widget.js.map +1 -1
- package/lib/main/browser/comments/comments-contribution.js +1 -1
- package/lib/main/browser/comments/comments-contribution.js.map +1 -1
- package/lib/main/browser/custom-editors/custom-editor-opener.spec.js +3 -2
- package/lib/main/browser/custom-editors/custom-editor-opener.spec.js.map +1 -1
- package/lib/main/browser/custom-editors/custom-editor-widget.js +1 -1
- package/lib/main/browser/custom-editors/custom-editor-widget.js.map +1 -1
- package/lib/main/browser/custom-editors/custom-editors-main.js +2 -1
- package/lib/main/browser/custom-editors/custom-editors-main.js.map +1 -1
- package/lib/main/browser/decorations/decorations-main.js +2 -1
- package/lib/main/browser/decorations/decorations-main.js.map +1 -1
- package/lib/main/browser/dialogs-main.js +2 -1
- package/lib/main/browser/dialogs-main.js.map +1 -1
- package/lib/main/browser/documents-main.js +3 -2
- package/lib/main/browser/documents-main.js.map +1 -1
- package/lib/main/browser/file-system-main-impl.js +3 -2
- package/lib/main/browser/file-system-main-impl.js.map +1 -1
- package/lib/main/browser/hierarchy/hierarchy-types-converters.js +3 -2
- package/lib/main/browser/hierarchy/hierarchy-types-converters.js.map +1 -1
- package/lib/main/browser/languages-main.js +3 -3
- package/lib/main/browser/languages-main.js.map +1 -1
- package/lib/main/browser/languages-main.spec.js +2 -1
- package/lib/main/browser/languages-main.spec.js.map +1 -1
- package/lib/main/browser/main-file-system-event-service.d.ts +1 -22
- package/lib/main/browser/main-file-system-event-service.d.ts.map +1 -1
- package/lib/main/browser/main-file-system-event-service.js +2 -48
- package/lib/main/browser/main-file-system-event-service.js.map +1 -1
- package/lib/main/browser/menus/menus-contribution-handler.d.ts.map +1 -1
- package/lib/main/browser/menus/menus-contribution-handler.js +1 -12
- package/lib/main/browser/menus/menus-contribution-handler.js.map +1 -1
- package/lib/main/browser/notebooks/renderers/output-webview-internal.d.ts.map +1 -1
- package/lib/main/browser/notebooks/renderers/output-webview-internal.js +3 -2
- package/lib/main/browser/notebooks/renderers/output-webview-internal.js.map +1 -1
- package/lib/main/browser/plugin-contribution-handler.js +1 -1
- package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
- package/lib/main/browser/plugin-ext-widget.js +1 -1
- package/lib/main/browser/plugin-ext-widget.js.map +1 -1
- package/lib/main/browser/plugin-icon-service.js +1 -1
- package/lib/main/browser/plugin-icon-service.js.map +1 -1
- package/lib/main/browser/plugin-icon-theme-service.d.ts +2 -2
- package/lib/main/browser/plugin-icon-theme-service.d.ts.map +1 -1
- package/lib/main/browser/plugin-icon-theme-service.js +2 -2
- package/lib/main/browser/plugin-icon-theme-service.js.map +1 -1
- package/lib/main/browser/plugin-icon-theme-service.spec.js +2 -1
- package/lib/main/browser/plugin-icon-theme-service.spec.js.map +1 -1
- package/lib/main/browser/plugin-shared-style.js.map +1 -1
- package/lib/main/browser/scm-main.d.ts +3 -1
- package/lib/main/browser/scm-main.d.ts.map +1 -1
- package/lib/main/browser/scm-main.js +6 -3
- package/lib/main/browser/scm-main.js.map +1 -1
- package/lib/main/browser/scm-main.spec.js +31 -0
- package/lib/main/browser/scm-main.spec.js.map +1 -1
- package/lib/main/browser/status-bar-message-registry-main.js +2 -1
- package/lib/main/browser/status-bar-message-registry-main.js.map +1 -1
- package/lib/main/browser/text-editor-main.js +2 -1
- package/lib/main/browser/text-editor-main.js.map +1 -1
- package/lib/main/browser/text-editors-main.js +2 -1
- package/lib/main/browser/text-editors-main.js.map +1 -1
- package/lib/main/browser/view/plugin-tree-view-node-label-provider.js +1 -1
- package/lib/main/browser/view/plugin-tree-view-node-label-provider.js.map +1 -1
- package/lib/main/browser/view/plugin-view-registry.d.ts +17 -2
- package/lib/main/browser/view/plugin-view-registry.d.ts.map +1 -1
- package/lib/main/browser/view/plugin-view-registry.js +72 -21
- package/lib/main/browser/view/plugin-view-registry.js.map +1 -1
- package/lib/main/browser/view/plugin-view-registry.spec.js +188 -9
- package/lib/main/browser/view/plugin-view-registry.spec.js.map +1 -1
- package/lib/main/browser/view/tree-view-decorator-service.js +1 -1
- package/lib/main/browser/view/tree-view-decorator-service.js.map +1 -1
- package/lib/main/browser/view/tree-view-widget.js +2 -2
- package/lib/main/browser/view/tree-view-widget.js.map +1 -1
- package/lib/main/browser/webview/pre/main.spec.d.ts +2 -0
- package/lib/main/browser/webview/pre/main.spec.d.ts.map +1 -0
- package/lib/main/browser/webview/pre/main.spec.js +45 -0
- package/lib/main/browser/webview/pre/main.spec.js.map +1 -0
- package/lib/main/browser/webview/webview-theme-data-provider.d.ts +1 -1
- package/lib/main/browser/webview/webview-theme-data-provider.d.ts.map +1 -1
- package/lib/main/browser/webview/webview.d.ts.map +1 -1
- package/lib/main/browser/webview/webview.js +6 -3
- package/lib/main/browser/webview/webview.js.map +1 -1
- package/lib/main/browser/window-state-main.js +2 -1
- package/lib/main/browser/window-state-main.js.map +1 -1
- package/lib/main/browser/workspace-main.js +1 -1
- package/lib/main/browser/workspace-main.js.map +1 -1
- package/lib/main/common/plugin-theia-environment.js +1 -1
- package/lib/main/common/plugin-theia-environment.js.map +1 -1
- package/lib/main/node/handlers/plugin-theia-directory-handler.js +4 -4
- package/lib/main/node/handlers/plugin-theia-directory-handler.js.map +1 -1
- package/lib/main/node/handlers/plugin-theia-file-handler.js +3 -3
- package/lib/main/node/handlers/plugin-theia-file-handler.js.map +1 -1
- package/lib/main/node/paths/plugin-paths-service.js +4 -4
- package/lib/main/node/paths/plugin-paths-service.js.map +1 -1
- package/lib/main/node/plugin-deployer-directory-handler-context-impl.js +2 -1
- package/lib/main/node/plugin-deployer-directory-handler-context-impl.js.map +1 -1
- package/lib/main/node/plugin-deployer-file-handler-context-impl.js +3 -2
- package/lib/main/node/plugin-deployer-file-handler-context-impl.js.map +1 -1
- package/lib/main/node/plugin-deployer-impl.d.ts.map +1 -1
- package/lib/main/node/plugin-deployer-impl.js +7 -2
- package/lib/main/node/plugin-deployer-impl.js.map +1 -1
- package/lib/main/node/plugin-deployer-impl.spec.d.ts +2 -0
- package/lib/main/node/plugin-deployer-impl.spec.d.ts.map +1 -0
- package/lib/main/node/plugin-deployer-impl.spec.js +66 -0
- package/lib/main/node/plugin-deployer-impl.spec.js.map +1 -0
- package/lib/main/node/plugin-github-resolver.js +1 -1
- package/lib/main/node/plugin-github-resolver.js.map +1 -1
- package/lib/main/node/plugin-http-resolver.js +1 -1
- package/lib/main/node/plugin-http-resolver.js.map +1 -1
- package/lib/main/node/plugin-service.d.ts +1 -1
- package/lib/main/node/plugin-service.d.ts.map +1 -1
- package/lib/main/node/plugin-service.js +4 -4
- package/lib/main/node/plugin-service.js.map +1 -1
- package/lib/main/node/plugins-key-value-storage.js +2 -2
- package/lib/main/node/plugins-key-value-storage.js.map +1 -1
- package/lib/main/node/plugins-key-value-storage.spec.js +2 -1
- package/lib/main/node/plugins-key-value-storage.spec.js.map +1 -1
- package/lib/main/node/resolvers/local-directory-plugin-deployer-resolver.js +2 -2
- package/lib/main/node/resolvers/local-directory-plugin-deployer-resolver.js.map +1 -1
- package/lib/main/node/resolvers/local-directory-plugin-deployer-resolver.spec.js +4 -3
- package/lib/main/node/resolvers/local-directory-plugin-deployer-resolver.spec.js.map +1 -1
- package/lib/main/node/resolvers/local-plugin-deployer-resolver.js +3 -3
- package/lib/main/node/resolvers/local-plugin-deployer-resolver.js.map +1 -1
- package/lib/main/node/temp-dir-util.js +3 -2
- package/lib/main/node/temp-dir-util.js.map +1 -1
- package/lib/plugin/comments.d.ts +1 -1
- package/lib/plugin/comments.d.ts.map +1 -1
- package/lib/plugin/custom-editors.js +2 -1
- package/lib/plugin/custom-editors.js.map +1 -1
- package/lib/plugin/decorations.spec.js +2 -1
- package/lib/plugin/decorations.spec.js.map +1 -1
- package/lib/plugin/document-data.d.ts.map +1 -1
- package/lib/plugin/document-data.js +0 -1
- package/lib/plugin/document-data.js.map +1 -1
- package/lib/plugin/documents.js +2 -1
- package/lib/plugin/documents.js.map +1 -1
- package/lib/plugin/editors-and-documents.js +1 -1
- package/lib/plugin/editors-and-documents.js.map +1 -1
- package/lib/plugin/file-system-event-service-ext-impl.d.ts +1 -1
- package/lib/plugin/file-system-event-service-ext-impl.d.ts.map +1 -1
- package/lib/plugin/file-system-event-service-ext-impl.js +3 -2
- package/lib/plugin/file-system-event-service-ext-impl.js.map +1 -1
- package/lib/plugin/file-system-ext-impl.js +5 -4
- package/lib/plugin/file-system-ext-impl.js.map +1 -1
- package/lib/plugin/file-system-watcher.spec.js +2 -1
- package/lib/plugin/file-system-watcher.spec.js.map +1 -1
- package/lib/plugin/known-commands.js +5 -5
- package/lib/plugin/known-commands.js.map +1 -1
- package/lib/plugin/known-commands.spec.js +2 -1
- package/lib/plugin/known-commands.spec.js.map +1 -1
- package/lib/plugin/languages/call-hierarchy.js +2 -1
- package/lib/plugin/languages/call-hierarchy.js.map +1 -1
- package/lib/plugin/languages/code-action.js +2 -1
- package/lib/plugin/languages/code-action.js.map +1 -1
- package/lib/plugin/languages/color.js +2 -1
- package/lib/plugin/languages/color.js.map +1 -1
- package/lib/plugin/languages/completion.js +2 -1
- package/lib/plugin/languages/completion.js.map +1 -1
- package/lib/plugin/languages/declaration.js +3 -2
- package/lib/plugin/languages/declaration.js.map +1 -1
- package/lib/plugin/languages/definition.js +3 -2
- package/lib/plugin/languages/definition.js.map +1 -1
- package/lib/plugin/languages/document-drop-edit.js +4 -3
- package/lib/plugin/languages/document-drop-edit.js.map +1 -1
- package/lib/plugin/languages/document-formatting.js +2 -1
- package/lib/plugin/languages/document-formatting.js.map +1 -1
- package/lib/plugin/languages/document-highlight.js +3 -2
- package/lib/plugin/languages/document-highlight.js.map +1 -1
- package/lib/plugin/languages/evaluatable-expression.js +2 -1
- package/lib/plugin/languages/evaluatable-expression.js.map +1 -1
- package/lib/plugin/languages/folding.js +2 -1
- package/lib/plugin/languages/folding.js.map +1 -1
- package/lib/plugin/languages/hover.js +2 -1
- package/lib/plugin/languages/hover.js.map +1 -1
- package/lib/plugin/languages/implementation.js +3 -2
- package/lib/plugin/languages/implementation.js.map +1 -1
- package/lib/plugin/languages/inlay-hints.js +2 -1
- package/lib/plugin/languages/inlay-hints.js.map +1 -1
- package/lib/plugin/languages/inline-completion.js +2 -1
- package/lib/plugin/languages/inline-completion.js.map +1 -1
- package/lib/plugin/languages/inline-values.js +2 -1
- package/lib/plugin/languages/inline-values.js.map +1 -1
- package/lib/plugin/languages/lens.js +2 -1
- package/lib/plugin/languages/lens.js.map +1 -1
- package/lib/plugin/languages/link-provider.js +2 -1
- package/lib/plugin/languages/link-provider.js.map +1 -1
- package/lib/plugin/languages/multi-document-highlight.js +3 -2
- package/lib/plugin/languages/multi-document-highlight.js.map +1 -1
- package/lib/plugin/languages/on-type-formatting.js +2 -1
- package/lib/plugin/languages/on-type-formatting.js.map +1 -1
- package/lib/plugin/languages/outline.js +3 -2
- package/lib/plugin/languages/outline.js.map +1 -1
- package/lib/plugin/languages/range-formatting.js +2 -1
- package/lib/plugin/languages/range-formatting.js.map +1 -1
- package/lib/plugin/languages/reference.js +2 -1
- package/lib/plugin/languages/reference.js.map +1 -1
- package/lib/plugin/languages/rename.js +2 -1
- package/lib/plugin/languages/rename.js.map +1 -1
- package/lib/plugin/languages/selection-range.js +2 -1
- package/lib/plugin/languages/selection-range.js.map +1 -1
- package/lib/plugin/languages/signature.js +2 -1
- package/lib/plugin/languages/signature.js.map +1 -1
- package/lib/plugin/languages/type-definition.js +3 -2
- package/lib/plugin/languages/type-definition.js.map +1 -1
- package/lib/plugin/languages/type-hierarchy.js +2 -1
- package/lib/plugin/languages/type-hierarchy.js.map +1 -1
- package/lib/plugin/languages/util.js +2 -1
- package/lib/plugin/languages/util.js.map +1 -1
- package/lib/plugin/languages/workspace-symbol.js +2 -1
- package/lib/plugin/languages/workspace-symbol.js.map +1 -1
- package/lib/plugin/node/debug/debug.spec.js +2 -1
- package/lib/plugin/node/debug/debug.spec.js.map +1 -1
- package/lib/plugin/node/debug/plugin-node-debug-adapter-creator.js +3 -2
- package/lib/plugin/node/debug/plugin-node-debug-adapter-creator.js.map +1 -1
- package/lib/plugin/node/env-node-ext.js +1 -1
- package/lib/plugin/node/env-node-ext.js.map +1 -1
- package/lib/plugin/notebook/notebook-document.js +3 -2
- package/lib/plugin/notebook/notebook-document.js.map +1 -1
- package/lib/plugin/notebook/notebook-editors.js +2 -1
- package/lib/plugin/notebook/notebook-editors.js.map +1 -1
- package/lib/plugin/notebook/notebooks.js +2 -1
- package/lib/plugin/notebook/notebooks.js.map +1 -1
- package/lib/plugin/path.spec.js +2 -1
- package/lib/plugin/path.spec.js.map +1 -1
- package/lib/plugin/plugin-context.js +1 -1
- package/lib/plugin/plugin-context.js.map +1 -1
- package/lib/plugin/plugin-icon-path.js +2 -1
- package/lib/plugin/plugin-icon-path.js.map +1 -1
- package/lib/plugin/plugin-manager.js +2 -2
- package/lib/plugin/plugin-manager.js.map +1 -1
- package/lib/plugin/preference-registry.spec.js +2 -1
- package/lib/plugin/preference-registry.spec.js.map +1 -1
- package/lib/plugin/quick-open.js +2 -1
- package/lib/plugin/quick-open.js.map +1 -1
- package/lib/plugin/relative-pattern.spec.js +3 -2
- package/lib/plugin/relative-pattern.spec.js.map +1 -1
- package/lib/plugin/scm.d.ts.map +1 -1
- package/lib/plugin/scm.js +14 -1
- package/lib/plugin/scm.js.map +1 -1
- package/lib/plugin/scm.spec.js +56 -1
- package/lib/plugin/scm.spec.js.map +1 -1
- package/lib/plugin/tasks/task-provider.js +2 -1
- package/lib/plugin/tasks/task-provider.js.map +1 -1
- package/lib/plugin/tasks/tasks.js +2 -1
- package/lib/plugin/tasks/tasks.js.map +1 -1
- package/lib/plugin/telemetry-ext.spec.js +2 -1
- package/lib/plugin/telemetry-ext.spec.js.map +1 -1
- package/lib/plugin/terminal-ext.js +1 -1
- package/lib/plugin/terminal-ext.js.map +1 -1
- package/lib/plugin/terminal-ext.spec.js +2 -1
- package/lib/plugin/terminal-ext.spec.js.map +1 -1
- package/lib/plugin/tests.js +1 -1
- package/lib/plugin/tests.js.map +1 -1
- package/lib/plugin/text-editor.js +2 -1
- package/lib/plugin/text-editor.js.map +1 -1
- package/lib/plugin/text-editors.js +2 -1
- package/lib/plugin/text-editors.js.map +1 -1
- package/lib/plugin/tree/tree-views.d.ts.map +1 -1
- package/lib/plugin/tree/tree-views.js +2 -1
- package/lib/plugin/tree/tree-views.js.map +1 -1
- package/lib/plugin/type-converters.js +6 -5
- package/lib/plugin/type-converters.js.map +1 -1
- package/lib/plugin/type-converters.spec.js +5 -4
- package/lib/plugin/type-converters.spec.js.map +1 -1
- package/lib/plugin/types-impl.d.ts +10 -0
- package/lib/plugin/types-impl.d.ts.map +1 -1
- package/lib/plugin/types-impl.js +7 -1
- package/lib/plugin/types-impl.js.map +1 -1
- package/lib/plugin/types-impl.spec.js +25 -2
- package/lib/plugin/types-impl.spec.js.map +1 -1
- package/lib/plugin/workspace.js +2 -2
- package/lib/plugin/workspace.js.map +1 -1
- package/lib/plugin/workspace.spec.js +2 -1
- package/lib/plugin/workspace.spec.js.map +1 -1
- package/lib/plugin-ext-frontend-electron-module.js +2 -1
- package/lib/plugin-ext-frontend-electron-module.js.map +1 -1
- package/lib/plugin-ext-frontend-module.js +2 -1
- package/lib/plugin-ext-frontend-module.js.map +1 -1
- package/package.json +32 -32
- package/src/common/character-classifier.ts +1 -1
- package/src/common/plugin-api-rpc.ts +2 -0
- package/src/common/plugin-protocol.ts +18 -0
- package/src/hosted/browser/hosted-plugin.spec.ts +66 -0
- package/src/hosted/browser/hosted-plugin.ts +3 -1
- package/src/hosted/node/plugin-host-proxy.ts +6 -3
- package/src/hosted/node/plugin-reader.ts +1 -1
- package/src/hosted/node/plugin-require-override.spec.ts +44 -0
- package/src/hosted/node/plugin-require-override.ts +1 -0
- package/src/main/browser/file-system-main-impl.ts +1 -1
- package/src/main/browser/main-file-system-event-service.ts +2 -49
- package/src/main/browser/menus/menus-contribution-handler.ts +6 -13
- package/src/main/browser/notebooks/renderers/output-webview-internal.ts +6 -3
- package/src/main/browser/plugin-shared-style.ts +2 -2
- package/src/main/browser/scm-main.spec.ts +32 -0
- package/src/main/browser/scm-main.ts +6 -2
- package/src/main/browser/view/plugin-view-registry.spec.ts +277 -12
- package/src/main/browser/view/plugin-view-registry.ts +76 -21
- package/src/main/browser/view/tree-view-widget.tsx +1 -1
- package/src/main/browser/webview/pre/main.js +19 -10
- package/src/main/browser/webview/pre/main.spec.ts +46 -0
- package/src/main/browser/webview/webview.ts +7 -3
- package/src/main/node/handlers/plugin-theia-directory-handler.ts +1 -1
- package/src/main/node/handlers/plugin-theia-file-handler.ts +1 -1
- package/src/main/node/plugin-deployer-file-handler-context-impl.ts +1 -1
- package/src/main/node/plugin-deployer-impl.spec.ts +75 -0
- package/src/main/node/plugin-deployer-impl.ts +7 -2
- package/src/main/node/plugin-service.ts +1 -1
- package/src/plugin/document-data.ts +0 -1
- package/src/plugin/file-system-event-service-ext-impl.ts +1 -1
- package/src/plugin/file-system-ext-impl.ts +2 -2
- package/src/plugin/known-commands.ts +5 -5
- package/src/plugin/plugin-context.ts +4 -4
- package/src/plugin/plugin-manager.ts +1 -1
- package/src/plugin/scm.spec.ts +67 -1
- package/src/plugin/scm.ts +18 -1
- package/src/plugin/tests.ts +2 -2
- package/src/plugin/tree/tree-views.ts +2 -1
- package/src/plugin/type-converters.spec.ts +1 -1
- package/src/plugin/types-impl.spec.ts +25 -0
- package/src/plugin/types-impl.ts +7 -0
- package/lib/main/browser/main-file-system-event-service.spec.d.ts +0 -2
- package/lib/main/browser/main-file-system-event-service.spec.d.ts.map +0 -1
- package/lib/main/browser/main-file-system-event-service.spec.js +0 -100
- package/lib/main/browser/main-file-system-event-service.spec.js.map +0 -1
- package/src/main/browser/main-file-system-event-service.spec.ts +0 -125
|
@@ -23,9 +23,10 @@ import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/front
|
|
|
23
23
|
FrontendApplicationConfigProvider.set({});
|
|
24
24
|
|
|
25
25
|
import { expect } from 'chai';
|
|
26
|
-
import { Disposable } from '@theia/core/lib/common';
|
|
26
|
+
import { Command, Disposable } from '@theia/core/lib/common';
|
|
27
27
|
import { PluginViewRegistry, ViewContainerInfo, PLUGIN_VIEW_DATA_FACTORY_ID } from './plugin-view-registry';
|
|
28
|
-
import
|
|
28
|
+
import { PluginViewType, ViewWelcome } from '../../../common';
|
|
29
|
+
import { BaseWidget, Panel, Widget } from '@theia/core/lib/browser/widgets/widget';
|
|
29
30
|
|
|
30
31
|
disableJSDOM();
|
|
31
32
|
|
|
@@ -54,7 +55,6 @@ describe('PluginViewRegistry - view menu labels', () => {
|
|
|
54
55
|
let registry: PluginViewRegistry;
|
|
55
56
|
let menus: RecordingMenuModelRegistry;
|
|
56
57
|
|
|
57
|
-
const toggleCommandId = (id: string): string => `plugin.view-container.${id}.toggle`;
|
|
58
58
|
const internals = (): {
|
|
59
59
|
viewContainers: Map<string, ViewContainerInfo>;
|
|
60
60
|
registerViewMenuAction(containerId: string, label: string): Disposable;
|
|
@@ -76,21 +76,21 @@ describe('PluginViewRegistry - view menu labels', () => {
|
|
|
76
76
|
|
|
77
77
|
it('uses the plain label for a single container', () => {
|
|
78
78
|
registerContainer('a', 'Claude Code', 'left');
|
|
79
|
-
expect(menus.actions.get(
|
|
79
|
+
expect(menus.actions.get('a')?.label).to.equal('Claude Code');
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
it('leaves distinct labels unsuffixed', () => {
|
|
83
83
|
registerContainer('a', 'Explorer', 'left');
|
|
84
84
|
registerContainer('b', 'Claude Code', 'right');
|
|
85
|
-
expect(menus.actions.get(
|
|
86
|
-
expect(menus.actions.get(
|
|
85
|
+
expect(menus.actions.get('a')?.label).to.equal('Explorer');
|
|
86
|
+
expect(menus.actions.get('b')?.label).to.equal('Claude Code');
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
it('suffixes the location when two containers share a label', () => {
|
|
90
90
|
registerContainer('a', 'Claude Code', 'left');
|
|
91
91
|
registerContainer('b', 'Claude Code', 'right');
|
|
92
|
-
expect(menus.actions.get(
|
|
93
|
-
expect(menus.actions.get(
|
|
92
|
+
expect(menus.actions.get('a')?.label).to.equal('Claude Code (Side Bar)');
|
|
93
|
+
expect(menus.actions.get('b')?.label).to.equal('Claude Code (Secondary Side Bar)');
|
|
94
94
|
});
|
|
95
95
|
|
|
96
96
|
it('drops the suffix from the remaining container once the duplicate is removed', () => {
|
|
@@ -99,12 +99,14 @@ describe('PluginViewRegistry - view menu labels', () => {
|
|
|
99
99
|
|
|
100
100
|
disposeB.dispose();
|
|
101
101
|
|
|
102
|
-
expect(menus.actions.get(
|
|
103
|
-
expect(menus.actions.has(
|
|
102
|
+
expect(menus.actions.get('a')?.label).to.equal('Claude Code');
|
|
103
|
+
expect(menus.actions.has('b')).to.equal(false);
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
+
const welcome = (view: string): ViewWelcome => ({ view, content: `[Hi](command:${view}.hi)`, order: 0 });
|
|
109
|
+
|
|
108
110
|
describe('PluginViewRegistry - welcome-only views', () => {
|
|
109
111
|
|
|
110
112
|
interface FakeTreeViewWidget {
|
|
@@ -117,8 +119,6 @@ describe('PluginViewRegistry - welcome-only views', () => {
|
|
|
117
119
|
let createdWidget: FakeTreeViewWidget;
|
|
118
120
|
let getOrCreateCalls: Array<{ factoryId: string; options: unknown }>;
|
|
119
121
|
|
|
120
|
-
const welcome = (view: string): ViewWelcome => ({ view, content: `[Hi](command:${view}.hi)`, order: 0 });
|
|
121
|
-
|
|
122
122
|
const internals = (): {
|
|
123
123
|
views: Map<string, [string, { type?: unknown }]>;
|
|
124
124
|
viewDataProviders: Map<string, unknown>;
|
|
@@ -171,3 +171,268 @@ describe('PluginViewRegistry - welcome-only views', () => {
|
|
|
171
171
|
});
|
|
172
172
|
|
|
173
173
|
});
|
|
174
|
+
|
|
175
|
+
describe('PluginViewRegistry - welcome-only views on expand', () => {
|
|
176
|
+
|
|
177
|
+
const noop = () => Disposable.NULL;
|
|
178
|
+
|
|
179
|
+
let registry: PluginViewRegistry;
|
|
180
|
+
let view: { widgets: unknown[] };
|
|
181
|
+
let prepared: unknown[];
|
|
182
|
+
|
|
183
|
+
const internals = (): {
|
|
184
|
+
views: Map<string, [string, { type?: unknown }]>;
|
|
185
|
+
viewDataProviders: Map<string, unknown>;
|
|
186
|
+
viewsWelcome: Map<string, ViewWelcome[]>;
|
|
187
|
+
onDidExpandViewEmitter: { fire(viewId: string): void };
|
|
188
|
+
init(): void;
|
|
189
|
+
} => registry as unknown as {
|
|
190
|
+
views: Map<string, [string, { type?: unknown }]>;
|
|
191
|
+
viewDataProviders: Map<string, unknown>;
|
|
192
|
+
viewsWelcome: Map<string, ViewWelcome[]>;
|
|
193
|
+
onDidExpandViewEmitter: { fire(viewId: string): void };
|
|
194
|
+
init(): void;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
async function expand(viewId: string): Promise<void> {
|
|
198
|
+
internals().onDidExpandViewEmitter.fire(viewId);
|
|
199
|
+
await new Promise(resolve => setTimeout(resolve));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
beforeEach(() => {
|
|
203
|
+
registry = new PluginViewRegistry();
|
|
204
|
+
view = { widgets: [] };
|
|
205
|
+
prepared = [];
|
|
206
|
+
Object.assign(registry, {
|
|
207
|
+
shell: { activeWidget: undefined, onDidChangeActiveWidget: noop, initialized: new Promise(() => { }) },
|
|
208
|
+
viewContextKeys: { focusedView: { reset: () => { } } },
|
|
209
|
+
contextKeyService: { onDidChange: noop },
|
|
210
|
+
widgetManager: { onWillCreateWidget: noop, onDidCreateWidget: noop, getWidget: async () => view },
|
|
211
|
+
prepareView: async (widget: unknown) => { prepared.push(widget); }
|
|
212
|
+
});
|
|
213
|
+
internals().init();
|
|
214
|
+
internals().views.set('actions', ['container', {}]);
|
|
215
|
+
internals().viewsWelcome.set('actions', [welcome('actions')]);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('prepares an empty welcome-only view when it is expanded, as after restoring a saved layout', async () => {
|
|
219
|
+
await expand('actions');
|
|
220
|
+
|
|
221
|
+
expect(prepared).to.deep.equal([view]);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('leaves a view with a data provider to the provider', async () => {
|
|
225
|
+
internals().viewDataProviders.set('actions', () => undefined);
|
|
226
|
+
|
|
227
|
+
await expand('actions');
|
|
228
|
+
|
|
229
|
+
expect(prepared).to.have.lengthOf(0);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('leaves a view that already has content alone', async () => {
|
|
233
|
+
view.widgets.push({});
|
|
234
|
+
|
|
235
|
+
await expand('actions');
|
|
236
|
+
|
|
237
|
+
expect(prepared).to.have.lengthOf(0);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('leaves a view without welcomes alone', async () => {
|
|
241
|
+
internals().viewsWelcome.delete('actions');
|
|
242
|
+
|
|
243
|
+
await expand('actions');
|
|
244
|
+
|
|
245
|
+
expect(prepared).to.have.lengthOf(0);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('leaves a webview view alone', async () => {
|
|
249
|
+
internals().views.set('actions', ['container', { type: PluginViewType.Webview }]);
|
|
250
|
+
|
|
251
|
+
await expand('actions');
|
|
252
|
+
|
|
253
|
+
expect(prepared).to.have.lengthOf(0);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
describe('PluginViewRegistry - prepareView', () => {
|
|
259
|
+
|
|
260
|
+
interface FakeViewWidget {
|
|
261
|
+
options: { viewId: string };
|
|
262
|
+
title: { label: string };
|
|
263
|
+
widgets: unknown[];
|
|
264
|
+
isDisposed: boolean;
|
|
265
|
+
addWidget(widget: unknown): void;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
let registry: PluginViewRegistry;
|
|
269
|
+
let view: FakeViewWidget;
|
|
270
|
+
let dataWidget: { isDisposed: boolean; dispose(): void };
|
|
271
|
+
|
|
272
|
+
beforeEach(() => {
|
|
273
|
+
registry = new PluginViewRegistry();
|
|
274
|
+
view = {
|
|
275
|
+
options: { viewId: 'actions' },
|
|
276
|
+
title: { label: '' },
|
|
277
|
+
widgets: [],
|
|
278
|
+
isDisposed: false,
|
|
279
|
+
addWidget(widget: unknown): void {
|
|
280
|
+
this.widgets.push(widget);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
dataWidget = { isDisposed: false, dispose: () => { } };
|
|
284
|
+
(registry as unknown as { views: Map<string, unknown> }).views.set('actions', ['container', { id: 'actions', name: 'Actions' }]);
|
|
285
|
+
(registry as unknown as { createViewDataWidget: unknown }).createViewDataWidget = async () => dataWidget;
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
const prepareView = (): Promise<void> => (registry as unknown as { prepareView(widget: FakeViewWidget): Promise<void> }).prepareView(view);
|
|
289
|
+
|
|
290
|
+
it('adds the created data widget to the view', async () => {
|
|
291
|
+
await prepareView();
|
|
292
|
+
|
|
293
|
+
expect(view.widgets).to.deep.equal([dataWidget]);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('leaves the view empty when its data widget was disposed before it could be added', async () => {
|
|
297
|
+
dataWidget.isDisposed = true;
|
|
298
|
+
|
|
299
|
+
await prepareView();
|
|
300
|
+
|
|
301
|
+
expect(view.widgets).to.have.lengthOf(0);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
describe('PluginViewRegistry - VS Code view commands', () => {
|
|
307
|
+
|
|
308
|
+
let registry: PluginViewRegistry;
|
|
309
|
+
let commands: Map<string, Command>;
|
|
310
|
+
|
|
311
|
+
const internals = (): {
|
|
312
|
+
doRegisterViewContainer(id: string, location: string, options: { label: string }): Disposable;
|
|
313
|
+
} => registry as unknown as {
|
|
314
|
+
doRegisterViewContainer(id: string, location: string, options: { label: string }): Disposable;
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
beforeEach(() => {
|
|
318
|
+
registry = new PluginViewRegistry();
|
|
319
|
+
commands = new Map();
|
|
320
|
+
(registry as unknown as { commands: unknown }).commands = {
|
|
321
|
+
registerCommand: (command: Command) => {
|
|
322
|
+
commands.set(command.id, command);
|
|
323
|
+
return Disposable.create(() => commands.delete(command.id));
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
(registry as unknown as { menus: unknown }).menus = new RecordingMenuModelRegistry();
|
|
327
|
+
(registry as unknown as { quickView: unknown }).quickView = { registerItem: () => Disposable.NULL };
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it('registers the container id and the view focus and open commands once a view is added', () => {
|
|
331
|
+
const containerId = 'workbench.view.extension.sample';
|
|
332
|
+
internals().doRegisterViewContainer(containerId, 'left', { label: 'Sample' });
|
|
333
|
+
expect(commands.has(containerId)).to.equal(false);
|
|
334
|
+
|
|
335
|
+
const disposeView = registry.registerView('sample', { id: 'sample.view', name: 'Sample View' });
|
|
336
|
+
|
|
337
|
+
expect(commands.get(containerId)).to.include({ label: 'Toggle Sample', category: 'View' });
|
|
338
|
+
expect(commands.get('plugin.view-container.workbench.view.extension.sample.toggle')?.label).to.equal(undefined);
|
|
339
|
+
expect(commands.get('sample.view.focus')).to.include({ label: 'Focus on Sample View View', category: 'Sample' });
|
|
340
|
+
expect(commands.has('sample.view.open')).to.equal(true);
|
|
341
|
+
|
|
342
|
+
disposeView.dispose();
|
|
343
|
+
expect(commands.has('sample.view.focus')).to.equal(false);
|
|
344
|
+
expect(commands.has('sample.view.open')).to.equal(false);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
describe('PluginViewRegistry - webview view resolution', () => {
|
|
350
|
+
|
|
351
|
+
class FakeWebviewWidget extends BaseWidget {
|
|
352
|
+
setContentOptions(): void { }
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const viewId = 'test.webviewView';
|
|
356
|
+
let registry: PluginViewRegistry;
|
|
357
|
+
let webview: FakeWebviewWidget;
|
|
358
|
+
let resolveCount: number;
|
|
359
|
+
let disableDom: () => void;
|
|
360
|
+
|
|
361
|
+
const createWebviewView = (): Promise<unknown> =>
|
|
362
|
+
(registry as unknown as { createNewWebviewView(id: string): Promise<unknown> }).createNewWebviewView(viewId);
|
|
363
|
+
const registerResolver = (): Promise<Disposable> =>
|
|
364
|
+
registry.registerWebviewView(viewId, { resolve: async () => { resolveCount++; } });
|
|
365
|
+
const settle = (): Promise<void> => new Promise(resolve => setTimeout(resolve, 0));
|
|
366
|
+
|
|
367
|
+
before(() => disableDom = enableJSDOM());
|
|
368
|
+
after(() => disableDom());
|
|
369
|
+
|
|
370
|
+
beforeEach(() => {
|
|
371
|
+
registry = new PluginViewRegistry();
|
|
372
|
+
webview = new FakeWebviewWidget();
|
|
373
|
+
resolveCount = 0;
|
|
374
|
+
(registry as unknown as { widgetManager: unknown }).widgetManager = { getOrCreateWidget: async () => webview };
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
afterEach(() => webview.dispose());
|
|
378
|
+
|
|
379
|
+
it('does not resolve a webview view that has not been shown', async () => {
|
|
380
|
+
await createWebviewView();
|
|
381
|
+
await registerResolver();
|
|
382
|
+
await settle();
|
|
383
|
+
|
|
384
|
+
expect(resolveCount).to.equal(0);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it('resolves a webview view once it is shown', async () => {
|
|
388
|
+
await createWebviewView();
|
|
389
|
+
await registerResolver();
|
|
390
|
+
await settle();
|
|
391
|
+
|
|
392
|
+
Widget.attach(webview, document.body);
|
|
393
|
+
await settle();
|
|
394
|
+
|
|
395
|
+
expect(resolveCount).to.equal(1);
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
it('resolves a webview view that is shown before its provider is registered', async () => {
|
|
399
|
+
await createWebviewView();
|
|
400
|
+
Widget.attach(webview, document.body);
|
|
401
|
+
await settle();
|
|
402
|
+
|
|
403
|
+
await registerResolver();
|
|
404
|
+
await settle();
|
|
405
|
+
|
|
406
|
+
expect(resolveCount).to.equal(1);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
it('resolves a webview view in a hidden parent only once the parent is shown', async () => {
|
|
410
|
+
const parent = new Panel();
|
|
411
|
+
parent.hide();
|
|
412
|
+
parent.addWidget(webview);
|
|
413
|
+
Widget.attach(parent, document.body);
|
|
414
|
+
await createWebviewView();
|
|
415
|
+
await registerResolver();
|
|
416
|
+
await settle();
|
|
417
|
+
expect(resolveCount).to.equal(0);
|
|
418
|
+
|
|
419
|
+
parent.show();
|
|
420
|
+
await settle();
|
|
421
|
+
parent.hide();
|
|
422
|
+
parent.show();
|
|
423
|
+
await settle();
|
|
424
|
+
|
|
425
|
+
expect(resolveCount).to.equal(1);
|
|
426
|
+
parent.dispose();
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it('does not resolve a webview view that is disposed before it is shown', async () => {
|
|
430
|
+
await createWebviewView();
|
|
431
|
+
webview.dispose();
|
|
432
|
+
await registerResolver();
|
|
433
|
+
await settle();
|
|
434
|
+
|
|
435
|
+
expect(resolveCount).to.equal(0);
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
});
|
|
@@ -160,6 +160,7 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
|
|
|
160
160
|
|
|
161
161
|
this.updateFocusedView();
|
|
162
162
|
this.shell.onDidChangeActiveWidget(() => this.updateFocusedView());
|
|
163
|
+
this.onDidExpandView(viewId => this.prepareWelcomeOnlyView(viewId).catch(e => this.logger.error(e)));
|
|
163
164
|
|
|
164
165
|
this.widgetManager.onWillCreateWidget(({ factoryId, widget, waitUntil }) => {
|
|
165
166
|
if (factoryId === EXPLORER_VIEW_CONTAINER_ID && widget instanceof ViewContainerWidget) {
|
|
@@ -347,15 +348,30 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
|
|
|
347
348
|
return toDispose;
|
|
348
349
|
}
|
|
349
350
|
|
|
351
|
+
/**
|
|
352
|
+
* Toggles the view container the same way as {@link AbstractViewContribution.toggleView}:
|
|
353
|
+
* collapses its panel if it is the visible tab, otherwise opens and activates it.
|
|
354
|
+
*/
|
|
350
355
|
protected async toggleViewContainer(id: string): Promise<void> {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
356
|
+
const existing = await this.getPluginViewContainer(id);
|
|
357
|
+
const tabBar = existing && this.shell.getTabBarFor(existing);
|
|
358
|
+
const area = existing && this.shell.getAreaFor(existing);
|
|
359
|
+
if (existing && tabBar && area && this.shell.isExpanded(area) && tabBar.currentTitle === existing.title) {
|
|
360
|
+
if (area === 'left' || area === 'right') {
|
|
361
|
+
await this.shell.collapsePanel(area);
|
|
362
|
+
} else if (area === 'bottom') {
|
|
363
|
+
// Don't collapse the bottom panel if it's currently split
|
|
364
|
+
if (this.shell.bottomAreaTabBars.length === 1) {
|
|
365
|
+
await this.shell.collapsePanel('bottom');
|
|
366
|
+
}
|
|
367
|
+
} else {
|
|
368
|
+
existing.dispose();
|
|
358
369
|
}
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const widget = await this.openViewContainer(id);
|
|
373
|
+
if (widget) {
|
|
374
|
+
await this.shell.activateWidget(widget.id);
|
|
359
375
|
}
|
|
360
376
|
}
|
|
361
377
|
|
|
@@ -369,18 +385,22 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
|
|
|
369
385
|
toDispose.push(Disposable.create(() => this.viewContainerClauseContexts.delete(id)));
|
|
370
386
|
}
|
|
371
387
|
}
|
|
372
|
-
const toggleCommandId = `plugin.view-container.${id}.toggle`;
|
|
373
388
|
// Some plugins may register empty view containers.
|
|
374
389
|
// We should not register commands for them immediately, as that leads to bad UX.
|
|
375
390
|
// Instead, we register commands the first time we add a view to them.
|
|
376
391
|
let activate = () => {
|
|
392
|
+
// Like VS Code, use the container's id, e.g. `workbench.view.extension.${id}`, as the command id
|
|
377
393
|
toDispose.push(this.commands.registerCommand({
|
|
378
|
-
id
|
|
394
|
+
id,
|
|
379
395
|
category: nls.localizeByDefault('View'),
|
|
380
396
|
label: nls.localizeByDefault('Toggle {0}', options.label)
|
|
381
397
|
}, {
|
|
382
398
|
execute: () => this.toggleViewContainer(id)
|
|
383
399
|
}));
|
|
400
|
+
// Kept for backward compatibility with keybindings that use the former command id
|
|
401
|
+
toDispose.push(this.commands.registerCommand({ id: `plugin.view-container.${id}.toggle` }, {
|
|
402
|
+
execute: () => this.toggleViewContainer(id)
|
|
403
|
+
}));
|
|
384
404
|
toDispose.push(this.registerViewMenuAction(id, options.label));
|
|
385
405
|
toDispose.push(this.quickView?.registerItem({
|
|
386
406
|
label: options.label,
|
|
@@ -486,7 +506,7 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
|
|
|
486
506
|
}
|
|
487
507
|
}
|
|
488
508
|
const disposable = this.menus.registerMenuAction(CommonMenus.VIEW_VIEWS, {
|
|
489
|
-
commandId:
|
|
509
|
+
commandId: id,
|
|
490
510
|
label: menuLabel,
|
|
491
511
|
when: containerInfo.when
|
|
492
512
|
});
|
|
@@ -561,15 +581,24 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
|
|
|
561
581
|
when: view.when,
|
|
562
582
|
open: () => this.openView(view.id, { activate: true })
|
|
563
583
|
}));
|
|
564
|
-
toDispose.push(this.commands.registerCommand({
|
|
565
|
-
|
|
584
|
+
toDispose.push(this.commands.registerCommand({
|
|
585
|
+
id: `${view.id}.focus`,
|
|
586
|
+
category: this.viewContainers.get(viewContainerId)?.options.label,
|
|
587
|
+
label: nls.localizeByDefault('Focus on {0} View', view.name)
|
|
588
|
+
}, {
|
|
589
|
+
execute: async (options?: { preserveFocus?: boolean }) => { await this.openView(view.id, this.toOpenViewOptions(options)); },
|
|
590
|
+
isVisible: () => this.isViewVisible(view.id)
|
|
566
591
|
}));
|
|
567
592
|
toDispose.push(this.commands.registerCommand({ id: `${view.id}.open` }, {
|
|
568
|
-
execute: async () => { await this.openView(view.id,
|
|
593
|
+
execute: async (options?: { preserveFocus?: boolean }) => { await this.openView(view.id, this.toOpenViewOptions(options)); }
|
|
569
594
|
}));
|
|
570
595
|
return toDispose;
|
|
571
596
|
}
|
|
572
597
|
|
|
598
|
+
protected toOpenViewOptions(options?: { preserveFocus?: boolean }): { activate?: boolean, reveal?: boolean } {
|
|
599
|
+
return options?.preserveFocus ? { reveal: true } : { activate: true };
|
|
600
|
+
}
|
|
601
|
+
|
|
573
602
|
async resolveWebviewView(viewId: string, webview: WebviewView, cancellation: CancellationToken): Promise<void> {
|
|
574
603
|
const resolver = this.webviewViewResolvers.get(viewId);
|
|
575
604
|
if (resolver) {
|
|
@@ -652,14 +681,24 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
|
|
|
652
681
|
}
|
|
653
682
|
};
|
|
654
683
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
684
|
+
// Like VS Code, resolve a webview view only once it is visible: extensions start work in
|
|
685
|
+
// `resolveWebviewView`, and views that are hidden or never opened should not pay for it.
|
|
686
|
+
const resolveIfVisible = () => {
|
|
687
|
+
if (webview.isVisible) {
|
|
658
688
|
webviewView.resolve();
|
|
659
689
|
}
|
|
660
|
-
}
|
|
690
|
+
};
|
|
691
|
+
const toDispose = new DisposableCollection(
|
|
692
|
+
this.onNewResolverRegistered(resolver => {
|
|
693
|
+
if (resolver.viewType === viewId) {
|
|
694
|
+
// Potentially re-activate if we have a new resolver
|
|
695
|
+
resolveIfVisible();
|
|
696
|
+
}
|
|
697
|
+
}),
|
|
698
|
+
webview.onDidChangeVisibility(resolveIfVisible)
|
|
699
|
+
);
|
|
661
700
|
|
|
662
|
-
|
|
701
|
+
resolveIfVisible();
|
|
663
702
|
return webviewView;
|
|
664
703
|
}
|
|
665
704
|
|
|
@@ -758,7 +797,8 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
|
|
|
758
797
|
const currentDataWidget = widget.widgets[0];
|
|
759
798
|
const webviewId = currentDataWidget instanceof WebviewWidget ? currentDataWidget.identifier?.id : undefined;
|
|
760
799
|
const viewDataWidget = await this.createViewDataWidget(view.id, webviewId);
|
|
761
|
-
|
|
800
|
+
// `onDidInitializeLayout` can dispose the data widget before it is added here.
|
|
801
|
+
if (widget.isDisposed || viewDataWidget?.isDisposed) {
|
|
762
802
|
viewDataWidget?.dispose();
|
|
763
803
|
return;
|
|
764
804
|
}
|
|
@@ -1001,8 +1041,8 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
|
|
|
1001
1041
|
}
|
|
1002
1042
|
|
|
1003
1043
|
/**
|
|
1004
|
-
*
|
|
1005
|
-
*
|
|
1044
|
+
* Retrieves the restored state of the data widgets and disposes them: a view gets a new data widget
|
|
1045
|
+
* once its data provider registers or, for a view with only welcome content, once it is expanded.
|
|
1006
1046
|
*/
|
|
1007
1047
|
onDidInitializeLayout(): void {
|
|
1008
1048
|
const widgets = this.widgetManager.getWidgets(PLUGIN_VIEW_DATA_FACTORY_ID);
|
|
@@ -1080,6 +1120,21 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
|
|
|
1080
1120
|
return widget;
|
|
1081
1121
|
}
|
|
1082
1122
|
|
|
1123
|
+
/**
|
|
1124
|
+
* Gives an expanded view that has `viewsWelcome` content but neither a data provider nor a
|
|
1125
|
+
* content widget its welcome widget, which `onDidInitializeLayout` disposes when it was restored.
|
|
1126
|
+
*/
|
|
1127
|
+
protected async prepareWelcomeOnlyView(viewId: string): Promise<void> {
|
|
1128
|
+
if (this.views.get(viewId)?.[1]?.type === PluginViewType.Webview
|
|
1129
|
+
|| this.viewDataProviders.has(viewId) || !this.getViewWelcomes(viewId).length) {
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
const view = await this.getView(viewId);
|
|
1133
|
+
if (view && !view.widgets.length) {
|
|
1134
|
+
await this.prepareView(view);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1083
1138
|
protected async createViewWelcomeWidget(viewId: string): Promise<TreeViewWidget> {
|
|
1084
1139
|
const widget = await this.widgetManager.getOrCreateWidget<TreeViewWidget>(PLUGIN_VIEW_DATA_FACTORY_ID, { id: viewId });
|
|
1085
1140
|
if (!widget.model.root) {
|
|
@@ -811,7 +811,7 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
|
|
|
811
811
|
}
|
|
812
812
|
const className = [TREE_NODE_SEGMENT_CLASS, TREE_NODE_TAIL_CLASS, actionMenuNode.icon, ACTION_ITEM, 'theia-tree-view-inline-action'].join(' ');
|
|
813
813
|
const tabIndex = tabbable ? 0 : undefined;
|
|
814
|
-
const titleString = actionMenuNode.label + (AcceleratorSource.is(actionMenuNode) ? actionMenuNode.getAccelerator(undefined).join('+') : '');
|
|
814
|
+
const titleString = actionMenuNode.label + (AcceleratorSource.is(actionMenuNode) ? actionMenuNode.getAccelerator(undefined, 'logical').join('+') : '');
|
|
815
815
|
|
|
816
816
|
return <div key={index} className={className} title={titleString} tabIndex={tabIndex} onClick={e => {
|
|
817
817
|
e.stopPropagation();
|
|
@@ -34,6 +34,23 @@
|
|
|
34
34
|
(function () {
|
|
35
35
|
'use strict';
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* @param {KeyboardEvent} event
|
|
39
|
+
*/
|
|
40
|
+
const toNormalizedKeyboardInput = event => ({
|
|
41
|
+
key: event.key,
|
|
42
|
+
keyCode: event.keyCode,
|
|
43
|
+
code: event.code,
|
|
44
|
+
shiftKey: event.shiftKey,
|
|
45
|
+
altKey: event.altKey,
|
|
46
|
+
ctrlKey: event.ctrlKey,
|
|
47
|
+
metaKey: event.metaKey,
|
|
48
|
+
altGraph: event.getModifierState('AltGraph'),
|
|
49
|
+
repeat: event.repeat,
|
|
50
|
+
isComposing: event.isComposing,
|
|
51
|
+
location: event.location
|
|
52
|
+
});
|
|
53
|
+
|
|
37
54
|
/**
|
|
38
55
|
* Use polling to track focus of main webview and iframes within the webview
|
|
39
56
|
*
|
|
@@ -300,16 +317,7 @@ window.frameElement = null;
|
|
|
300
317
|
const handleInnerKeydown = (e) => {
|
|
301
318
|
preventDefaultBrowserHotkeys(e);
|
|
302
319
|
|
|
303
|
-
host.postMessage('did-keydown',
|
|
304
|
-
key: e.key,
|
|
305
|
-
keyCode: e.keyCode,
|
|
306
|
-
code: e.code,
|
|
307
|
-
shiftKey: e.shiftKey,
|
|
308
|
-
altKey: e.altKey,
|
|
309
|
-
ctrlKey: e.ctrlKey,
|
|
310
|
-
metaKey: e.metaKey,
|
|
311
|
-
repeat: e.repeat
|
|
312
|
-
});
|
|
320
|
+
host.postMessage('did-keydown', toNormalizedKeyboardInput(e));
|
|
313
321
|
};
|
|
314
322
|
|
|
315
323
|
/**
|
|
@@ -678,6 +686,7 @@ window.frameElement = null;
|
|
|
678
686
|
|
|
679
687
|
if (typeof module !== 'undefined') {
|
|
680
688
|
module.exports = createWebviewManager;
|
|
689
|
+
module.exports.toNormalizedKeyboardInput = toNormalizedKeyboardInput;
|
|
681
690
|
} else {
|
|
682
691
|
window.createWebviewManager = createWebviewManager;
|
|
683
692
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 EclipseSource and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// https://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
9
|
+
// *****************************************************************************
|
|
10
|
+
|
|
11
|
+
import { expect } from 'chai';
|
|
12
|
+
|
|
13
|
+
const { toNormalizedKeyboardInput } = require('../../../../../src/main/browser/webview/pre/main.js');
|
|
14
|
+
|
|
15
|
+
describe('webview keyboard transport', () => {
|
|
16
|
+
it('serializes explicit AltGraph and normalized keyboard fields', () => {
|
|
17
|
+
const input = toNormalizedKeyboardInput({
|
|
18
|
+
key: '[',
|
|
19
|
+
keyCode: 56,
|
|
20
|
+
code: 'Digit8',
|
|
21
|
+
shiftKey: false,
|
|
22
|
+
altKey: false,
|
|
23
|
+
ctrlKey: true,
|
|
24
|
+
metaKey: false,
|
|
25
|
+
repeat: true,
|
|
26
|
+
isComposing: false,
|
|
27
|
+
location: 2,
|
|
28
|
+
getModifierState: (modifier: string) => modifier === 'AltGraph'
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
expect(input).to.deep.equal({
|
|
32
|
+
key: '[',
|
|
33
|
+
keyCode: 56,
|
|
34
|
+
code: 'Digit8',
|
|
35
|
+
shiftKey: false,
|
|
36
|
+
altKey: false,
|
|
37
|
+
ctrlKey: true,
|
|
38
|
+
metaKey: false,
|
|
39
|
+
altGraph: true,
|
|
40
|
+
repeat: true,
|
|
41
|
+
isComposing: false,
|
|
42
|
+
location: 2
|
|
43
|
+
});
|
|
44
|
+
expect(input).not.to.have.property('getModifierState');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -54,6 +54,7 @@ import { ContextMenuRenderer } from '@theia/core/lib/browser';
|
|
|
54
54
|
import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
|
|
55
55
|
import { PluginViewWidget } from '../view/plugin-view-widget';
|
|
56
56
|
import { WebviewPreferences } from '../../common/webview-preferences';
|
|
57
|
+
import { NormalizedKeyboardInput } from '@theia/core/lib/browser/keyboard/keys';
|
|
57
58
|
|
|
58
59
|
// Style from core
|
|
59
60
|
const TRANSPARENT_OVERLAY_STYLE = 'theia-transparent-overlay';
|
|
@@ -325,11 +326,14 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget, Extract
|
|
|
325
326
|
this.toHide.push(this.on(WebviewMessageChannels.loadLocalhost, (entry: any) =>
|
|
326
327
|
this.loadLocalhost(entry.origin)
|
|
327
328
|
));
|
|
328
|
-
this.toHide.push(this.on(WebviewMessageChannels.didKeydown, (data:
|
|
329
|
+
this.toHide.push(this.on(WebviewMessageChannels.didKeydown, (data: NormalizedKeyboardInput) => {
|
|
329
330
|
// Electron: workaround for https://github.com/electron/electron/issues/14258
|
|
330
331
|
// We have to detect keyboard events in the <webview> and dispatch them to our
|
|
331
332
|
// keybinding service because these events do not bubble to the parent window anymore.
|
|
332
|
-
this.keybindings.
|
|
333
|
+
this.keybindings.dispatchNormalizedKeyDown(data, this.element);
|
|
334
|
+
// DOM capture listeners must still observe the emulated event. Mark it as already handled so the registry's
|
|
335
|
+
// capture listener does not execute the keybinding a second time.
|
|
336
|
+
this.keybindings.dispatchKeyDown(data, this.element, true);
|
|
333
337
|
}));
|
|
334
338
|
this.toHide.push(this.on(WebviewMessageChannels.didMouseDown, (data: MouseEvent) => {
|
|
335
339
|
// We have to dispatch mousedown events so menus will be closed when clicking inside webviews.
|
|
@@ -415,7 +419,7 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget, Extract
|
|
|
415
419
|
}
|
|
416
420
|
|
|
417
421
|
setContentOptions(contentOptions: WebviewContentOptions): void {
|
|
418
|
-
if (JSONExt.deepEqual(
|
|
422
|
+
if (JSONExt.deepEqual(this.contentOptions as any, contentOptions as any)) {
|
|
419
423
|
return;
|
|
420
424
|
}
|
|
421
425
|
this._contentOptions = contentOptions;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import * as path from 'path';
|
|
18
|
-
import
|
|
18
|
+
import filenamify from 'filenamify';
|
|
19
19
|
import * as fs from '@theia/core/shared/fs-extra';
|
|
20
20
|
import { URI, ILogger } from '@theia/core';
|
|
21
21
|
import { inject, injectable, named } from '@theia/core/shared/inversify';
|