mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-07 15:26:49 +01:00
Merge branch 'main' into benibenj/hideTabsActionBar
This commit is contained in:
Vendored
+2
-1
@@ -7,6 +7,7 @@
|
||||
"github.vscode-pull-request-github",
|
||||
"ms-vscode.vscode-github-issue-notebooks",
|
||||
"ms-vscode.vscode-selfhost-test-provider",
|
||||
"ms-vscode.extension-test-runner"
|
||||
"ms-vscode.extension-test-runner",
|
||||
"jrieken.vscode-pr-pinger"
|
||||
]
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -7,7 +7,7 @@
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"October 2023\"\n"
|
||||
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"November 2023\"\n"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-pylint repo:microsoft/vscode-black-formatter repo:microsoft/vscode-isort repo:microsoft/lsprotocol repo:microsoft/vscode-flake8 repo:microsoft/vscode-autopep8 repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-mypy repo:microsoft/vscode-python-debugger\n\n$MILESTONE=milestone:\"October 2023\"\n"
|
||||
"value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-pylint repo:microsoft/vscode-black-formatter repo:microsoft/vscode-isort repo:microsoft/lsprotocol repo:microsoft/vscode-flake8 repo:microsoft/vscode-autopep8 repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-mypy repo:microsoft/vscode-python-debugger\n\n$MILESTONE=milestone:\"November 2023\"\n"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-pylint repo:microsoft/vscode-black-formatter repo:microsoft/vscode-isort repo:microsoft/lsprotocol repo:microsoft/vscode-flake8 repo:microsoft/vscode-autopep8 repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-mypy repo:microsoft/vscode-python-debugger\n\n$MILESTONE=milestone:\"October 2023\"\n\n$MINE=assignee:@me\n"
|
||||
"value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-pylint repo:microsoft/vscode-black-formatter repo:microsoft/vscode-isort repo:microsoft/lsprotocol repo:microsoft/vscode-flake8 repo:microsoft/vscode-autopep8 repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-mypy repo:microsoft/vscode-python-debugger\n\n$MILESTONE=milestone:\"November 2023\"\n\n$MINE=assignee:@me\n"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release\n\n// current milestone name\n$milestone=milestone:\"October 2023\"\n"
|
||||
"value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release\n\n// current milestone name\n$milestone=milestone:\"November 2023\"\n"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels\n$milestone=milestone:\"October 2023\"\n$closedRecently=closed:>2023-09-29\n"
|
||||
"value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-livepreview repo:microsoft/vscode-livepreview repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels\n$milestone=milestone:\"November 2023\"\n$closedRecently=closed:>2023-09-29\n"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$milestone=milestone:\"October 2023\"\n"
|
||||
"value": "$milestone=milestone:\"November 2023\"\n"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "vscode-markdown-languageserver",
|
||||
"description": "Markdown language server",
|
||||
"version": "0.4.0-alpha.7",
|
||||
"version": "0.4.0-alpha.8",
|
||||
"author": "Microsoft Corporation",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -18,7 +18,7 @@
|
||||
"vscode-languageserver": "^8.1.0",
|
||||
"vscode-languageserver-textdocument": "^1.0.8",
|
||||
"vscode-languageserver-types": "^3.17.3",
|
||||
"vscode-markdown-languageservice": "^0.4.0-alpha.7",
|
||||
"vscode-markdown-languageservice": "^0.4.0-alpha.8",
|
||||
"vscode-uri": "^3.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -128,10 +128,10 @@ vscode-languageserver@^8.1.0:
|
||||
dependencies:
|
||||
vscode-languageserver-protocol "3.17.3"
|
||||
|
||||
vscode-markdown-languageservice@^0.4.0-alpha.7:
|
||||
version "0.4.0-alpha.7"
|
||||
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.4.0-alpha.7.tgz#485e3394ff792a6fb225e5323ba9b5170f6fa7e7"
|
||||
integrity sha512-GZ8e1ewU989nLSRyQp3wXjIBFWZnu/rfo4gJxazujU2nTkR+VhPGh/ar/5pX7iHLRbESvcqgVqRQNU7zzVo/hw==
|
||||
vscode-markdown-languageservice@^0.4.0-alpha.8:
|
||||
version "0.4.0-alpha.8"
|
||||
resolved "https://registry.yarnpkg.com/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.4.0-alpha.8.tgz#5c3aaf3b3cd3f6b309f8dfcf93cbfb1397041adc"
|
||||
integrity sha512-6S6RE5s+4biWg2xk9bpwNi6GihUYQIVxdO3I+jb/XDyvfmqYVxrN86cKLF8QSbaQvX3fMuBAxBLFfX93FdJi3w==
|
||||
dependencies:
|
||||
"@vscode/l10n" "^0.0.10"
|
||||
node-html-parser "^6.1.5"
|
||||
|
||||
@@ -27,7 +27,7 @@ export function inferredProjectCompilerOptions(
|
||||
): Proto.ExternalProjectCompilerOptions {
|
||||
const projectConfig: Proto.ExternalProjectCompilerOptions = {
|
||||
module: 'ESNext' as Proto.ModuleKind,
|
||||
moduleResolution: (version.gte(API.v500) ? 'Bundler' : 'Node') as Proto.ModuleResolutionKind,
|
||||
moduleResolution: 'Node' as Proto.ModuleResolutionKind,
|
||||
target: 'ES2022' as Proto.ScriptTarget,
|
||||
jsx: 'react' as Proto.JsxEmit,
|
||||
};
|
||||
|
||||
+7
-7
@@ -96,14 +96,14 @@
|
||||
"vscode-oniguruma": "1.7.0",
|
||||
"vscode-regexpp": "^3.1.0",
|
||||
"vscode-textmate": "9.0.0",
|
||||
"xterm": "5.4.0-beta.32",
|
||||
"xterm-addon-canvas": "0.6.0-beta.32",
|
||||
"xterm": "5.4.0-beta.37",
|
||||
"xterm-addon-canvas": "0.6.0-beta.37",
|
||||
"xterm-addon-image": "0.6.0-beta.21",
|
||||
"xterm-addon-search": "0.14.0-beta.31",
|
||||
"xterm-addon-serialize": "0.12.0-beta.31",
|
||||
"xterm-addon-unicode11": "0.7.0-beta.31",
|
||||
"xterm-addon-webgl": "0.17.0-beta.31",
|
||||
"xterm-headless": "5.4.0-beta.32",
|
||||
"xterm-addon-search": "0.14.0-beta.36",
|
||||
"xterm-addon-serialize": "0.12.0-beta.36",
|
||||
"xterm-addon-unicode11": "0.7.0-beta.36",
|
||||
"xterm-addon-webgl": "0.17.0-beta.36",
|
||||
"xterm-headless": "5.4.0-beta.37",
|
||||
"yauzl": "^2.9.2",
|
||||
"yazl": "^2.4.3"
|
||||
},
|
||||
|
||||
+7
-7
@@ -26,14 +26,14 @@
|
||||
"vscode-oniguruma": "1.7.0",
|
||||
"vscode-regexpp": "^3.1.0",
|
||||
"vscode-textmate": "9.0.0",
|
||||
"xterm": "5.4.0-beta.32",
|
||||
"xterm-addon-canvas": "0.6.0-beta.32",
|
||||
"xterm": "5.4.0-beta.37",
|
||||
"xterm-addon-canvas": "0.6.0-beta.37",
|
||||
"xterm-addon-image": "0.6.0-beta.21",
|
||||
"xterm-addon-search": "0.14.0-beta.31",
|
||||
"xterm-addon-serialize": "0.12.0-beta.31",
|
||||
"xterm-addon-unicode11": "0.7.0-beta.31",
|
||||
"xterm-addon-webgl": "0.17.0-beta.31",
|
||||
"xterm-headless": "5.4.0-beta.32",
|
||||
"xterm-addon-search": "0.14.0-beta.36",
|
||||
"xterm-addon-serialize": "0.12.0-beta.36",
|
||||
"xterm-addon-unicode11": "0.7.0-beta.36",
|
||||
"xterm-addon-webgl": "0.17.0-beta.36",
|
||||
"xterm-headless": "5.4.0-beta.37",
|
||||
"yauzl": "^2.9.2",
|
||||
"yazl": "^2.4.3"
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
"tas-client-umd": "0.1.8",
|
||||
"vscode-oniguruma": "1.7.0",
|
||||
"vscode-textmate": "9.0.0",
|
||||
"xterm": "5.4.0-beta.32",
|
||||
"xterm-addon-canvas": "0.6.0-beta.32",
|
||||
"xterm": "5.4.0-beta.37",
|
||||
"xterm-addon-canvas": "0.6.0-beta.37",
|
||||
"xterm-addon-image": "0.6.0-beta.21",
|
||||
"xterm-addon-search": "0.14.0-beta.31",
|
||||
"xterm-addon-unicode11": "0.7.0-beta.31",
|
||||
"xterm-addon-webgl": "0.17.0-beta.31"
|
||||
"xterm-addon-search": "0.14.0-beta.36",
|
||||
"xterm-addon-unicode11": "0.7.0-beta.36",
|
||||
"xterm-addon-webgl": "0.17.0-beta.36"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-20
@@ -68,32 +68,32 @@ vscode-textmate@9.0.0:
|
||||
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-9.0.0.tgz#313c6c8792b0507aef35aeb81b6b370b37c44d6c"
|
||||
integrity sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg==
|
||||
|
||||
xterm-addon-canvas@0.6.0-beta.32:
|
||||
version "0.6.0-beta.32"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.6.0-beta.32.tgz#c9e74dd72fcc981a2e0cbd0b82827676bc5c74b9"
|
||||
integrity sha512-Xw7oE4dbS+x+pu6cGW1bDSXcVviuorLz1OLaYw46jjmDezIqQIIEMhSMOprExFEWgeRQ9AEN4lPqw6aH87V74w==
|
||||
xterm-addon-canvas@0.6.0-beta.37:
|
||||
version "0.6.0-beta.37"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.6.0-beta.37.tgz#4f7692fc87f3500a5a6e7f822ec74796e6a36db2"
|
||||
integrity sha512-eFN7iPxqiQosUO+rbXKwPz/AR3TLJcLCVWjvT5EaewqNpw+E9rWVwRRPGqYSw+qkSKM/vcNlySIkq4hmpA/ohg==
|
||||
|
||||
xterm-addon-image@0.6.0-beta.21:
|
||||
version "0.6.0-beta.21"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.21.tgz#e3708bc504c56a23ff31f12a2eeb335331a92aac"
|
||||
integrity sha512-8/PTaXVPa4kQ0xzVeuZZk10OpbZBj2cgfwhM2B0ChSPvwrk0lX+ksnXdtDKH3tg+JYvo7fIhNXtkr4NwWt7VJQ==
|
||||
|
||||
xterm-addon-search@0.14.0-beta.31:
|
||||
version "0.14.0-beta.31"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.14.0-beta.31.tgz#933ca5d2d642dacad29f2cfbd50830cff83bc274"
|
||||
integrity sha512-JRY1ukhoh32D0AMz78xpumQkLgkcP9d3GXj6gzVHZZsjLAMDaJYEubYq1bUhM7IGHUyg+x0sdRJyx7d6fJpiQg==
|
||||
xterm-addon-search@0.14.0-beta.36:
|
||||
version "0.14.0-beta.36"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.14.0-beta.36.tgz#4bb161130c39090d506f73468ef65054aedcb9f0"
|
||||
integrity sha512-2ydZV1Nt8d0vOjZ/y2RXiw3QLgabK+PCA7yETqZNivnmhSfcxtYPyI4aRfG/lc3hoMKiPppSSjJF0MlV/qo8ww==
|
||||
|
||||
xterm-addon-unicode11@0.7.0-beta.31:
|
||||
version "0.7.0-beta.31"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.7.0-beta.31.tgz#abcba752172323f31312bd8a3f9b6a049dbca6e3"
|
||||
integrity sha512-vvBKJbBoLbeIf2++6D16VnOOwevZE3nyO/PDZ7cyTJK1eYR73rr8ZbjUrH92YoTu4Z8MpZFepGQOgK/vlAQMwQ==
|
||||
xterm-addon-unicode11@0.7.0-beta.36:
|
||||
version "0.7.0-beta.36"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.7.0-beta.36.tgz#bde0b8c98211b74b0288cd5bad09107384b870ca"
|
||||
integrity sha512-vV/f7dTP/46JjoJLYDCxolCWPoUn0cF7S5upYvY0ZA1VLQ9UnXmaNjzrg+9f+QBoXEQ2eQDLQcRFWOc6BAbF+A==
|
||||
|
||||
xterm-addon-webgl@0.17.0-beta.31:
|
||||
version "0.17.0-beta.31"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.17.0-beta.31.tgz#3cd29b4858e3f4f6dd5a8dd969454e85e1f43baa"
|
||||
integrity sha512-vYHj+HlTcqUlFFVuoCTjlgh89/lIoSkZ7Nc87cwSFTrJsl07qoKutmpupqFXyjhbEA1fQY2SuQLx08Gmf2jWkQ==
|
||||
xterm-addon-webgl@0.17.0-beta.36:
|
||||
version "0.17.0-beta.36"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.17.0-beta.36.tgz#6ed16a83cd4bed3cbddd631e7974375aa8f7e023"
|
||||
integrity sha512-5PNQZcNH2UTaqSf7Exgh/fvsNeTOs+CSEuIaTafzKuMIrWH14+cRdyJdzyo8OKTNzhJOjwWDOTQTD/sur4lrLg==
|
||||
|
||||
xterm@5.4.0-beta.32:
|
||||
version "5.4.0-beta.32"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.4.0-beta.32.tgz#1b4242cf1c0c1a5a1070da58d3f11956b537130a"
|
||||
integrity sha512-mWTwEiNBFMF89oqVfi6qTM2Py5gC1Mwvslx1KxmI2Ukgh9v3CrqKDhj29eY1ZeAo0uuYknFWKyuexqp+3SHJCA==
|
||||
xterm@5.4.0-beta.37:
|
||||
version "5.4.0-beta.37"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.4.0-beta.37.tgz#bae127be8c939f096232d9858e77a457d6b77ddf"
|
||||
integrity sha512-ys+mXqLFrJc7khmYN/MgBnfLv38NgXfkwkEXsCZKHGqn3h2xUBvTvsrSEWO3NQeDPLj4zMr1RwqTblMK9St3BA==
|
||||
|
||||
+28
-28
@@ -589,45 +589,45 @@ wrappy@1:
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
xterm-addon-canvas@0.6.0-beta.32:
|
||||
version "0.6.0-beta.32"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.6.0-beta.32.tgz#c9e74dd72fcc981a2e0cbd0b82827676bc5c74b9"
|
||||
integrity sha512-Xw7oE4dbS+x+pu6cGW1bDSXcVviuorLz1OLaYw46jjmDezIqQIIEMhSMOprExFEWgeRQ9AEN4lPqw6aH87V74w==
|
||||
xterm-addon-canvas@0.6.0-beta.37:
|
||||
version "0.6.0-beta.37"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.6.0-beta.37.tgz#4f7692fc87f3500a5a6e7f822ec74796e6a36db2"
|
||||
integrity sha512-eFN7iPxqiQosUO+rbXKwPz/AR3TLJcLCVWjvT5EaewqNpw+E9rWVwRRPGqYSw+qkSKM/vcNlySIkq4hmpA/ohg==
|
||||
|
||||
xterm-addon-image@0.6.0-beta.21:
|
||||
version "0.6.0-beta.21"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.21.tgz#e3708bc504c56a23ff31f12a2eeb335331a92aac"
|
||||
integrity sha512-8/PTaXVPa4kQ0xzVeuZZk10OpbZBj2cgfwhM2B0ChSPvwrk0lX+ksnXdtDKH3tg+JYvo7fIhNXtkr4NwWt7VJQ==
|
||||
|
||||
xterm-addon-search@0.14.0-beta.31:
|
||||
version "0.14.0-beta.31"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.14.0-beta.31.tgz#933ca5d2d642dacad29f2cfbd50830cff83bc274"
|
||||
integrity sha512-JRY1ukhoh32D0AMz78xpumQkLgkcP9d3GXj6gzVHZZsjLAMDaJYEubYq1bUhM7IGHUyg+x0sdRJyx7d6fJpiQg==
|
||||
xterm-addon-search@0.14.0-beta.36:
|
||||
version "0.14.0-beta.36"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.14.0-beta.36.tgz#4bb161130c39090d506f73468ef65054aedcb9f0"
|
||||
integrity sha512-2ydZV1Nt8d0vOjZ/y2RXiw3QLgabK+PCA7yETqZNivnmhSfcxtYPyI4aRfG/lc3hoMKiPppSSjJF0MlV/qo8ww==
|
||||
|
||||
xterm-addon-serialize@0.12.0-beta.31:
|
||||
version "0.12.0-beta.31"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.12.0-beta.31.tgz#2a95dc1e12f4097e2894b04c9cb8fff0bc0b858c"
|
||||
integrity sha512-h2rWR+Lfi1Iv4VkLUlrBMYh5Mdq8vux2BKyCJe6a1ZnEu5Dzb0VuiNxfTKXTCT5M83nMn7TCB9TX0E8z6bs7xw==
|
||||
xterm-addon-serialize@0.12.0-beta.36:
|
||||
version "0.12.0-beta.36"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.12.0-beta.36.tgz#8e74159317e2c1e5f2724fd92b85df2b87d2c9c9"
|
||||
integrity sha512-J2mr3Wuxzvxke14IpfJBhwCHlWoB428FE06tOfbGi5lCBm0AnO2cIyRymvgVZG4QVXVxzzWroE8wP/WQQVe45w==
|
||||
|
||||
xterm-addon-unicode11@0.7.0-beta.31:
|
||||
version "0.7.0-beta.31"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.7.0-beta.31.tgz#abcba752172323f31312bd8a3f9b6a049dbca6e3"
|
||||
integrity sha512-vvBKJbBoLbeIf2++6D16VnOOwevZE3nyO/PDZ7cyTJK1eYR73rr8ZbjUrH92YoTu4Z8MpZFepGQOgK/vlAQMwQ==
|
||||
xterm-addon-unicode11@0.7.0-beta.36:
|
||||
version "0.7.0-beta.36"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.7.0-beta.36.tgz#bde0b8c98211b74b0288cd5bad09107384b870ca"
|
||||
integrity sha512-vV/f7dTP/46JjoJLYDCxolCWPoUn0cF7S5upYvY0ZA1VLQ9UnXmaNjzrg+9f+QBoXEQ2eQDLQcRFWOc6BAbF+A==
|
||||
|
||||
xterm-addon-webgl@0.17.0-beta.31:
|
||||
version "0.17.0-beta.31"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.17.0-beta.31.tgz#3cd29b4858e3f4f6dd5a8dd969454e85e1f43baa"
|
||||
integrity sha512-vYHj+HlTcqUlFFVuoCTjlgh89/lIoSkZ7Nc87cwSFTrJsl07qoKutmpupqFXyjhbEA1fQY2SuQLx08Gmf2jWkQ==
|
||||
xterm-addon-webgl@0.17.0-beta.36:
|
||||
version "0.17.0-beta.36"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.17.0-beta.36.tgz#6ed16a83cd4bed3cbddd631e7974375aa8f7e023"
|
||||
integrity sha512-5PNQZcNH2UTaqSf7Exgh/fvsNeTOs+CSEuIaTafzKuMIrWH14+cRdyJdzyo8OKTNzhJOjwWDOTQTD/sur4lrLg==
|
||||
|
||||
xterm-headless@5.4.0-beta.32:
|
||||
version "5.4.0-beta.32"
|
||||
resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.4.0-beta.32.tgz#0d5cd35e1a0372888055ff0b06dfe17457979a6c"
|
||||
integrity sha512-DQduq8KSoQZyRrQAFB+FkcY2UMxCW39P1/duOpksebc6PT9pbGkyPe5s+AdUQGiYzriEpzVtKUzDcquoVmpPhA==
|
||||
xterm-headless@5.4.0-beta.37:
|
||||
version "5.4.0-beta.37"
|
||||
resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.4.0-beta.37.tgz#1e89dfa7e667a5951974a9e9b5e1b0875198ca65"
|
||||
integrity sha512-iP28Z419p7anaNetLhmPOpt/DUdeA45jVLqoTn8bRpwFj8kM/gI76tUO9y/TyMfv79yWwPv2MrkALfS6ZyTi7g==
|
||||
|
||||
xterm@5.4.0-beta.32:
|
||||
version "5.4.0-beta.32"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.4.0-beta.32.tgz#1b4242cf1c0c1a5a1070da58d3f11956b537130a"
|
||||
integrity sha512-mWTwEiNBFMF89oqVfi6qTM2Py5gC1Mwvslx1KxmI2Ukgh9v3CrqKDhj29eY1ZeAo0uuYknFWKyuexqp+3SHJCA==
|
||||
xterm@5.4.0-beta.37:
|
||||
version "5.4.0-beta.37"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.4.0-beta.37.tgz#bae127be8c939f096232d9858e77a457d6b77ddf"
|
||||
integrity sha512-ys+mXqLFrJc7khmYN/MgBnfLv38NgXfkwkEXsCZKHGqn3h2xUBvTvsrSEWO3NQeDPLj4zMr1RwqTblMK9St3BA==
|
||||
|
||||
yallist@^4.0.0:
|
||||
version "4.0.0"
|
||||
|
||||
+52
-46
@@ -18,23 +18,38 @@ import * as platform from 'vs/base/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
|
||||
type WindowGlobal = Window & typeof globalThis;
|
||||
|
||||
interface IWindow {
|
||||
readonly window: WindowGlobal;
|
||||
readonly disposables: DisposableStore;
|
||||
}
|
||||
|
||||
export const { registerWindow, getWindows, getWindowsCount, onDidRegisterWindow, onWillUnregisterWindow, onDidUnregisterWindow } = (function () {
|
||||
const windows = new Set([window]);
|
||||
const onDidRegisterWindow = new event.Emitter<{ window: Window & typeof globalThis; disposables: DisposableStore }>();
|
||||
const onDidUnregisterWindow = new event.Emitter<Window & typeof globalThis>();
|
||||
const onWillUnregisterWindow = new event.Emitter<Window & typeof globalThis>();
|
||||
const windows = new Map<WindowGlobal, IWindow>();
|
||||
windows.set(window, { window, disposables: new DisposableStore() });
|
||||
|
||||
const onDidRegisterWindow = new event.Emitter<IWindow>();
|
||||
const onDidUnregisterWindow = new event.Emitter<WindowGlobal>();
|
||||
const onWillUnregisterWindow = new event.Emitter<WindowGlobal>();
|
||||
|
||||
return {
|
||||
onDidRegisterWindow: onDidRegisterWindow.event,
|
||||
onWillUnregisterWindow: onWillUnregisterWindow.event,
|
||||
onDidUnregisterWindow: onDidUnregisterWindow.event,
|
||||
registerWindow(window: Window & typeof globalThis): IDisposable {
|
||||
registerWindow(window: WindowGlobal): IDisposable {
|
||||
if (windows.has(window)) {
|
||||
return Disposable.None;
|
||||
}
|
||||
|
||||
windows.add(window);
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
const registeredWindow = {
|
||||
window,
|
||||
disposables: disposables.add(new DisposableStore())
|
||||
};
|
||||
windows.set(window, registeredWindow);
|
||||
|
||||
disposables.add(toDisposable(() => {
|
||||
windows.delete(window);
|
||||
onDidUnregisterWindow.fire(window);
|
||||
@@ -44,14 +59,12 @@ export const { registerWindow, getWindows, getWindowsCount, onDidRegisterWindow,
|
||||
onWillUnregisterWindow.fire(window);
|
||||
}));
|
||||
|
||||
const eventDisposables = new DisposableStore();
|
||||
disposables.add(eventDisposables);
|
||||
onDidRegisterWindow.fire({ window, disposables: eventDisposables });
|
||||
onDidRegisterWindow.fire(registeredWindow);
|
||||
|
||||
return disposables;
|
||||
},
|
||||
getWindows(): Iterable<Window & typeof globalThis> {
|
||||
return windows;
|
||||
getWindows(): Iterable<IWindow> {
|
||||
return windows.values();
|
||||
},
|
||||
getWindowsCount(): number {
|
||||
return windows.size;
|
||||
@@ -163,14 +176,14 @@ export function addDisposableGenericMouseUpListener(node: EventTarget, handler:
|
||||
* If currently in an animation frame, `runner` will be executed immediately.
|
||||
* @return token that can be used to cancel the scheduled runner (only if `runner` was not executed immediately).
|
||||
*/
|
||||
export let runAtThisOrScheduleAtNextAnimationFrame: (runner: () => void, priority?: number) => IDisposable;
|
||||
export let runAtThisOrScheduleAtNextAnimationFrame: (runner: () => void, targetWindow: Window, priority?: number) => IDisposable;
|
||||
/**
|
||||
* Schedule a callback to be run at the next animation frame.
|
||||
* This allows multiple parties to register callbacks that should run at the next animation frame.
|
||||
* If currently in an animation frame, `runner` will be executed at the next animation frame.
|
||||
* @return token that can be used to cancel the scheduled runner.
|
||||
*/
|
||||
export let scheduleAtNextAnimationFrame: (runner: () => void, priority?: number) => IDisposable;
|
||||
export let scheduleAtNextAnimationFrame: (runner: () => void, targetWindow: Window, priority?: number) => IDisposable;
|
||||
|
||||
class AnimationFrameQueueItem implements IDisposable {
|
||||
|
||||
@@ -239,35 +252,35 @@ class AnimationFrameQueueItem implements IDisposable {
|
||||
inAnimationFrameRunner = false;
|
||||
};
|
||||
|
||||
scheduleAtNextAnimationFrame = (runner: () => void, priority: number = 0) => {
|
||||
scheduleAtNextAnimationFrame = (runner: () => void, targetWindow: Window, priority: number = 0) => {
|
||||
const item = new AnimationFrameQueueItem(runner, priority);
|
||||
NEXT_QUEUE.push(item);
|
||||
|
||||
if (!animFrameRequested) {
|
||||
animFrameRequested = true;
|
||||
requestAnimationFrame(animationFrameRunner);
|
||||
targetWindow.requestAnimationFrame(animationFrameRunner);
|
||||
}
|
||||
|
||||
return item;
|
||||
};
|
||||
|
||||
runAtThisOrScheduleAtNextAnimationFrame = (runner: () => void, priority?: number) => {
|
||||
runAtThisOrScheduleAtNextAnimationFrame = (runner: () => void, targetWindow: Window, priority?: number) => {
|
||||
if (inAnimationFrameRunner) {
|
||||
const item = new AnimationFrameQueueItem(runner, priority);
|
||||
CURRENT_QUEUE!.push(item);
|
||||
return item;
|
||||
} else {
|
||||
return scheduleAtNextAnimationFrame(runner, priority);
|
||||
return scheduleAtNextAnimationFrame(runner, targetWindow, priority);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
export function measure(callback: () => void): IDisposable {
|
||||
return scheduleAtNextAnimationFrame(callback, 10000 /* must be early */);
|
||||
export function measure(callback: () => void, targetWindow: Window): IDisposable {
|
||||
return scheduleAtNextAnimationFrame(callback, targetWindow, 10000 /* must be early */);
|
||||
}
|
||||
|
||||
export function modify(callback: () => void): IDisposable {
|
||||
return scheduleAtNextAnimationFrame(callback, -10000 /* must be late */);
|
||||
export function modify(callback: () => void, targetWindow: Window): IDisposable {
|
||||
return scheduleAtNextAnimationFrame(callback, targetWindow, -10000 /* must be late */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -758,25 +771,24 @@ export function getActiveDocument(): Document {
|
||||
return document;
|
||||
}
|
||||
|
||||
const documents = Array.from(getWindows()).map(window => window.document);
|
||||
return documents.find(doc => doc.hasFocus()) ?? document;
|
||||
const documents = Array.from(getWindows()).map(({ window }) => window.document);
|
||||
return documents.find(document => document.hasFocus()) ?? document;
|
||||
}
|
||||
|
||||
export function getActiveWindow(): Window & typeof globalThis {
|
||||
export function getActiveWindow(): WindowGlobal {
|
||||
const document = getActiveDocument();
|
||||
return document.defaultView?.window ?? window;
|
||||
}
|
||||
|
||||
export function getWindow(element: Node): Window & typeof globalThis;
|
||||
export function getWindow(event: UIEvent): Window & typeof globalThis;
|
||||
export function getWindow(obj: unknown): Window & typeof globalThis;
|
||||
export function getWindow(e: unknown): Window & typeof globalThis {
|
||||
const candidateNode = e as Node | undefined;
|
||||
export function getWindow(element: Node | undefined | null): WindowGlobal;
|
||||
export function getWindow(event: UIEvent | undefined | null): WindowGlobal;
|
||||
export function getWindow(e: unknown): WindowGlobal {
|
||||
const candidateNode = e as Node | undefined | null;
|
||||
if (candidateNode?.ownerDocument?.defaultView) {
|
||||
return candidateNode.ownerDocument.defaultView.window;
|
||||
}
|
||||
|
||||
const candidateEvent = e as UIEvent | undefined;
|
||||
const candidateEvent = e as UIEvent | undefined | null;
|
||||
if (candidateEvent?.view) {
|
||||
return candidateEvent.view.window;
|
||||
}
|
||||
@@ -805,19 +817,13 @@ export function createStyleSheet(container: HTMLElement = document.head, beforeA
|
||||
// With <head> as container, the stylesheet becomes global and is tracked
|
||||
// to support auxiliary windows to clone the stylesheet.
|
||||
if (container === document.head) {
|
||||
for (const targetWindow of getWindows()) {
|
||||
for (const { window: targetWindow, disposables } of getWindows()) {
|
||||
if (targetWindow === window) {
|
||||
continue; // main window is already tracked
|
||||
}
|
||||
|
||||
const cloneDisposable = cloneGlobalStyleSheet(style, targetWindow);
|
||||
const cloneDisposable = disposables.add(cloneGlobalStyleSheet(style, targetWindow));
|
||||
disposableStore?.add(cloneDisposable);
|
||||
|
||||
disposableStore?.add(event.Event.once(onDidUnregisterWindow)(unregisteredWindow => {
|
||||
if (unregisteredWindow === targetWindow) {
|
||||
cloneDisposable.dispose();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -989,22 +995,22 @@ function isCSSStyleRule(rule: CSSRule): rule is CSSStyleRule {
|
||||
|
||||
export function isMouseEvent(e: unknown): e is MouseEvent {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return e instanceof MouseEvent || e instanceof getWindow(e).MouseEvent;
|
||||
return e instanceof MouseEvent || e instanceof getWindow(e as UIEvent).MouseEvent;
|
||||
}
|
||||
|
||||
export function isKeyboardEvent(e: unknown): e is KeyboardEvent {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return e instanceof KeyboardEvent || e instanceof getWindow(e).KeyboardEvent;
|
||||
return e instanceof KeyboardEvent || e instanceof getWindow(e as UIEvent).KeyboardEvent;
|
||||
}
|
||||
|
||||
export function isPointerEvent(e: unknown): e is PointerEvent {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return e instanceof PointerEvent || e instanceof getWindow(e).PointerEvent;
|
||||
return e instanceof PointerEvent || e instanceof getWindow(e as UIEvent).PointerEvent;
|
||||
}
|
||||
|
||||
export function isDragEvent(e: unknown): e is DragEvent {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return e instanceof DragEvent || e instanceof getWindow(e).DragEvent;
|
||||
return e instanceof DragEvent || e instanceof getWindow(e as UIEvent).DragEvent;
|
||||
}
|
||||
|
||||
export const EventType = {
|
||||
@@ -1456,13 +1462,13 @@ export function windowOpenWithSuccess(url: string, noOpener = true): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function animate(fn: () => void): IDisposable {
|
||||
export function animate(fn: () => void, targetWindow: Window): IDisposable {
|
||||
const step = () => {
|
||||
fn();
|
||||
stepDisposable = scheduleAtNextAnimationFrame(step);
|
||||
stepDisposable = scheduleAtNextAnimationFrame(step, targetWindow);
|
||||
};
|
||||
|
||||
let stepDisposable = scheduleAtNextAnimationFrame(step);
|
||||
let stepDisposable = scheduleAtNextAnimationFrame(step, targetWindow);
|
||||
return toDisposable(() => stepDisposable.dispose());
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ export class Gesture extends Disposable {
|
||||
|
||||
this._register(EventUtils.runAndSubscribe(DomUtils.onDidRegisterWindow, ({ window, disposables }) => {
|
||||
disposables.add(DomUtils.addDisposableListener(window.document, 'touchstart', (e: TouchEvent) => this.onTouchStart(e), { passive: false }));
|
||||
disposables.add(DomUtils.addDisposableListener(window.document, 'touchend', (e: TouchEvent) => this.onTouchEnd(e)));
|
||||
disposables.add(DomUtils.addDisposableListener(window.document, 'touchend', (e: TouchEvent) => this.onTouchEnd(window, e)));
|
||||
disposables.add(DomUtils.addDisposableListener(window.document, 'touchmove', (e: TouchEvent) => this.onTouchMove(e), { passive: false }));
|
||||
}, { window, disposables: this._store }));
|
||||
}
|
||||
@@ -173,7 +173,7 @@ export class Gesture extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private onTouchEnd(e: TouchEvent): void {
|
||||
private onTouchEnd(targetWindow: Window, e: TouchEvent): void {
|
||||
const timestamp = Date.now(); // use Date.now() because on FF e.timeStamp is not epoch based.
|
||||
|
||||
const activeTouchCount = Object.keys(this.activeTouches).length;
|
||||
@@ -218,13 +218,13 @@ export class Gesture extends Disposable {
|
||||
|
||||
// We need to get all the dispatch targets on the start of the inertia event
|
||||
const dispatchTo = [...this.targets].filter(t => data.initialTarget instanceof Node && t.contains(data.initialTarget));
|
||||
this.inertia(dispatchTo, timestamp, // time now
|
||||
Math.abs(deltaX) / deltaT, // speed
|
||||
deltaX > 0 ? 1 : -1, // x direction
|
||||
finalX, // x now
|
||||
Math.abs(deltaY) / deltaT, // y speed
|
||||
deltaY > 0 ? 1 : -1, // y direction
|
||||
finalY // y now
|
||||
this.inertia(targetWindow, dispatchTo, timestamp, // time now
|
||||
Math.abs(deltaX) / deltaT, // speed
|
||||
deltaX > 0 ? 1 : -1, // x direction
|
||||
finalX, // x now
|
||||
Math.abs(deltaY) / deltaT, // y speed
|
||||
deltaY > 0 ? 1 : -1, // y direction
|
||||
finalY // y now
|
||||
);
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ export class Gesture extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private inertia(dispatchTo: readonly EventTarget[], t1: number, vX: number, dirX: number, x: number, vY: number, dirY: number, y: number): void {
|
||||
private inertia(targetWindow: Window, dispatchTo: readonly EventTarget[], t1: number, vX: number, dirX: number, x: number, vY: number, dirY: number, y: number): void {
|
||||
this.handle = DomUtils.scheduleAtNextAnimationFrame(() => {
|
||||
const now = Date.now();
|
||||
|
||||
@@ -311,9 +311,9 @@ export class Gesture extends Disposable {
|
||||
dispatchTo.forEach(d => d.dispatchEvent(evt));
|
||||
|
||||
if (!stopped) {
|
||||
this.inertia(dispatchTo, now, vX, dirX, x + delta_pos_x, vY, dirY, y + delta_pos_y);
|
||||
this.inertia(targetWindow, dispatchTo, now, vX, dirX, x + delta_pos_x, vY, dirY, y + delta_pos_y);
|
||||
}
|
||||
});
|
||||
}, targetWindow);
|
||||
}
|
||||
|
||||
private onTouchMove(e: TouchEvent): void {
|
||||
|
||||
@@ -128,7 +128,7 @@ export class BreadcrumbsWidget {
|
||||
this._domNode.style.width = `${dim.width}px`;
|
||||
this._domNode.style.height = `${dim.height}px`;
|
||||
disposables.add(this._updateScrollbar());
|
||||
}));
|
||||
}, dom.getWindow(this._domNode)));
|
||||
return disposables;
|
||||
}
|
||||
|
||||
@@ -138,8 +138,8 @@ export class BreadcrumbsWidget {
|
||||
this._scrollable.setRevealOnScroll(false);
|
||||
this._scrollable.scanDomNode();
|
||||
this._scrollable.setRevealOnScroll(true);
|
||||
});
|
||||
});
|
||||
}, dom.getWindow(this._domNode));
|
||||
}, dom.getWindow(this._domNode));
|
||||
}
|
||||
|
||||
private _style(styleElement: HTMLStyleElement, style: IBreadcrumbsWidgetStyles): void {
|
||||
|
||||
@@ -617,16 +617,22 @@ export class HistoryInputBox extends InputBox implements IHistoryNavigationWidge
|
||||
readonly onDidBlur = this._onDidBlur.event;
|
||||
|
||||
constructor(container: HTMLElement, contextViewProvider: IContextViewProvider | undefined, options: IHistoryInputOptions) {
|
||||
const NLS_PLACEHOLDER_HISTORY_HINT = nls.localize({ key: 'history.inputbox.hint', comment: ['Text will be prefixed with \u21C5 plus a single space, then used as a hint where input field keeps history'] }, "for history");
|
||||
const NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX = ` or \u21C5 ${NLS_PLACEHOLDER_HISTORY_HINT}`;
|
||||
const NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS = ` (\u21C5 ${NLS_PLACEHOLDER_HISTORY_HINT})`;
|
||||
const NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_NO_PARENS = nls.localize({
|
||||
key: 'history.inputbox.hint.suffix.noparens',
|
||||
comment: ['Text is the suffix of an input field placeholder coming after the action the input field performs, this will be used when the input field ends in a closing parenthesis ")", for example "Filter (e.g. text, !exclude)". The character inserted into the final string is \u21C5 to represent the up and down arrow keys.']
|
||||
}, ' or {0} for history', `\u21C5`);
|
||||
const NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS = nls.localize({
|
||||
key: 'history.inputbox.hint.suffix.inparens',
|
||||
comment: ['Text is the suffix of an input field placeholder coming after the action the input field performs, this will be used when the input field does NOT end in a closing parenthesis (eg. "Find"). The character inserted into the final string is \u21C5 to represent the up and down arrow keys.']
|
||||
}, ' ({0} for history)', `\u21C5`);
|
||||
|
||||
super(container, contextViewProvider, options);
|
||||
this.history = new HistoryNavigator<string>(options.history, 100);
|
||||
|
||||
// Function to append the history suffix to the placeholder if necessary
|
||||
const addSuffix = () => {
|
||||
if (options.showHistoryHint && options.showHistoryHint() && !this.placeholder.endsWith(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX) && !this.placeholder.endsWith(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS) && this.history.getHistory().length) {
|
||||
const suffix = this.placeholder.endsWith(')') ? NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX : NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS;
|
||||
if (options.showHistoryHint && options.showHistoryHint() && !this.placeholder.endsWith(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_NO_PARENS) && !this.placeholder.endsWith(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS) && this.history.getHistory().length) {
|
||||
const suffix = this.placeholder.endsWith(')') ? NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_NO_PARENS : NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS;
|
||||
const suffixedPlaceholder = this.placeholder + suffix;
|
||||
if (options.showPlaceholderOnFocus && !dom.isActiveElement(this.input)) {
|
||||
this.placeholder = suffixedPlaceholder;
|
||||
@@ -666,7 +672,7 @@ export class HistoryInputBox extends InputBox implements IHistoryNavigationWidge
|
||||
}
|
||||
};
|
||||
if (!resetPlaceholder(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_IN_PARENS)) {
|
||||
resetPlaceholder(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX);
|
||||
resetPlaceholder(NLS_PLACEHOLDER_HISTORY_HINT_SUFFIX_NO_PARENS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd';
|
||||
import { $, addDisposableListener, animate, Dimension, getContentHeight, getContentWidth, getTopLeftOffset, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { $, addDisposableListener, animate, Dimension, getContentHeight, getContentWidth, getTopLeftOffset, getWindow, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { EventType as TouchEventType, Gesture, GestureEvent } from 'vs/base/browser/touch';
|
||||
@@ -407,7 +407,7 @@ export class ListView<T> implements IListView<T> {
|
||||
this.scrollable = this.disposables.add(new Scrollable({
|
||||
forceIntegerValues: true,
|
||||
smoothScrollDuration: (options.smoothScrolling ?? false) ? 125 : 0,
|
||||
scheduleAtNextAnimationFrame: cb => scheduleAtNextAnimationFrame(cb)
|
||||
scheduleAtNextAnimationFrame: cb => scheduleAtNextAnimationFrame(cb, getWindow(this.domNode))
|
||||
}));
|
||||
this.scrollableElement = this.disposables.add(new SmoothScrollableElement(this.rowsContainer, {
|
||||
alwaysConsumeMouseWheel: options.alwaysConsumeMouseWheel ?? DefaultOptions.alwaysConsumeMouseWheel,
|
||||
@@ -684,7 +684,7 @@ export class ListView<T> implements IListView<T> {
|
||||
this.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight });
|
||||
this.updateScrollWidth();
|
||||
this.scrollableElementUpdateDisposable = null;
|
||||
});
|
||||
}, getWindow(this.domNode));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1291,7 +1291,7 @@ export class ListView<T> implements IListView<T> {
|
||||
private setupDragAndDropScrollTopAnimation(event: DragEvent): void {
|
||||
if (!this.dragOverAnimationDisposable) {
|
||||
const viewTop = getTopLeftOffset(this.domNode).top;
|
||||
this.dragOverAnimationDisposable = animate(this.animateDragAndDropScrollTop.bind(this, viewTop));
|
||||
this.dragOverAnimationDisposable = animate(this.animateDragAndDropScrollTop.bind(this, viewTop), getWindow(this.domNode));
|
||||
}
|
||||
|
||||
this.dragOverAnimationStopDisposable.dispose();
|
||||
|
||||
@@ -630,7 +630,7 @@ export class MenuBar extends Disposable {
|
||||
this.overflowLayoutScheduled = DOM.scheduleAtNextAnimationFrame(() => {
|
||||
this.updateOverflowAction();
|
||||
this.overflowLayoutScheduled = undefined;
|
||||
});
|
||||
}, DOM.getWindow(this.container));
|
||||
}
|
||||
|
||||
this.setUnfocusedState();
|
||||
|
||||
@@ -576,7 +576,7 @@ export class ScrollableElement extends AbstractScrollableElement {
|
||||
const scrollable = new Scrollable({
|
||||
forceIntegerValues: true,
|
||||
smoothScrollDuration: 0,
|
||||
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback)
|
||||
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback, dom.getWindow(element))
|
||||
});
|
||||
super(element, options, scrollable);
|
||||
this._register(scrollable);
|
||||
@@ -621,7 +621,7 @@ export class DomScrollableElement extends AbstractScrollableElement {
|
||||
const scrollable = new Scrollable({
|
||||
forceIntegerValues: false, // See https://github.com/microsoft/vscode/issues/139877
|
||||
smoothScrollDuration: 0,
|
||||
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback)
|
||||
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback, dom.getWindow(element))
|
||||
});
|
||||
super(element, options, scrollable);
|
||||
this._register(scrollable);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { $, addDisposableListener, append, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { $, addDisposableListener, append, getWindow, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
import { ISashEvent as IBaseSashEvent, Orientation, Sash, SashState } from 'vs/base/browser/ui/sash/sash';
|
||||
import { SmoothScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
@@ -584,7 +584,7 @@ export class SplitView<TLayoutContext = undefined, TView extends IView<TLayoutCo
|
||||
this.scrollable = this._register(new Scrollable({
|
||||
forceIntegerValues: true,
|
||||
smoothScrollDuration: 125,
|
||||
scheduleAtNextAnimationFrame
|
||||
scheduleAtNextAnimationFrame: callback => scheduleAtNextAnimationFrame(callback, getWindow(this.el)),
|
||||
}));
|
||||
this.scrollableElement = this._register(new SmoothScrollableElement(this.viewContainer, {
|
||||
vertical: this.orientation === Orientation.VERTICAL ? (options.scrollbarVisibility ?? ScrollbarVisibility.Auto) : ScrollbarVisibility.Hidden,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IDimension } from 'vs/editor/common/core/dimension';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { getWindow, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
|
||||
export class ElementSizeObserver extends Disposable {
|
||||
|
||||
@@ -65,10 +66,10 @@ export class ElementSizeObserver extends Disposable {
|
||||
alreadyObservedThisAnimationFrame = true;
|
||||
observeNow();
|
||||
} finally {
|
||||
requestAnimationFrame(() => {
|
||||
scheduleAtNextAnimationFrame(() => {
|
||||
alreadyObservedThisAnimationFrame = false;
|
||||
update();
|
||||
});
|
||||
}, getWindow(this._referenceDomElement));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -682,7 +682,7 @@ class TopBottomDragScrollingOperation extends Disposable {
|
||||
this._position = position;
|
||||
this._mouseEvent = mouseEvent;
|
||||
this._lastTime = Date.now();
|
||||
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute());
|
||||
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute(), dom.getWindow(mouseEvent.browserEvent));
|
||||
}
|
||||
|
||||
public override dispose(): void {
|
||||
@@ -752,7 +752,7 @@ class TopBottomDragScrollingOperation extends Disposable {
|
||||
}
|
||||
|
||||
this._dispatchMouse(mouseTarget, true, NavigationCommandRevealType.None);
|
||||
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute());
|
||||
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute(), dom.getWindow(mouseTarget.element));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -432,7 +432,7 @@ export class View extends ViewEventHandler {
|
||||
|
||||
private _scheduleRender(): void {
|
||||
if (this._renderAnimationFrame === null) {
|
||||
this._renderAnimationFrame = dom.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), 100);
|
||||
this._renderAnimationFrame = dom.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), dom.getWindow(this.domNode.domNode), 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ export class ViewCursor {
|
||||
return null;
|
||||
}
|
||||
|
||||
const window = dom.getWindow(this._domNode);
|
||||
const window = dom.getWindow(this._domNode.domNode);
|
||||
let width: number;
|
||||
if (this._cursorStyle === TextEditorCursorStyle.Line) {
|
||||
width = dom.computeScreenAwareSize(window, this._lineCursorWidth > 0 ? this._lineCursorWidth : 2);
|
||||
|
||||
@@ -1648,7 +1648,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
model,
|
||||
DOMLineBreaksComputerFactory.create(),
|
||||
MonospaceLineBreaksComputerFactory.create(this._configuration.options),
|
||||
(callback) => dom.scheduleAtNextAnimationFrame(callback),
|
||||
(callback) => dom.scheduleAtNextAnimationFrame(callback, dom.getWindow(this._domElement)),
|
||||
this.languageConfigurationService,
|
||||
this._themeService,
|
||||
attachedView,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { $, h } from 'vs/base/browser/dom';
|
||||
import { $, getWindow, h } from 'vs/base/browser/dom';
|
||||
import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash';
|
||||
import { findLast } from 'vs/base/common/arraysFind';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
@@ -178,6 +178,7 @@ export class DiffEditorWidget extends DelegatingEditor implements IDiffEditor {
|
||||
/** @description ViewZoneManager */
|
||||
store.add(this._instantiationService.createInstance(
|
||||
readHotReloadableExport(ViewZoneManager, reader),
|
||||
getWindow(this._domElement),
|
||||
this._editors,
|
||||
this._diffModel,
|
||||
this._options,
|
||||
|
||||
@@ -42,14 +42,15 @@ export class ViewZoneManager extends Disposable {
|
||||
private readonly _originalTopPadding = observableValue(this, 0);
|
||||
private readonly _originalScrollTop: IObservable<number>;
|
||||
private readonly _originalScrollOffset = observableValue<number, boolean>(this, 0);
|
||||
private readonly _originalScrollOffsetAnimated = animatedObservable(this._originalScrollOffset, this._store);
|
||||
private readonly _originalScrollOffsetAnimated = animatedObservable(this._targetWindow, this._originalScrollOffset, this._store);
|
||||
|
||||
private readonly _modifiedTopPadding = observableValue(this, 0);
|
||||
private readonly _modifiedScrollTop: IObservable<number>;
|
||||
private readonly _modifiedScrollOffset = observableValue<number, boolean>(this, 0);
|
||||
private readonly _modifiedScrollOffsetAnimated = animatedObservable(this._modifiedScrollOffset, this._store);
|
||||
private readonly _modifiedScrollOffsetAnimated = animatedObservable(this._targetWindow, this._modifiedScrollOffset, this._store);
|
||||
|
||||
constructor(
|
||||
private readonly _targetWindow: Window,
|
||||
private readonly _editors: DiffEditorEditors,
|
||||
private readonly _diffModel: IObservable<DiffEditorViewModel | undefined>,
|
||||
private readonly _options: DiffEditorOptions,
|
||||
|
||||
@@ -123,7 +123,7 @@ export class ObservableElementSizeObserver extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
export function animatedObservable(base: IObservable<number, boolean>, store: DisposableStore): IObservable<number> {
|
||||
export function animatedObservable(targetWindow: Window, base: IObservable<number, boolean>, store: DisposableStore): IObservable<number> {
|
||||
let targetVal = base.get();
|
||||
let startVal = targetVal;
|
||||
let curVal = targetVal;
|
||||
@@ -160,7 +160,7 @@ export function animatedObservable(base: IObservable<number, boolean>, store: Di
|
||||
curVal = Math.floor(easeOutExpo(passedMs, startVal, targetVal - startVal, durationMs));
|
||||
|
||||
if (passedMs < durationMs) {
|
||||
animationFrame = requestAnimationFrame(update);
|
||||
animationFrame = targetWindow.requestAnimationFrame(update);
|
||||
} else {
|
||||
curVal = targetVal;
|
||||
}
|
||||
|
||||
@@ -571,7 +571,7 @@ export class SuggestWidget implements IDisposable {
|
||||
this._layout(this.element.size);
|
||||
// Reset focus border
|
||||
this._details.widget.domNode.classList.remove('focused');
|
||||
});
|
||||
}, dom.getWindow(this.element.domNode));
|
||||
}
|
||||
|
||||
focusSelected(): void {
|
||||
@@ -721,7 +721,7 @@ export class SuggestWidget implements IDisposable {
|
||||
this._positionDetails();
|
||||
this.editor.focus();
|
||||
this.element.domNode.classList.add('shows-details');
|
||||
});
|
||||
}, dom.getWindow(this.element.domNode));
|
||||
}
|
||||
|
||||
toggleExplainMode(): void {
|
||||
|
||||
@@ -41,6 +41,7 @@ class EditorScopedQuickInputService extends QuickInputService {
|
||||
_serviceBrand: undefined,
|
||||
get hasContainer() { return true; },
|
||||
get container() { return widget.getDomNode(); },
|
||||
getContainer() { return widget.getDomNode(); },
|
||||
get containers() { return [widget.getDomNode()]; },
|
||||
get activeContainer() { return widget.getDomNode(); },
|
||||
get mainContainerDimension() { return editor.getLayoutInfo(); },
|
||||
|
||||
@@ -54,6 +54,10 @@ class StandaloneLayoutService implements ILayoutService {
|
||||
return activeCodeEditor?.getContainerDomNode() ?? this.container;
|
||||
}
|
||||
|
||||
getContainer() {
|
||||
return this.activeContainer;
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
this._codeEditorService.getFocusedCodeEditor()?.focus();
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ export class MockScopableContextKeyService extends MockContextKeyService {
|
||||
* Don't implement this for all tests since we rarely depend on this behavior and it isn't implemented fully
|
||||
*/
|
||||
public override createScoped(domNote: HTMLElement): IScopedContextKeyService {
|
||||
return new MockContextKeyService();
|
||||
return new MockScopableContextKeyService();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,11 @@ export interface ILayoutService {
|
||||
*/
|
||||
readonly containers: Iterable<HTMLElement>;
|
||||
|
||||
/**
|
||||
* Get the container for the given window.
|
||||
*/
|
||||
getContainer(window: Window): HTMLElement;
|
||||
|
||||
/**
|
||||
* An offset to use for positioning elements inside the main container.
|
||||
*/
|
||||
|
||||
@@ -128,7 +128,7 @@ export class Menubar {
|
||||
this.fallbackMenuHandlers['workbench.action.openWorkspace'] = (menuItem, win, event) => this.nativeHostMainService.pickWorkspaceAndOpen(undefined, { forceNewWindow: this.isOptionClick(event), telemetryExtraData: { from: telemetryFrom } });
|
||||
|
||||
// Recent Menu Items
|
||||
this.fallbackMenuHandlers['workbench.action.clearRecentFiles'] = () => this.workspacesHistoryMainService.clearRecentlyOpened();
|
||||
this.fallbackMenuHandlers['workbench.action.clearRecentFiles'] = () => this.workspacesHistoryMainService.clearRecentlyOpened({ confirm: true /* ask for confirmation */ });
|
||||
|
||||
// Help Menu Items
|
||||
const youTubeUrl = this.productService.youTubeUrl;
|
||||
|
||||
@@ -377,10 +377,10 @@ export class CommandDetectionCapability extends Disposable implements ICommandDe
|
||||
// Conpty could have the wrong cursor position at this point.
|
||||
if (!this._cursorOnNextLine() || !prompt) {
|
||||
this._windowsPromptPollingInProcess = true;
|
||||
// Poll for 200ms until the cursor position is correct.
|
||||
// Poll for 1000ms until the cursor position is correct.
|
||||
let i = 0;
|
||||
for (; i < 20; i++) {
|
||||
await timeout(10);
|
||||
for (; i < 50; i++) {
|
||||
await timeout(20);
|
||||
prompt = this._getWindowsPrompt();
|
||||
if (this._store.isDisposed || !this._windowsPromptPollingInProcess || this._cursorOnNextLine() && prompt) {
|
||||
if (!this._windowsPromptPollingInProcess) {
|
||||
@@ -390,7 +390,7 @@ export class CommandDetectionCapability extends Disposable implements ICommandDe
|
||||
}
|
||||
}
|
||||
this._windowsPromptPollingInProcess = false;
|
||||
if (i === 20) {
|
||||
if (i >= 50) {
|
||||
this._logService.debug('CommandDetectionCapability#_handleCommandStartWindows reached max attempts, ', this._cursorOnNextLine(), this._getWindowsPrompt());
|
||||
} else if (prompt) {
|
||||
// use the regex to set the position as it's possible input has occurred
|
||||
@@ -428,9 +428,11 @@ export class CommandDetectionCapability extends Disposable implements ICommandDe
|
||||
private _cursorOnNextLine(): boolean {
|
||||
const lastCommand = this.commands.at(-1);
|
||||
|
||||
// There is only a single command, so this check is unnecessary
|
||||
if (!lastCommand) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
const cursorYAbsolute = this._terminal.buffer.active.baseY + this._terminal.buffer.active.cursorY;
|
||||
// If the cursor position is within the last command, we should poll.
|
||||
const lastCommandYAbsolute = (lastCommand.endMarker ? lastCommand.endMarker.line : lastCommand.marker?.line) ?? -1;
|
||||
@@ -442,8 +444,26 @@ export class CommandDetectionCapability extends Disposable implements ICommandDe
|
||||
if (!line) {
|
||||
return;
|
||||
}
|
||||
// TODO: fine tune prompt regex to accomodate for unique configurtions.
|
||||
return line.translateToString(true)?.match(/^(?<prompt>(\(.+\)\s)?(?:PS.+>\s)|(?:[A-Z]:\\.*>))/)?.groups?.prompt;
|
||||
// TODO: fine tune prompt regex to accomodate for unique configurations.
|
||||
const lineText = line.translateToString(true);
|
||||
if (!lineText) {
|
||||
return;
|
||||
}
|
||||
|
||||
// PowerShell
|
||||
const pwshMatch = lineText.match(/(?<prompt>(\(.+\)\s)?(?:PS.+>\s?))/);
|
||||
if (pwshMatch) {
|
||||
let prompt = pwshMatch?.groups?.prompt;
|
||||
if (lineText === prompt && prompt.endsWith('>')) {
|
||||
// Conpty may not 'render' the space at the end of the prompt
|
||||
prompt += ' ';
|
||||
}
|
||||
return prompt;
|
||||
}
|
||||
|
||||
// Command Prompt
|
||||
const cmdMatch = lineText.match(/^(?<prompt>(\(.+\)\s)?(?:[A-Z]:\\.*>))/);
|
||||
return cmdMatch?.groups?.prompt;
|
||||
}
|
||||
|
||||
handleGenericCommand(options?: IHandleCommandOptions): void {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { fail, strictEqual } from 'assert';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { ConsoleLogger, ILogService } from 'vs/platform/log/common/log';
|
||||
@@ -12,37 +11,30 @@ import { LogService } from 'vs/platform/log/common/logService';
|
||||
import { RequestStore } from 'vs/platform/terminal/common/requestStore';
|
||||
|
||||
suite('RequestStore', () => {
|
||||
let disposables: DisposableStore;
|
||||
let instantiationService: TestInstantiationService;
|
||||
|
||||
setup(() => {
|
||||
disposables = new DisposableStore();
|
||||
instantiationService = new TestInstantiationService();
|
||||
instantiationService.stub(ILogService, new LogService(new ConsoleLogger()));
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
instantiationService.dispose();
|
||||
disposables.dispose();
|
||||
});
|
||||
|
||||
ensureNoDisposablesAreLeakedInTestSuite();
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
|
||||
test('should resolve requests', async () => {
|
||||
const store: RequestStore<{ data: string }, { arg: string }> = disposables.add(instantiationService.createInstance(RequestStore<{ data: string }, { arg: string }>, undefined));
|
||||
const requestStore: RequestStore<{ data: string }, { arg: string }> = store.add(instantiationService.createInstance(RequestStore<{ data: string }, { arg: string }>, undefined));
|
||||
let eventArgs: { requestId: number; arg: string } | undefined;
|
||||
disposables.add(store.onCreateRequest(e => eventArgs = e));
|
||||
const request = store.createRequest({ arg: 'foo' });
|
||||
store.add(requestStore.onCreateRequest(e => eventArgs = e));
|
||||
const request = requestStore.createRequest({ arg: 'foo' });
|
||||
strictEqual(typeof eventArgs?.requestId, 'number');
|
||||
strictEqual(eventArgs?.arg, 'foo');
|
||||
store.acceptReply(eventArgs!.requestId, { data: 'bar' });
|
||||
requestStore.acceptReply(eventArgs!.requestId, { data: 'bar' });
|
||||
const result = await request;
|
||||
strictEqual(result.data, 'bar');
|
||||
});
|
||||
|
||||
test('should reject the promise when the request times out', async () => {
|
||||
const store: RequestStore<{ data: string }, { arg: string }> = disposables.add(instantiationService.createInstance(RequestStore<{ data: string }, { arg: string }>, 1));
|
||||
const request = store.createRequest({ arg: 'foo' });
|
||||
const requestStore: RequestStore<{ data: string }, { arg: string }> = store.add(instantiationService.createInstance(RequestStore<{ data: string }, { arg: string }>, 1));
|
||||
const request = requestStore.createRequest({ arg: 'foo' });
|
||||
let threw = false;
|
||||
try {
|
||||
await request;
|
||||
|
||||
@@ -13,7 +13,7 @@ import { zoomLevelToZoomFactor } from 'vs/platform/window/common/window';
|
||||
* browser helper so that it can be accessed in non-electron layers.
|
||||
*/
|
||||
export function applyZoom(zoomLevel: number): void {
|
||||
for (const window of getWindows()) {
|
||||
for (const { window } of getWindows()) {
|
||||
getGlobals(window)?.webFrame?.setZoomLevel(zoomLevel);
|
||||
}
|
||||
setZoomFactor(zoomLevelToZoomFactor(zoomLevel));
|
||||
|
||||
@@ -24,6 +24,7 @@ import { IRecent, IRecentFile, IRecentFolder, IRecentlyOpened, IRecentWorkspace,
|
||||
import { IWorkspaceIdentifier, WORKSPACE_EXTENSION } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService';
|
||||
|
||||
export const IWorkspacesHistoryMainService = createDecorator<IWorkspacesHistoryMainService>('workspacesHistoryMainService');
|
||||
|
||||
@@ -36,7 +37,7 @@ export interface IWorkspacesHistoryMainService {
|
||||
addRecentlyOpened(recents: IRecent[]): Promise<void>;
|
||||
getRecentlyOpened(): Promise<IRecentlyOpened>;
|
||||
removeRecentlyOpened(paths: URI[]): Promise<void>;
|
||||
clearRecentlyOpened(): Promise<void>;
|
||||
clearRecentlyOpened(options?: { confirm?: boolean }): Promise<void>;
|
||||
}
|
||||
|
||||
export class WorkspacesHistoryMainService extends Disposable implements IWorkspacesHistoryMainService {
|
||||
@@ -54,7 +55,8 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@IWorkspacesManagementMainService private readonly workspacesManagementMainService: IWorkspacesManagementMainService,
|
||||
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
|
||||
@IApplicationStorageMainService private readonly applicationStorageMainService: IApplicationStorageMainService
|
||||
@IApplicationStorageMainService private readonly applicationStorageMainService: IApplicationStorageMainService,
|
||||
@IDialogMainService private readonly dialogMainService: IDialogMainService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -157,7 +159,24 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa
|
||||
}
|
||||
}
|
||||
|
||||
async clearRecentlyOpened(): Promise<void> {
|
||||
async clearRecentlyOpened(options?: { confirm?: boolean }): Promise<void> {
|
||||
if (options?.confirm) {
|
||||
const { response } = await this.dialogMainService.showMessageBox({
|
||||
type: 'warning',
|
||||
buttons: [
|
||||
localize({ key: 'clearButtonLabel', comment: ['&& denotes a mnemonic'] }, "&&Clear"),
|
||||
localize({ key: 'cancel', comment: ['&& denotes a mnemonic'] }, "&&Cancel")
|
||||
],
|
||||
message: localize('confirmClearRecentsMessage', "Do you want to clear all recently opened files and workspaces?"),
|
||||
detail: localize('confirmClearDetail', "This action is irreversible!"),
|
||||
cancelId: 1
|
||||
});
|
||||
|
||||
if (response !== 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await this.saveRecentlyOpened({ workspaces: [], files: [] });
|
||||
app.clearRecentDocuments();
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ import { localize } from 'vs/nls';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IDisposable, toDisposable, dispose, DisposableStore, setDisposableTracker, DisposableTracker, DisposableInfo } from 'vs/base/common/lifecycle';
|
||||
import { getDomNodePagePosition, createStyleSheet, createCSSRule, append, $, getActiveDocument } from 'vs/base/browser/dom';
|
||||
import { getDomNodePagePosition, createStyleSheet, createCSSRule, append, $, getActiveDocument, onDidRegisterWindow, getWindows } from 'vs/base/browser/dom';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ContextKeyExpr, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { Context } from 'vs/platform/contextkey/browser/contextKeyService';
|
||||
@@ -130,13 +130,34 @@ class ToggleScreencastModeAction extends Action2 {
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
const container = layoutService.container;
|
||||
const container = layoutService.activeContainer;
|
||||
|
||||
const mouseMarker = append(container, $('.screencast-mouse'));
|
||||
disposables.add(toDisposable(() => mouseMarker.remove()));
|
||||
|
||||
const onMouseDown = disposables.add(new DomEmitter(container, 'mousedown', true));
|
||||
const onMouseUp = disposables.add(new DomEmitter(container, 'mouseup', true));
|
||||
const onMouseMove = disposables.add(new DomEmitter(container, 'mousemove', true));
|
||||
const keyboardMarker = append(container, $('.screencast-keyboard'));
|
||||
disposables.add(toDisposable(() => keyboardMarker.remove()));
|
||||
|
||||
const onMouseDown = disposables.add(new Emitter<MouseEvent>());
|
||||
const onMouseUp = disposables.add(new Emitter<MouseEvent>());
|
||||
const onMouseMove = disposables.add(new Emitter<MouseEvent>());
|
||||
|
||||
function registerContainerListeners(container: HTMLElement, disposables: DisposableStore): void {
|
||||
disposables.add(disposables.add(new DomEmitter(container, 'mousedown', true)).event(e => onMouseDown.fire(e)));
|
||||
disposables.add(disposables.add(new DomEmitter(container, 'mouseup', true)).event(e => onMouseUp.fire(e)));
|
||||
disposables.add(disposables.add(new DomEmitter(container, 'mousemove', true)).event(e => onMouseMove.fire(e)));
|
||||
}
|
||||
|
||||
for (const { window, disposables } of getWindows()) {
|
||||
registerContainerListeners(layoutService.getContainer(window), disposables);
|
||||
}
|
||||
|
||||
disposables.add(onDidRegisterWindow(({ window, disposables }) => registerContainerListeners(layoutService.getContainer(window), disposables)));
|
||||
|
||||
disposables.add(layoutService.onDidChangeActiveContainer(() => {
|
||||
layoutService.activeContainer.appendChild(mouseMarker);
|
||||
layoutService.activeContainer.appendChild(keyboardMarker);
|
||||
}));
|
||||
|
||||
const updateMouseIndicatorColor = () => {
|
||||
mouseMarker.style.borderColor = Color.fromHex(configurationService.getValue<string>('screencastMode.mouseIndicatorColor')).toString();
|
||||
@@ -172,9 +193,6 @@ class ToggleScreencastModeAction extends Action2 {
|
||||
});
|
||||
}));
|
||||
|
||||
const keyboardMarker = append(container, $('.screencast-keyboard'));
|
||||
disposables.add(toDisposable(() => keyboardMarker.remove()));
|
||||
|
||||
const updateKeyboardFontSize = () => {
|
||||
keyboardMarker.style.fontSize = `${clamp(configurationService.getValue<number>('screencastMode.fontSize') || 56, 20, 100)}px`;
|
||||
};
|
||||
@@ -214,10 +232,23 @@ class ToggleScreencastModeAction extends Action2 {
|
||||
}
|
||||
}));
|
||||
|
||||
const onKeyDown = disposables.add(new DomEmitter(window, 'keydown', true));
|
||||
const onCompositionStart = disposables.add(new DomEmitter(window, 'compositionstart', true));
|
||||
const onCompositionUpdate = disposables.add(new DomEmitter(window, 'compositionupdate', true));
|
||||
const onCompositionEnd = disposables.add(new DomEmitter(window, 'compositionend', true));
|
||||
const onKeyDown = disposables.add(new Emitter<KeyboardEvent>());
|
||||
const onCompositionStart = disposables.add(new Emitter<CompositionEvent>());
|
||||
const onCompositionUpdate = disposables.add(new Emitter<CompositionEvent>());
|
||||
const onCompositionEnd = disposables.add(new Emitter<CompositionEvent>());
|
||||
|
||||
function registerWindowListeners(window: Window, disposables: DisposableStore): void {
|
||||
disposables.add(disposables.add(new DomEmitter(window, 'keydown', true)).event(e => onKeyDown.fire(e)));
|
||||
disposables.add(disposables.add(new DomEmitter(window, 'compositionstart', true)).event(e => onCompositionStart.fire(e)));
|
||||
disposables.add(disposables.add(new DomEmitter(window, 'compositionupdate', true)).event(e => onCompositionUpdate.fire(e)));
|
||||
disposables.add(disposables.add(new DomEmitter(window, 'compositionend', true)).event(e => onCompositionEnd.fire(e)));
|
||||
}
|
||||
|
||||
for (const { window, disposables } of getWindows()) {
|
||||
registerWindowListeners(window, disposables);
|
||||
}
|
||||
|
||||
disposables.add(onDidRegisterWindow(({ window, disposables }) => registerWindowListeners(window, disposables)));
|
||||
|
||||
let length = 0;
|
||||
let composing: Element | undefined = undefined;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, MaximizedEditorGroupContext, TitleBarVisibleContext, TitleBarStyleContext } from 'vs/workbench/common/contextkeys';
|
||||
import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds, TitleBarVisibleContext, TitleBarStyleContext, MultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';
|
||||
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor';
|
||||
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow } from 'vs/base/browser/dom';
|
||||
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
@@ -45,7 +45,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
|
||||
private activeEditorGroupLast: IContextKey<boolean>;
|
||||
private activeEditorGroupLocked: IContextKey<boolean>;
|
||||
private multipleEditorGroupsContext: IContextKey<boolean>;
|
||||
private maximizedEditorGroupContext: IContextKey<boolean>;
|
||||
|
||||
private editorsVisibleContext: IContextKey<boolean>;
|
||||
|
||||
@@ -139,7 +138,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
|
||||
this.activeEditorGroupLast = ActiveEditorGroupLastContext.bindTo(this.contextKeyService);
|
||||
this.activeEditorGroupLocked = ActiveEditorGroupLockedContext.bindTo(this.contextKeyService);
|
||||
this.multipleEditorGroupsContext = MultipleEditorGroupsContext.bindTo(this.contextKeyService);
|
||||
this.maximizedEditorGroupContext = MaximizedEditorGroupContext.bindTo(this.contextKeyService);
|
||||
|
||||
// Working Copies
|
||||
this.dirtyWorkingCopiesContext = DirtyWorkingCopiesContext.bindTo(this.contextKeyService);
|
||||
@@ -238,8 +236,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
|
||||
this._register(this.editorGroupService.onDidChangeActiveGroup(() => this.updateEditorGroupContextKeys()));
|
||||
this._register(this.editorGroupService.onDidChangeGroupLocked(() => this.updateEditorGroupContextKeys()));
|
||||
|
||||
this._register(this.editorGroupService.onDidChangeGroupMaximized((maximized) => this.maximizedEditorGroupContext.set(maximized)));
|
||||
|
||||
this._register(this.editorGroupService.onDidChangeEditorPartOptions(() => this.updateEditorAreaContextKeys()));
|
||||
|
||||
this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => disposables.add(addDisposableListener(window, EventType.FOCUS_IN, () => this.updateInputContextKeys(window.document), true)), { window, disposables: this._store }));
|
||||
|
||||
@@ -52,7 +52,7 @@ import { IAuxiliaryWindowService, isAuxiliaryWindow } from 'vs/workbench/service
|
||||
//#region Layout Implementation
|
||||
|
||||
interface ILayoutRuntimeState {
|
||||
activeContainer: 'main' | number /* window ID */;
|
||||
activeContainerId: 'main' | number /* window ID */;
|
||||
fullscreen: boolean;
|
||||
maximized: boolean;
|
||||
hasFocus: boolean;
|
||||
@@ -170,7 +170,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
get activeContainer() { return this.getContainerFromDocument(getActiveDocument()); }
|
||||
get containers(): Iterable<HTMLElement> {
|
||||
const containers: HTMLElement[] = [];
|
||||
for (const window of getWindows()) {
|
||||
for (const { window } of getWindows()) {
|
||||
containers.push(this.getContainerFromDocument(window.document));
|
||||
}
|
||||
|
||||
@@ -453,8 +453,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
private onWindowFocusChanged(hasFocus: boolean): void {
|
||||
if (hasFocus) {
|
||||
const activeContainerId = this.getActiveContainerId();
|
||||
if (this.state.runtime.activeContainer !== activeContainerId) {
|
||||
this.state.runtime.activeContainer = activeContainerId;
|
||||
if (this.state.runtime.activeContainerId !== activeContainerId) {
|
||||
this.state.runtime.activeContainerId = activeContainerId;
|
||||
this._onDidChangeActiveContainer.fire();
|
||||
}
|
||||
}
|
||||
@@ -615,7 +615,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
|
||||
// Layout Runtime State
|
||||
const layoutRuntimeState: ILayoutRuntimeState = {
|
||||
activeContainer: this.getActiveContainerId(),
|
||||
activeContainerId: this.getActiveContainerId(),
|
||||
fullscreen: isFullscreen(),
|
||||
hasFocus: this.hostService.hasFocus,
|
||||
maximized: false,
|
||||
@@ -1125,12 +1125,19 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
}
|
||||
}
|
||||
|
||||
getContainer(part: Parts): HTMLElement | undefined {
|
||||
if (!this.parts.get(part)) {
|
||||
return undefined;
|
||||
getContainer(window: Window): HTMLElement;
|
||||
getContainer(part: Parts): HTMLElement | undefined;
|
||||
getContainer(windowOrPart: Window | Parts): HTMLElement | undefined {
|
||||
if (typeof windowOrPart === 'string') {
|
||||
const part = windowOrPart;
|
||||
if (!this.parts.get(part)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this.getPart(part).getContainer();
|
||||
}
|
||||
|
||||
return this.getPart(part).getContainer();
|
||||
return this.getContainerFromDocument(windowOrPart.document);
|
||||
}
|
||||
|
||||
isVisible(part: Parts): boolean {
|
||||
@@ -1185,7 +1192,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
}
|
||||
|
||||
// with the command center enabled, we should always show
|
||||
if (this.configurationService.getValue<boolean>('window.commandCenter')) {
|
||||
if (this.configurationService.getValue<boolean>(LayoutSettings.COMMAND_CENTER)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import { IEditorPaneRegistry, EditorPaneDescriptor } from 'vs/workbench/browser/
|
||||
import { IEditorFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor';
|
||||
import {
|
||||
TextCompareEditorActiveContext, ActiveEditorPinnedContext, EditorGroupEditorsCountContext, ActiveEditorStickyContext, ActiveEditorAvailableEditorIdsContext,
|
||||
MultipleEditorGroupsContext, ActiveEditorDirtyContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext,
|
||||
EditorTabsVisibleContext, ActiveEditorLastInGroupContext, MaximizedEditorGroupContext
|
||||
EditorPartMultipleEditorGroupsContext, ActiveEditorDirtyContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext,
|
||||
EditorTabsVisibleContext, ActiveEditorLastInGroupContext, EditorPartMaximizedEditorGroupContext, MultipleEditorGroupsContext
|
||||
} from 'vs/workbench/common/contextkeys';
|
||||
import { SideBySideEditorInput, SideBySideEditorInputSerializer } from 'vs/workbench/common/editor/sideBySideEditorInput';
|
||||
import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor';
|
||||
@@ -384,8 +384,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: SHOW_EDITORS_IN
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: localize('closeAll', "Close All") }, group: '5_close', order: 10 });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: CLOSE_SAVED_EDITORS_COMMAND_ID, title: localize('closeAllSaved', "Close Saved") }, group: '5_close', order: 20 });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_KEEP_EDITORS_COMMAND_ID, title: localize('togglePreviewMode', "Enable Preview Editors"), toggled: ContextKeyExpr.has('config.workbench.editor.enablePreview') }, group: '7_settings', order: 10 });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('maximizeGroup', "Maximize Group") }, group: '8_group_operations', order: 5, when: ContextKeyExpr.and(MaximizedEditorGroupContext.negate(), MultipleEditorGroupsContext) });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('unmaximizeGroup', "Unmaximize Group") }, group: '8_group_operations', order: 5, when: MaximizedEditorGroupContext });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('maximizeGroup', "Maximize Group") }, group: '8_group_operations', order: 5, when: ContextKeyExpr.and(EditorPartMaximizedEditorGroupContext.negate(), EditorPartMultipleEditorGroupsContext) });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_MAXIMIZE_EDITOR_GROUP, title: localize('unmaximizeGroup', "Unmaximize Group") }, group: '8_group_operations', order: 5, when: EditorPartMaximizedEditorGroupContext });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_LOCK_GROUP_COMMAND_ID, title: localize('lockGroup', "Lock Group"), toggled: ActiveEditorGroupLockedContext }, group: '8_group_operations', order: 10, when: MultipleEditorGroupsContext });
|
||||
|
||||
function appendEditorToolItem(primary: ICommandAction, when: ContextKeyExpression | undefined, order: number, alternative?: ICommandAction, precondition?: ContextKeyExpression | undefined): void {
|
||||
@@ -601,7 +601,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarRecentMenu, {
|
||||
group: 'z_clear',
|
||||
command: {
|
||||
id: ClearRecentFilesAction.ID,
|
||||
title: localize({ key: 'miClearRecentOpen', comment: ['&& denotes a mnemonic'] }, "&&Clear Recently Opened")
|
||||
title: localize({ key: 'miClearRecentOpen', comment: ['&& denotes a mnemonic'] }, "&&Clear Recently Opened...")
|
||||
},
|
||||
order: 1
|
||||
});
|
||||
|
||||
@@ -28,7 +28,9 @@ export const DEFAULT_EDITOR_MAX_DIMENSIONS = new Dimension(Number.POSITIVE_INFIN
|
||||
export const DEFAULT_EDITOR_PART_OPTIONS: IEditorPartOptions = {
|
||||
showTabs: 'multiple',
|
||||
highlightModifiedTabs: false,
|
||||
tabCloseButton: 'right',
|
||||
tabActionLocation: 'right',
|
||||
tabActionCloseVisibility: true,
|
||||
tabActionUnpinVisibility: true,
|
||||
tabSizing: 'fit',
|
||||
tabSizingFixedMinWidth: 50,
|
||||
tabSizingFixedMaxWidth: 160,
|
||||
@@ -104,6 +106,8 @@ function validateEditorPartOptions(options: IEditorPartOptions): void {
|
||||
'wrapTabs',
|
||||
'scrollToSwitchTabs',
|
||||
'highlightModifiedTabs',
|
||||
'tabActionCloseVisibility',
|
||||
'tabActionUnpinVisibility',
|
||||
'pinnedTabsOnSeparateRow',
|
||||
'focusRecentEditorAfterClose',
|
||||
'showIcons',
|
||||
@@ -138,7 +142,7 @@ function validateEditorPartOptions(options: IEditorPartOptions): void {
|
||||
// String options
|
||||
const stringOptions: Array<[OptionalStringKey<IEditorPartOptions>, Array<string>]> = [
|
||||
['showTabs', ['multiple', 'single', 'none']],
|
||||
['tabCloseButton', ['left', 'right', 'off']],
|
||||
['tabActionLocation', ['left', 'right']],
|
||||
['tabSizing', ['fit', 'shrink', 'fixed']],
|
||||
['pinnedTabSizing', ['normal', 'compact', 'shrink']],
|
||||
['tabHeight', ['default', 'compact']],
|
||||
|
||||
@@ -33,7 +33,7 @@ import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { Categories } from 'vs/platform/action/common/actionCommonCategories';
|
||||
import { ActiveEditorAvailableEditorIdsContext, ActiveEditorContext, ActiveEditorGroupEmptyContext, MaximizedEditorGroupContext, MultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';
|
||||
import { ActiveEditorAvailableEditorIdsContext, ActiveEditorContext, ActiveEditorGroupEmptyContext, EditorPartMaximizedEditorGroupContext, EditorPartMultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { getActiveDocument } from 'vs/base/browser/dom';
|
||||
|
||||
@@ -1073,7 +1073,7 @@ export class MaximizeGroupHideSidebarAction extends Action2 {
|
||||
title: { value: localize('maximizeEditorHideSidebar', "Maximize Editor Group and Hide Side Bars"), original: 'Maximize Editor Group and Hide Side Bars' },
|
||||
f1: true,
|
||||
category: Categories.View,
|
||||
precondition: ContextKeyExpr.and(MaximizedEditorGroupContext.negate(), MultipleEditorGroupsContext)
|
||||
precondition: ContextKeyExpr.and(EditorPartMaximizedEditorGroupContext.negate(), EditorPartMultipleEditorGroupsContext)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1098,7 +1098,7 @@ export class ToggleMaximizeEditorGroupAction extends Action2 {
|
||||
title: { value: localize('toggleMaximizeEditorGroup', "Toggle Maximize Editor Group"), original: 'Toggle Maximize Editor Group' },
|
||||
f1: true,
|
||||
category: Categories.View,
|
||||
precondition: ContextKeyExpr.or(MultipleEditorGroupsContext, MaximizedEditorGroupContext),
|
||||
precondition: ContextKeyExpr.or(EditorPartMultipleEditorGroupsContext, EditorPartMaximizedEditorGroupContext),
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyM),
|
||||
@@ -1107,16 +1107,16 @@ export class ToggleMaximizeEditorGroupAction extends Action2 {
|
||||
id: MenuId.EditorTitle,
|
||||
order: -10000, // towards the front
|
||||
group: 'navigation',
|
||||
when: MaximizedEditorGroupContext
|
||||
when: EditorPartMaximizedEditorGroupContext
|
||||
},
|
||||
{
|
||||
id: MenuId.EmptyEditorGroup,
|
||||
order: -10000, // towards the front
|
||||
group: 'navigation',
|
||||
when: MaximizedEditorGroupContext
|
||||
when: EditorPartMaximizedEditorGroupContext
|
||||
}],
|
||||
icon: Codicon.screenFull,
|
||||
toggled: MaximizedEditorGroupContext,
|
||||
toggled: EditorPartMaximizedEditorGroupContext,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1600,7 +1600,7 @@ export class ClearRecentFilesAction extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: ClearRecentFilesAction.ID,
|
||||
title: { value: localize('clearRecentFiles', "Clear Recently Opened"), original: 'Clear Recently Opened' },
|
||||
title: { value: localize('clearRecentFiles', "Clear Recently Opened..."), original: 'Clear Recently Opened...' },
|
||||
f1: true,
|
||||
category: Categories.File
|
||||
});
|
||||
|
||||
@@ -28,8 +28,7 @@ const openFileNonMacOnly: WatermarkEntry = { text: localize('watermark.openFile'
|
||||
const openFolderNonMacOnly: WatermarkEntry = { text: localize('watermark.openFolder', "Open Folder"), id: 'workbench.action.files.openFolder', mac: false };
|
||||
const openFileOrFolderMacOnly: WatermarkEntry = { text: localize('watermark.openFileFolder', "Open File or Folder"), id: 'workbench.action.files.openFileFolder', mac: true };
|
||||
const openRecent: WatermarkEntry = { text: localize('watermark.openRecent', "Open Recent"), id: 'workbench.action.openRecent' };
|
||||
const newUntitledFile: WatermarkEntry = { text: localize('watermark.newUntitledFile', "New Untitled Text File"), id: 'workbench.action.files.newUntitledFile' };
|
||||
const newUntitledFileMacOnly: WatermarkEntry = Object.assign({ mac: true }, newUntitledFile);
|
||||
const newUntitledFileMacOnly: WatermarkEntry = { text: localize('watermark.newUntitledFile', "New Untitled Text File"), id: 'workbench.action.files.newUntitledFile', mac: true };
|
||||
const findInFiles: WatermarkEntry = { text: localize('watermark.findInFiles', "Find in Files"), id: 'workbench.action.findInFiles' };
|
||||
const toggleTerminal: WatermarkEntry = { text: localize({ key: 'watermark.toggleTerminal', comment: ['toggle is a verb here'] }, "Toggle Terminal"), id: 'workbench.action.terminal.toggleTerminal', when: ContextKeyExpr.equals('terminalProcessSupported', true) };
|
||||
const startDebugging: WatermarkEntry = { text: localize('watermark.startDebugging', "Start Debugging"), id: 'workbench.action.debug.start', when: ContextKeyExpr.equals('terminalProcessSupported', true) };
|
||||
|
||||
@@ -32,6 +32,9 @@ import { findGroup } from 'vs/workbench/services/editor/common/editorGroupFinder
|
||||
import { SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { EditorPartMaximizedEditorGroupContext, EditorPartMultipleEditorGroupsContext } from 'vs/workbench/common/contextkeys';
|
||||
|
||||
interface IEditorPartUIState {
|
||||
readonly serializedGrid: ISerializedGrid;
|
||||
@@ -140,6 +143,8 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
|
||||
|
||||
private container: HTMLElement | undefined;
|
||||
|
||||
private scopedInstantiationService!: IInstantiationService;
|
||||
|
||||
private centeredLayoutWidget!: CenteredViewLayout;
|
||||
|
||||
private gridWidget!: SerializableGrid<IEditorGroupView>;
|
||||
@@ -156,7 +161,8 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@IHostService private readonly hostService: IHostService
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService
|
||||
) {
|
||||
super(id, { hasTitle: false }, themeService, storageService, layoutService);
|
||||
|
||||
@@ -214,7 +220,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
|
||||
|
||||
readonly sideGroup: IEditorSideGroup = {
|
||||
openEditor: (editor, options) => {
|
||||
const [group] = this.instantiationService.invokeFunction(accessor => findGroup(accessor, { editor, options }, SIDE_GROUP));
|
||||
const [group] = this.scopedInstantiationService.invokeFunction(accessor => findGroup(accessor, { editor, options }, SIDE_GROUP));
|
||||
|
||||
return group.openEditor(editor, options);
|
||||
}
|
||||
@@ -624,11 +630,11 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
|
||||
// Create group view
|
||||
let groupView: IEditorGroupView;
|
||||
if (from instanceof EditorGroupView) {
|
||||
groupView = EditorGroupView.createCopy(from, this.editorPartsView, this, this.groupsLabel, this.count, this.instantiationService);
|
||||
groupView = EditorGroupView.createCopy(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService,);
|
||||
} else if (isSerializedEditorGroupModel(from)) {
|
||||
groupView = EditorGroupView.createFromSerialized(from, this.editorPartsView, this, this.groupsLabel, this.count, this.instantiationService);
|
||||
groupView = EditorGroupView.createFromSerialized(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService);
|
||||
} else {
|
||||
groupView = EditorGroupView.createNew(this.editorPartsView, this, this.groupsLabel, this.count, this.instantiationService);
|
||||
groupView = EditorGroupView.createNew(this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService);
|
||||
}
|
||||
|
||||
// Keep in map
|
||||
@@ -930,7 +936,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
|
||||
createEditorDropTarget(container: unknown, delegate: IEditorDropTargetDelegate): IDisposable {
|
||||
assertType(container instanceof HTMLElement);
|
||||
|
||||
return this.instantiationService.createInstance(EditorDropTarget, container, delegate);
|
||||
return this.scopedInstantiationService.createInstance(EditorDropTarget, container, delegate);
|
||||
}
|
||||
|
||||
//#region Part
|
||||
@@ -967,6 +973,12 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
|
||||
this.container.classList.add('content');
|
||||
parent.appendChild(this.container);
|
||||
|
||||
// Scoped instantiation service
|
||||
const scopedContextKeyService = this._register(this.contextKeyService.createScoped(this.container));
|
||||
this.scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection(
|
||||
[IContextKeyService, scopedContextKeyService]
|
||||
));
|
||||
|
||||
// Grid control
|
||||
this.doCreateGridControl(options);
|
||||
|
||||
@@ -977,6 +989,9 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
|
||||
// Drag & Drop support
|
||||
this.setupDragAndDropSupport(parent, this.container);
|
||||
|
||||
// Context keys
|
||||
this.handleContextKeys(scopedContextKeyService);
|
||||
|
||||
// Signal ready
|
||||
this.whenReadyPromise.complete();
|
||||
this._isReady = true;
|
||||
@@ -989,6 +1004,32 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
|
||||
return this.container;
|
||||
}
|
||||
|
||||
private handleContextKeys(contextKeyService: IContextKeyService): void {
|
||||
const multipleEditorGroupsContext = EditorPartMultipleEditorGroupsContext.bindTo(contextKeyService);
|
||||
const maximizedEditorGroupContext = EditorPartMaximizedEditorGroupContext.bindTo(contextKeyService);
|
||||
|
||||
const updateContextKeys = () => {
|
||||
const groupCount = this.count;
|
||||
if (groupCount > 1) {
|
||||
multipleEditorGroupsContext.set(true);
|
||||
} else {
|
||||
multipleEditorGroupsContext.reset();
|
||||
}
|
||||
|
||||
if (this.hasMaximizedGroup()) {
|
||||
maximizedEditorGroupContext.set(true);
|
||||
} else {
|
||||
maximizedEditorGroupContext.reset();
|
||||
}
|
||||
};
|
||||
|
||||
updateContextKeys();
|
||||
|
||||
this._register(this.onDidAddGroup(() => updateContextKeys()));
|
||||
this._register(this.onDidRemoveGroup(() => updateContextKeys()));
|
||||
this._register(this.onDidChangeGroupMaximized(() => updateContextKeys()));
|
||||
}
|
||||
|
||||
private setupDragAndDropSupport(parent: HTMLElement, container: HTMLElement): void {
|
||||
|
||||
// Editor drop target
|
||||
@@ -1335,9 +1376,10 @@ export class MainEditorPart extends EditorPart {
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@IHostService hostService: IHostService
|
||||
@IHostService hostService: IHostService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
) {
|
||||
super(editorPartsView, Parts.EDITOR_PART, '', false, instantiationService, themeService, configurationService, storageService, layoutService, hostService);
|
||||
super(editorPartsView, Parts.EDITOR_PART, '', false, instantiationService, themeService, configurationService, storageService, layoutService, hostService, contextKeyService);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1356,10 +1398,11 @@ export class AuxiliaryEditorPart extends EditorPart implements IAuxiliaryEditorP
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@IHostService hostService: IHostService
|
||||
@IHostService hostService: IHostService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
) {
|
||||
const id = AuxiliaryEditorPart.COUNTER++;
|
||||
super(editorPartsView, `workbench.parts.auxiliaryEditor.${id}`, groupsLabel, true, instantiationService, themeService, configurationService, storageService, layoutService, hostService);
|
||||
super(editorPartsView, `workbench.parts.auxiliaryEditor.${id}`, groupsLabel, true, instantiationService, themeService, configurationService, storageService, layoutService, hostService, contextKeyService);
|
||||
}
|
||||
|
||||
protected override saveState(): void {
|
||||
|
||||
@@ -315,7 +315,6 @@ const nlsMultiSelection = localize('multiSelection', "{0} selections");
|
||||
const nlsEOLLF = localize('endOfLineLineFeed', "LF");
|
||||
const nlsEOLCRLF = localize('endOfLineCarriageReturnLineFeed', "CRLF");
|
||||
|
||||
|
||||
export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
private readonly tabFocusModeElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
||||
@@ -335,6 +334,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
||||
private toRender: StateChange | undefined = undefined;
|
||||
|
||||
private editorService: IEditorService;
|
||||
private targetWindow = window;
|
||||
|
||||
constructor(
|
||||
@IEditorService editorService: IEditorService,
|
||||
@@ -570,7 +570,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
||||
if (toRender) {
|
||||
this.doRenderNow();
|
||||
}
|
||||
});
|
||||
}, this.targetWindow);
|
||||
} else {
|
||||
this.toRender.combine(changed);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export class EditorTitleControl extends Themable {
|
||||
}
|
||||
|
||||
private createBreadcrumbsControl(): BreadcrumbsControlFactory | undefined {
|
||||
if (this.groupsView.partOptions.showTabs !== 'multiple') {
|
||||
if (this.groupsView.partOptions.showTabs === 'single') {
|
||||
return undefined; // Single tabs have breadcrumbs inlined. No tabs have no breadcrumbs.
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ export class EditorTitleControl extends Themable {
|
||||
// Update editor tabs control if options changed
|
||||
if (
|
||||
oldOptions.showTabs !== newOptions.showTabs ||
|
||||
(newOptions.showTabs === 'multiple' && oldOptions.pinnedTabsOnSeparateRow !== newOptions.pinnedTabsOnSeparateRow)
|
||||
(newOptions.showTabs !== 'single' && oldOptions.pinnedTabsOnSeparateRow !== newOptions.pinnedTabsOnSeparateRow)
|
||||
) {
|
||||
// Clear old
|
||||
this.editorTabsControlDisposable.clear();
|
||||
|
||||
@@ -115,9 +115,9 @@
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.tab-actions-right,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.tab-actions-off:not(.sticky-compact),
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.close-action-off:not(.sticky-compact),
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.has-icon.tab-actions-right,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.has-icon.tab-actions-off:not(.sticky-compact) {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.has-icon.close-action-off:not(.sticky-compact) {
|
||||
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab actions is not left (unless sticky-compact) */
|
||||
}
|
||||
|
||||
@@ -205,9 +205,9 @@
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-left::after,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off::after,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-action-off::after,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.tab-actions-left::after,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.tab-actions-off::after {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.close-action-off::after {
|
||||
content: '';
|
||||
display: flex;
|
||||
flex: 0;
|
||||
@@ -310,7 +310,7 @@
|
||||
padding-right: 5px; /* with tab sizing shrink/fixed and badges, we want a right-padding because the close button is hidden */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.tab-actions-left):not(.tab-actions-off) .tab-label {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink:not(.tab-actions-left):not(.close-action-off) .tab-label {
|
||||
padding-right: 5px; /* ensure that the gradient does not show when tab actions show https://github.com/microsoft/vscode/issues/189625*/
|
||||
}
|
||||
|
||||
@@ -365,16 +365,16 @@
|
||||
overflow: visible; /* ...but still show the tab actions on hover, focus and when dirty or sticky */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off:not(.dirty):not(.sticky) > .tab-actions,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.sticky-compact > .tab-actions {
|
||||
display: none; /* hide the tab actions when we are configured to hide it (unless dirty or sticky, but always when sticky-compact) */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off:not(.dirty) > .tab-actions,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off.sticky-compact > .tab-actions {
|
||||
display: none; /* hide the tab actions when we are configured to hide it (unless dirty, but always when sticky-compact) */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-actions .action-label, /* always show tab actions for active tab */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-actions .action-label:focus, /* always show tab actions on focus */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover > .tab-actions .action-label, /* always show tab actions on hover */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-actions .action-label, /* always show tab actions on hover */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.sticky > .tab-actions .action-label, /* always show tab actions for sticky tabs */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.sticky:not(.pinned-action-off) > .tab-actions .action-label, /* always show tab actions for sticky tabs */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-actions .action-label { /* always show tab actions for dirty tabs */
|
||||
opacity: 1;
|
||||
}
|
||||
@@ -404,7 +404,7 @@
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-actions .action-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-actions .action-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-actions .action-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky > .tab-actions .action-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky:not(.pinned-action-off) > .tab-actions .action-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-actions .action-label {
|
||||
opacity: 0.5; /* show tab actions dimmed for inactive group */
|
||||
}
|
||||
@@ -415,25 +415,24 @@
|
||||
|
||||
/* Tab Actions: Off */
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off {
|
||||
padding-right: 10px; /* give a little bit more room if tab actions is off */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off:not(.sticky-compact),
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.tab-actions-off:not(.sticky-compact) {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-action-off:not(.sticky-compact),
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.close-action-off:not(.sticky-compact) {
|
||||
padding-right: 5px; /* we need less room when sizing is shrink/fixed (unless tab is sticky-compact) */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.dirty-border-top > .tab-actions {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off.dirty-border-top > .tab-actions {
|
||||
display: none; /* hide dirty state when highlightModifiedTabs is enabled and when running without tab actions */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.dirty:not(.dirty-border-top):not(.sticky-compact),
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.sticky:not(.sticky-compact) {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off.dirty:not(.dirty-border-top):not(.sticky-compact) {
|
||||
padding-right: 0; /* remove extra padding when we are running without tab actions (unless tab is sticky-compact) */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off > .tab-actions {
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-action-off > .tab-actions {
|
||||
pointer-events: none; /* don't allow tab actions to be clicked when running without tab actions */
|
||||
}
|
||||
|
||||
|
||||
@@ -745,7 +745,9 @@ export class MultiEditorTabsControl extends EditorTabsControl {
|
||||
// Redraw tabs when other options change
|
||||
if (
|
||||
oldOptions.labelFormat !== newOptions.labelFormat ||
|
||||
oldOptions.tabCloseButton !== newOptions.tabCloseButton ||
|
||||
oldOptions.tabActionLocation !== newOptions.tabActionLocation ||
|
||||
oldOptions.tabActionCloseVisibility !== newOptions.tabActionCloseVisibility ||
|
||||
oldOptions.tabActionUnpinVisibility !== newOptions.tabActionUnpinVisibility ||
|
||||
oldOptions.tabSizing !== newOptions.tabSizing ||
|
||||
oldOptions.pinnedTabSizing !== newOptions.pinnedTabSizing ||
|
||||
oldOptions.showIcons !== newOptions.showIcons ||
|
||||
@@ -1036,7 +1038,7 @@ export class MultiEditorTabsControl extends EditorTabsControl {
|
||||
|
||||
// Fixes https://github.com/microsoft/vscode/issues/18733
|
||||
tab.classList.add('dragged');
|
||||
scheduleAtNextAnimationFrame(() => tab.classList.remove('dragged'));
|
||||
scheduleAtNextAnimationFrame(() => tab.classList.remove('dragged'), getWindow(tab));
|
||||
}));
|
||||
|
||||
// Drop support
|
||||
@@ -1321,19 +1323,33 @@ export class MultiEditorTabsControl extends EditorTabsControl {
|
||||
this.redrawTabLabel(editor, tabIndex, tabContainer, tabLabelWidget, tabLabel);
|
||||
|
||||
// Action
|
||||
const tabAction = isTabSticky ? this.unpinEditorAction : this.closeEditorAction;
|
||||
if (!tabActionBar.hasAction(tabAction)) {
|
||||
const hasUnpinAction = isTabSticky && options.tabActionUnpinVisibility;
|
||||
const hasCloseAction = !hasUnpinAction && options.tabActionCloseVisibility;
|
||||
const hasAction = hasUnpinAction || hasCloseAction;
|
||||
|
||||
// If no action is visible, ensure to clear it
|
||||
if (!hasAction) {
|
||||
if (!tabActionBar.isEmpty()) {
|
||||
tabActionBar.clear();
|
||||
}
|
||||
}
|
||||
// If action is visible, ensure it is showing
|
||||
else {
|
||||
const tabAction = hasUnpinAction ? this.unpinEditorAction : this.closeEditorAction;
|
||||
if (!tabActionBar.hasAction(tabAction)) {
|
||||
if (!tabActionBar.isEmpty()) {
|
||||
tabActionBar.clear();
|
||||
}
|
||||
|
||||
tabActionBar.push(tabAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(tabAction) });
|
||||
tabActionBar.push(tabAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(tabAction) });
|
||||
}
|
||||
}
|
||||
|
||||
// Settings
|
||||
const tabActionsVisibility = isTabSticky && options.pinnedTabSizing === 'compact' ? 'off' /* treat sticky compact tabs as tabCloseButton: 'off' */ : options.tabCloseButton;
|
||||
for (const option of ['off', 'left', 'right']) {
|
||||
tabContainer.classList.toggle(`tab-actions-${option}`, tabActionsVisibility === option);
|
||||
tabContainer.classList.toggle(`pinned-action-off`, isTabSticky && !hasUnpinAction);
|
||||
tabContainer.classList.toggle(`close-action-off`, !hasUnpinAction && !hasCloseAction);
|
||||
|
||||
for (const option of ['left', 'right']) {
|
||||
tabContainer.classList.toggle(`tab-actions-${option}`, hasAction && options.tabActionLocation === option);
|
||||
}
|
||||
|
||||
const tabSizing = isTabSticky && options.pinnedTabSizing === 'shrink' ? 'shrink' /* treat sticky shrink tabs as tabSizing: 'shrink' */ : options.tabSizing;
|
||||
@@ -1593,16 +1609,25 @@ export class MultiEditorTabsControl extends EditorTabsControl {
|
||||
Object.assign(this.dimensions, dimensions);
|
||||
|
||||
if (this.visible) {
|
||||
// The layout of tabs can be an expensive operation because we access DOM properties
|
||||
// that can result in the browser doing a full page layout to validate them. To buffer
|
||||
// this a little bit we try at least to schedule this work on the next animation frame
|
||||
// when we have restored or when idle otherwise.
|
||||
if (!this.layoutScheduler.value) {
|
||||
const scheduledLayout = (this.lifecycleService.phase >= LifecyclePhase.Restored ? scheduleAtNextAnimationFrame : runWhenIdle)(() => {
|
||||
|
||||
// The layout of tabs can be an expensive operation because we access DOM properties
|
||||
// that can result in the browser doing a full page layout to validate them. To buffer
|
||||
// this a little bit we try at least to schedule this work on the next animation frame
|
||||
// when we have restored or when idle otherwise.
|
||||
|
||||
const layoutFunction = () => {
|
||||
this.doLayout(this.dimensions, this.layoutScheduler.value?.options /* ensure to pick up latest options */);
|
||||
|
||||
this.layoutScheduler.clear();
|
||||
});
|
||||
};
|
||||
|
||||
let scheduledLayout: IDisposable;
|
||||
if (this.lifecycleService.phase >= LifecyclePhase.Restored) {
|
||||
scheduledLayout = scheduleAtNextAnimationFrame(layoutFunction, getWindow(this.tabsContainer));
|
||||
} else {
|
||||
scheduledLayout = runWhenIdle(layoutFunction);
|
||||
}
|
||||
|
||||
this.layoutScheduler.value = { options, dispose: () => scheduledLayout.dispose() };
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { IEditorTitleControlDimensions } from 'vs/workbench/browser/parts/editor
|
||||
import { IToolbarActions } from 'vs/workbench/common/editor';
|
||||
|
||||
export class NoEditorTabsControl extends EditorTabsControl {
|
||||
private activeEditor: EditorInput | null = null;
|
||||
|
||||
protected prepareEditorActions(editorActions: IToolbarActions): IToolbarActions {
|
||||
return {
|
||||
@@ -20,10 +21,27 @@ export class NoEditorTabsControl extends EditorTabsControl {
|
||||
}
|
||||
|
||||
openEditor(editor: EditorInput): boolean {
|
||||
return false;
|
||||
return this.handleOpenedEditors();
|
||||
}
|
||||
|
||||
openEditors(editors: EditorInput[]): boolean {
|
||||
return this.handleOpenedEditors();
|
||||
}
|
||||
|
||||
private handleOpenedEditors(): boolean {
|
||||
const didChange = this.activeEditorChanged();
|
||||
this.activeEditor = this.tabsModel.activeEditor;
|
||||
return didChange;
|
||||
}
|
||||
|
||||
private activeEditorChanged(): boolean {
|
||||
if (
|
||||
!this.activeEditor && this.tabsModel.activeEditor || // active editor changed from null => editor
|
||||
this.activeEditor && !this.tabsModel.activeEditor || // active editor changed from editor => null
|
||||
(!this.activeEditor || !this.tabsModel.isActive(this.activeEditor)) // active editor changed from editorA => editorB
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'vs/css!./media/notificationsToasts';
|
||||
import { localize } from 'vs/nls';
|
||||
import { INotificationsModel, NotificationChangeType, INotificationChangeEvent, INotificationViewItem, NotificationViewItemContentChangeKind } from 'vs/workbench/common/notifications';
|
||||
import { IDisposable, dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { addDisposableListener, EventType, Dimension, scheduleAtNextAnimationFrame, isAncestorOfActiveElement } from 'vs/base/browser/dom';
|
||||
import { addDisposableListener, EventType, Dimension, scheduleAtNextAnimationFrame, isAncestorOfActiveElement, getWindow } from 'vs/base/browser/dom';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { NotificationsList } from 'vs/workbench/browser/parts/notifications/notificationsList';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
@@ -150,7 +150,7 @@ export class NotificationsToasts extends Themable implements INotificationsToast
|
||||
// (see also https://github.com/microsoft/vscode/issues/107935)
|
||||
const itemDisposables = new DisposableStore();
|
||||
this.mapNotificationToDisposable.set(item, itemDisposables);
|
||||
itemDisposables.add(scheduleAtNextAnimationFrame(() => this.doAddToast(item, itemDisposables)));
|
||||
itemDisposables.add(scheduleAtNextAnimationFrame(() => this.doAddToast(item, itemDisposables), getWindow(this.container)));
|
||||
}
|
||||
|
||||
private doAddToast(item: INotificationViewItem, itemDisposables: DisposableStore): void {
|
||||
|
||||
@@ -24,7 +24,7 @@ import { CustomMenubarControl } from 'vs/workbench/browser/parts/titlebar/menuba
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { Parts, IWorkbenchLayoutService, LayoutSettings, ActivityBarPosition } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { Parts, IWorkbenchLayoutService, ActivityBarPosition, LayoutSettings } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { createActionViewItem, createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { Action2, IMenu, IMenuService, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { ContextKeyExpr, ContextKeyExpression, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
@@ -54,8 +54,6 @@ import { IEditorCommandsContext, IToolbarActions } from 'vs/workbench/common/edi
|
||||
|
||||
export class TitlebarPart extends Part implements ITitleService {
|
||||
|
||||
private static readonly configCommandCenter = 'window.commandCenter';
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
//#region IView
|
||||
@@ -159,7 +157,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
}
|
||||
|
||||
get isCommandCenterVisible() {
|
||||
return this.configurationService.getValue<boolean>(TitlebarPart.configCommandCenter);
|
||||
return this.configurationService.getValue<boolean>(LayoutSettings.COMMAND_CENTER);
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
@@ -202,7 +200,7 @@ export class TitlebarPart extends Part implements ITitleService {
|
||||
}
|
||||
}
|
||||
|
||||
if (event.affectsConfiguration(TitlebarPart.configCommandCenter)) {
|
||||
if (event.affectsConfiguration(LayoutSettings.COMMAND_CENTER)) {
|
||||
this.updateTitle();
|
||||
this._onDidChangeCommandCenterVisibility.fire();
|
||||
this._onDidChange.fire(undefined);
|
||||
@@ -640,7 +638,7 @@ class ToogleConfigAction extends Action2 {
|
||||
|
||||
registerAction2(class ToogleCommandCenter extends ToogleConfigAction {
|
||||
constructor() {
|
||||
super('window.commandCenter', localize('toggle.commandCenter', 'Command Center'), 1);
|
||||
super(LayoutSettings.COMMAND_CENTER, localize('toggle.commandCenter', 'Command Center'), 1);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { ConfigurationMigrationWorkbenchContribution, DynamicWorkbenchConfigurat
|
||||
import { isStandalone } from 'vs/base/browser/browser';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { ActivityBarPosition, LayoutSettings } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { ActivityBarPosition, EditorTabsMode, LayoutSettings } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
|
||||
const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
|
||||
@@ -38,9 +38,9 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
|
||||
description: localize('tabScrollbarHeight', "Controls the height of the scrollbars used for tabs and breadcrumbs in the editor title area."),
|
||||
default: 'default',
|
||||
},
|
||||
'workbench.editor.showTabs': {
|
||||
[LayoutSettings.EDITOR_TABS_MODE]: {
|
||||
'type': 'string',
|
||||
'enum': ['multiple', 'single', 'none'],
|
||||
'enum': [EditorTabsMode.MULTIPLE, EditorTabsMode.SINGLE, EditorTabsMode.NONE],
|
||||
'enumDescriptions': [
|
||||
localize('workbench.editor.showTabs.multiple', "Each editor is displayed as a tab in the editor title area."),
|
||||
localize('workbench.editor.showTabs.single', "The active editor is displayed as a single large tab in the editor title area."),
|
||||
@@ -153,11 +153,21 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
|
||||
}
|
||||
}
|
||||
},
|
||||
'workbench.editor.tabCloseButton': {
|
||||
'type': 'string',
|
||||
'enum': ['left', 'right', 'off'],
|
||||
'default': 'right',
|
||||
'markdownDescription': localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'editorTabCloseButton' }, "Controls the position of the editor's tabs close buttons, or disables them when set to 'off'. This value is ignored when `#workbench.editor.showTabs#` is not set to `multiple`.")
|
||||
'workbench.editor.tabActionLocation': {
|
||||
type: 'string',
|
||||
enum: ['left', 'right'],
|
||||
default: 'right',
|
||||
markdownDescription: localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'tabActionLocation' }, "Controls the position of the editor's tabs action buttons (close, unpin). This value is ignored when `#workbench.editor.showTabs#` is not set to `multiple`.")
|
||||
},
|
||||
'workbench.editor.tabActionCloseVisibility': {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: localize('workbench.editor.tabActionCloseVisibility', "Controls the visibility of the tab close action button.")
|
||||
},
|
||||
'workbench.editor.tabActionUnpinVisibility': {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: localize('workbench.editor.tabActionUnpinVisibility', "Controls the visibility of the tab unpin action button.")
|
||||
},
|
||||
'workbench.editor.tabSizing': {
|
||||
'type': 'string',
|
||||
@@ -632,7 +642,7 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
|
||||
'default': isMacintosh ? ' \u2014 ' : ' - ',
|
||||
'markdownDescription': localize("window.titleSeparator", "Separator used by {0}.", '`#window.title#`')
|
||||
},
|
||||
'window.commandCenter': {
|
||||
[LayoutSettings.COMMAND_CENTER]: {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
markdownDescription: isWeb ?
|
||||
@@ -806,11 +816,21 @@ Registry.as<IConfigurationMigrationRegistry>(Extensions.ConfigurationMigration)
|
||||
return [['workbench.editor.doubleClickTabToToggleEditorGroupSizes', { value: value }]];
|
||||
}
|
||||
}, {
|
||||
key: 'workbench.editor.showTabs', migrateFn: (value: any) => {
|
||||
key: LayoutSettings.EDITOR_TABS_MODE, migrateFn: (value: any) => {
|
||||
if (typeof value === 'boolean') {
|
||||
value = value ? 'multiple' : 'single';
|
||||
value = value ? EditorTabsMode.MULTIPLE : EditorTabsMode.SINGLE;
|
||||
}
|
||||
return [['workbench.editor.showTabs', { value: value }]];
|
||||
return [[LayoutSettings.EDITOR_TABS_MODE, { value }]];
|
||||
}
|
||||
}, {
|
||||
key: 'workbench.editor.tabCloseButton', migrateFn: (value: any) => {
|
||||
const result: ConfigurationKeyValuePairs = [];
|
||||
if (value === 'left' || value === 'right') {
|
||||
result.push(['workbench.editor.tabActionLocation', { value }]);
|
||||
} else if (value === 'off') {
|
||||
result.push(['workbench.editor.tabActionCloseVisibility', { value: false }]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}, {
|
||||
key: 'zenMode.hideTabs', migrateFn: (value: any) => {
|
||||
|
||||
@@ -71,6 +71,11 @@ export const ActiveEditorGroupLockedContext = new RawContextKey<boolean>('active
|
||||
export const MultipleEditorGroupsContext = new RawContextKey<boolean>('multipleEditorGroups', false, localize('multipleEditorGroups', "Whether there are multiple editor groups opened"));
|
||||
export const SingleEditorGroupsContext = MultipleEditorGroupsContext.toNegated();
|
||||
|
||||
// Editor Part Context Keys
|
||||
export const EditorPartMultipleEditorGroupsContext = new RawContextKey<boolean>('editorPartMultipleEditorGroups', false, localize('editorPartMultipleEditorGroups', "Whether there are multiple editor groups opened in an editor part"));
|
||||
export const EditorPartSingleEditorGroupsContext = EditorPartMultipleEditorGroupsContext.toNegated();
|
||||
export const EditorPartMaximizedEditorGroupContext = new RawContextKey<boolean>('editorPartMaximizedEditorGroup', false, localize('editorPartEditorGroupMaximized', "Editor Part has a maximized group"));
|
||||
|
||||
// Editor Layout Context Keys
|
||||
export const EditorsVisibleContext = new RawContextKey<boolean>('editorIsOpen', false, localize('editorIsOpen', "Whether an editor is open"));
|
||||
export const InEditorZenModeContext = new RawContextKey<boolean>('inZenMode', false, localize('inZenMode', "Whether Zen mode is enabled"));
|
||||
@@ -79,7 +84,6 @@ export const SplitEditorsVertically = new RawContextKey<boolean>('splitEditorsVe
|
||||
export const EditorAreaVisibleContext = new RawContextKey<boolean>('editorAreaVisible', true, localize('editorAreaVisible', "Whether the editor area is visible"));
|
||||
export const EditorTabsVisibleContext = new RawContextKey<boolean>('editorTabsVisible', true, localize('editorTabsVisible', "Whether editor tabs are visible"));
|
||||
export const EditorPinnedAndUnpinnedTabsContext = new RawContextKey<boolean>('editorPinnedAndUnpinnedTabsVisible', false, true);
|
||||
export const MaximizedEditorGroupContext = new RawContextKey<boolean>('maximizedEditorGroup', false, localize('editorGroupMaximized', "Editor group is maximized"));
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
@@ -1113,7 +1113,9 @@ interface IEditorPartConfiguration {
|
||||
wrapTabs?: boolean;
|
||||
scrollToSwitchTabs?: boolean;
|
||||
highlightModifiedTabs?: boolean;
|
||||
tabCloseButton?: 'left' | 'right' | 'off';
|
||||
tabActionLocation?: 'left' | 'right';
|
||||
tabActionCloseVisibility?: boolean;
|
||||
tabActionUnpinVisibility?: boolean;
|
||||
tabSizing?: 'fit' | 'shrink' | 'fixed';
|
||||
tabSizingFixedMinWidth?: number;
|
||||
tabSizingFixedMaxWidth?: number;
|
||||
|
||||
@@ -458,7 +458,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
|
||||
const disposable = templateData.elementDisposables.add(dom.scheduleAtNextAnimationFrame(() => {
|
||||
disposable.dispose();
|
||||
this._onDidChangeItemHeight.fire({ element, height: newHeight });
|
||||
}));
|
||||
}, dom.getWindow(templateData.value)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,7 +496,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
|
||||
const disposable = templateData.elementDisposables.add(dom.scheduleAtNextAnimationFrame(() => {
|
||||
disposable.dispose();
|
||||
this._onDidChangeItemHeight.fire({ element, height: newHeight });
|
||||
}));
|
||||
}, dom.getWindow(templateData.value)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,12 @@ export class QuickChatService extends Disposable implements IQuickChatService {
|
||||
|
||||
open(providerId?: string, options?: IQuickChatOpenOptions): void {
|
||||
if (this._input) {
|
||||
if (this._currentChat && options?.query) {
|
||||
this._currentChat.setValue(options.query, options.selection);
|
||||
if (!options.isPartialQuery) {
|
||||
this._currentChat.acceptInput();
|
||||
}
|
||||
}
|
||||
return this.focus();
|
||||
}
|
||||
|
||||
|
||||
@@ -407,7 +407,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
dom.scheduleAtNextAnimationFrame(() => {
|
||||
// Can't set scrollTop during this event listener, the list might overwrite the change
|
||||
revealLastElement(this.tree);
|
||||
}, 0);
|
||||
}, dom.getWindow(this.listContainer), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,7 +640,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
const inputPartHeight = this.inputPart.layout(possibleMaxHeight, width);
|
||||
const newHeight = Math.min(renderHeight + diff, possibleMaxHeight - inputPartHeight);
|
||||
this.layout(newHeight + inputPartHeight, width);
|
||||
});
|
||||
}, dom.getWindow(this.listContainer));
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ class InputEditorDecorations extends Disposable {
|
||||
|
||||
private registerViewModelListeners(): void {
|
||||
this.viewModelDisposables.value = this.widget.viewModel?.onDidChange(e => {
|
||||
if (e?.kind === 'changePlaceholder') {
|
||||
if (e?.kind === 'changePlaceholder' || e?.kind === 'initialize') {
|
||||
this.updateInputEditorDecorations();
|
||||
}
|
||||
});
|
||||
@@ -127,7 +127,6 @@ class InputEditorDecorations extends Disposable {
|
||||
|
||||
private async updateInputEditorDecorations() {
|
||||
const inputValue = this.widget.inputEditor.getValue();
|
||||
const slashCommands = await this.widget.getSlashCommands(); // TODO this async call can lead to a flicker of the placeholder text when switching editor tabs
|
||||
|
||||
const viewModel = this.widget.viewModel;
|
||||
if (!viewModel) {
|
||||
@@ -136,10 +135,7 @@ class InputEditorDecorations extends Disposable {
|
||||
|
||||
if (!inputValue) {
|
||||
const viewModelPlaceholder = this.widget.viewModel?.inputPlaceholder;
|
||||
const defaultPlaceholder = slashCommands?.length ?
|
||||
localize('interactive.input.placeholderWithCommands', "Ask a question or type '@' or '/'") :
|
||||
localize('interactive.input.placeholderNoCommands', "Ask a question");
|
||||
const placeholder = viewModelPlaceholder ?? defaultPlaceholder;
|
||||
const placeholder = viewModelPlaceholder ?? '';
|
||||
const decoration: IDecorationOptions[] = [
|
||||
{
|
||||
range: {
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
}
|
||||
|
||||
.interactive-item-container .header .avatar .codicon {
|
||||
color: var(--vscode-chat-avatarForeground);
|
||||
color: var(--vscode-chat-avatarForeground) !important;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@ export const chatRequestBorder = registerColor(
|
||||
|
||||
export const chatSlashCommandBackground = registerColor(
|
||||
'chat.slashCommandBackground',
|
||||
{ dark: badgeBackground, light: badgeBackground, hcDark: Color.white, hcLight: badgeBackground },
|
||||
{ dark: '#34414B', light: '#D2ECFF', hcDark: Color.white, hcLight: badgeBackground },
|
||||
localize('chat.slashCommandBackground', 'The background color of a chat slash command.')
|
||||
);
|
||||
|
||||
export const chatSlashCommandForeground = registerColor(
|
||||
'chat.slashCommandForeground',
|
||||
{ dark: badgeForeground, light: badgeForeground, hcDark: Color.black, hcLight: badgeForeground },
|
||||
{ dark: '#40A6FF', light: '#306CA2', hcDark: Color.black, hcLight: badgeForeground },
|
||||
localize('chat.slashCommandForeground', 'The foreground color of a chat slash command.')
|
||||
);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ export function isWelcomeVM(item: unknown): item is IChatWelcomeMessageViewModel
|
||||
return !!item && typeof item === 'object' && 'content' in item;
|
||||
}
|
||||
|
||||
export type IChatViewModelChangeEvent = IChatAddRequestEvent | IChangePlaceholderEvent | null;
|
||||
export type IChatViewModelChangeEvent = IChatAddRequestEvent | IChangePlaceholderEvent | IChatSessionInitEvent | null;
|
||||
|
||||
export interface IChatAddRequestEvent {
|
||||
kind: 'addRequest';
|
||||
@@ -36,6 +36,10 @@ export interface IChangePlaceholderEvent {
|
||||
kind: 'changePlaceholder';
|
||||
}
|
||||
|
||||
export interface IChatSessionInitEvent {
|
||||
kind: 'initialize';
|
||||
}
|
||||
|
||||
export interface IChatViewModel {
|
||||
readonly initState: ChatModelInitState;
|
||||
readonly providerId: string;
|
||||
@@ -184,7 +188,10 @@ export class ChatViewModel extends Disposable implements IChatViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
this._onDidChange.fire(e.kind === 'addRequest' ? { kind: 'addRequest' } : null);
|
||||
const modelEventToVmEvent: IChatViewModelChangeEvent = e.kind === 'addRequest' ? { kind: 'addRequest' } :
|
||||
e.kind === 'initialize' ? { kind: 'initialize' } :
|
||||
null;
|
||||
this._onDidChange.fire(modelEventToVmEvent);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import { ISashEvent, IVerticalSashLayoutProvider, Orientation, Sash } from 'vs/b
|
||||
import { registerColor } from 'vs/platform/theme/common/colorRegistry';
|
||||
|
||||
const NLS_FIND_INPUT_LABEL = nls.localize('label.find', "Find");
|
||||
const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find (\u21C5 for history)");
|
||||
const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find");
|
||||
const NLS_PREVIOUS_MATCH_BTN_LABEL = nls.localize('label.previousMatchButton', "Previous Match");
|
||||
const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next Match");
|
||||
const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close");
|
||||
|
||||
@@ -170,7 +170,7 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
|
||||
this._scrollable = new Scrollable({
|
||||
forceIntegerValues: true,
|
||||
smoothScrollDuration: 125,
|
||||
scheduleAtNextAnimationFrame: cb => dom.scheduleAtNextAnimationFrame(cb)
|
||||
scheduleAtNextAnimationFrame: cb => dom.scheduleAtNextAnimationFrame(cb, dom.getWindow(container))
|
||||
});
|
||||
this._scrollableElement = this._register(new SmoothScrollableElement(body, {
|
||||
horizontal: ScrollbarVisibility.Visible,
|
||||
@@ -489,7 +489,7 @@ export class CommentNode<T extends IRange | ICellRange> extends Disposable {
|
||||
dom.scheduleAtNextAnimationFrame(() => {
|
||||
this._commentEditor!.layout({ width: container.clientWidth - 14, height: this._editorHeight });
|
||||
this._commentEditor!.focus();
|
||||
});
|
||||
}, dom.getWindow(editContainer));
|
||||
|
||||
const lastLine = this._commentEditorModel.getLineCount();
|
||||
const lastColumn = this._commentEditorModel.getLineLength(lastLine) + 1;
|
||||
|
||||
@@ -869,8 +869,20 @@ export class CommentController implements IEditorContribution {
|
||||
const matchedZones = this._commentWidgets.filter(zoneWidget => zoneWidget.owner === thread.owner && Range.lift(zoneWidget.commentThread.range)?.equalsRange(thread.range));
|
||||
if (thread.isReply && matchedZones.length) {
|
||||
this.commentService.removeContinueOnComment({ owner: thread.owner, uri: editorURI, range: thread.range, isReply: true });
|
||||
const matchedZone = matchedZones[0];
|
||||
matchedZone.setPendingComment(thread.body);
|
||||
matchedZones[0].setPendingComment(thread.body);
|
||||
} else if (matchedZones.length) {
|
||||
this.commentService.removeContinueOnComment({ owner: thread.owner, uri: editorURI, range: thread.range, isReply: false });
|
||||
const existingPendingComment = matchedZones[0].getPendingComments().newComment;
|
||||
// We need to try to reconcile the existing pending comment with the incoming pending comment
|
||||
let pendingComment: string;
|
||||
if (!existingPendingComment || thread.body.includes(existingPendingComment)) {
|
||||
pendingComment = thread.body;
|
||||
} else if (existingPendingComment.includes(thread.body)) {
|
||||
pendingComment = existingPendingComment;
|
||||
} else {
|
||||
pendingComment = `${existingPendingComment}\n${thread.body}`;
|
||||
}
|
||||
matchedZones[0].setPendingComment(pendingComment);
|
||||
} else if (!thread.isReply) {
|
||||
const threadStillAvailable = this.commentService.removeContinueOnComment({ owner: thread.owner, uri: editorURI, range: thread.range, isReply: false });
|
||||
if (!threadStillAvailable) {
|
||||
|
||||
@@ -36,7 +36,7 @@ import { debugToolBarBackground, debugToolBarBorder } from 'vs/workbench/contrib
|
||||
import { CONTINUE_ID, CONTINUE_LABEL, DISCONNECT_AND_SUSPEND_ID, DISCONNECT_AND_SUSPEND_LABEL, DISCONNECT_ID, DISCONNECT_LABEL, FOCUS_SESSION_ID, FOCUS_SESSION_LABEL, PAUSE_ID, PAUSE_LABEL, RESTART_LABEL, RESTART_SESSION_ID, REVERSE_CONTINUE_ID, STEP_BACK_ID, STEP_INTO_ID, STEP_INTO_LABEL, STEP_OUT_ID, STEP_OUT_LABEL, STEP_OVER_ID, STEP_OVER_LABEL, STOP_ID, STOP_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands';
|
||||
import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons';
|
||||
import { CONTEXT_DEBUG_STATE, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_IN_DEBUG_MODE, CONTEXT_MULTI_SESSION_DEBUG, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_SUSPEND_DEBUGGEE_SUPPORTED, CONTEXT_TERMINATE_DEBUGGEE_SUPPORTED, IDebugConfiguration, IDebugService, State, VIEWLET_ID } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { EditorTabsMode, IWorkbenchLayoutService, LayoutSettings, Parts } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
|
||||
const DEBUG_TOOLBAR_POSITION_KEY = 'debug.actionswidgetposition';
|
||||
@@ -132,6 +132,10 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
|
||||
if (e.affectsConfiguration('debug.toolBarLocation')) {
|
||||
this.updateScheduler.schedule();
|
||||
}
|
||||
if (e.affectsConfiguration(LayoutSettings.EDITOR_TABS_MODE) || e.affectsConfiguration(LayoutSettings.COMMAND_CENTER)) {
|
||||
this._yRange = undefined;
|
||||
this.setYCoordinate();
|
||||
}
|
||||
}));
|
||||
this._register(this.debugToolBarMenu.onDidChange(() => this.updateScheduler.schedule()));
|
||||
this._register(this.actionBar.actionRunner.onDidRun((e: IRunEvent) => {
|
||||
@@ -163,7 +167,7 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
|
||||
// Prevent default to stop editor selecting text #8524
|
||||
mouseMoveEvent.preventDefault();
|
||||
// Reduce x by width of drag handle to reduce jarring #16604
|
||||
this.setCoordinates(mouseMoveEvent.posx - 14, mouseMoveEvent.posy - (this.layoutService.mainContainerOffset.top));
|
||||
this.setCoordinates(mouseMoveEvent.posx - 14, mouseMoveEvent.posy - 14);
|
||||
});
|
||||
|
||||
const mouseUpListener = dom.addDisposableGenericMouseUpListener(window, (e: MouseEvent) => {
|
||||
@@ -185,6 +189,11 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
|
||||
const position = parseFloat(left) / window.innerWidth;
|
||||
this.storageService.store(DEBUG_TOOLBAR_POSITION_KEY, position, StorageScope.PROFILE, StorageTarget.MACHINE);
|
||||
}
|
||||
if (this.yCoordinate) {
|
||||
this.storageService.store(DEBUG_TOOLBAR_Y_KEY, this.yCoordinate, StorageScope.PROFILE, StorageTarget.MACHINE);
|
||||
} else {
|
||||
this.storageService.remove(DEBUG_TOOLBAR_Y_KEY, StorageScope.PROFILE);
|
||||
}
|
||||
}
|
||||
|
||||
override updateStyles(): void {
|
||||
@@ -208,12 +217,6 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
|
||||
}
|
||||
}
|
||||
|
||||
private setYCoordinate(y = this.yCoordinate): void {
|
||||
const titlebarOffset = this.layoutService.mainContainerOffset.top;
|
||||
this.$el.style.top = `${titlebarOffset + y}px`;
|
||||
this.yCoordinate = y;
|
||||
}
|
||||
|
||||
private setCoordinates(x?: number, y?: number): void {
|
||||
if (!this.isVisible) {
|
||||
return;
|
||||
@@ -230,12 +233,38 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
|
||||
if (y === undefined) {
|
||||
y = this.storageService.getNumber(DEBUG_TOOLBAR_Y_KEY, StorageScope.PROFILE, 0);
|
||||
}
|
||||
const titleAreaHeight = 35;
|
||||
if ((y < titleAreaHeight / 2) || (y > titleAreaHeight + titleAreaHeight / 2)) {
|
||||
const moveToTop = y < titleAreaHeight;
|
||||
this.setYCoordinate(moveToTop ? 0 : titleAreaHeight);
|
||||
this.storageService.store(DEBUG_TOOLBAR_Y_KEY, moveToTop ? 0 : 2 * titleAreaHeight, StorageScope.PROFILE, StorageTarget.MACHINE);
|
||||
|
||||
this.setYCoordinate(y);
|
||||
}
|
||||
|
||||
private setYCoordinate(y = this.yCoordinate): void {
|
||||
const [yMin, yMax] = this.yRange;
|
||||
y = Math.max(yMin, Math.min(y, yMax));
|
||||
this.$el.style.top = `${y}px`;
|
||||
this.yCoordinate = y;
|
||||
}
|
||||
|
||||
private _yRange: [number, number] | undefined;
|
||||
private get yRange(): [number, number] {
|
||||
if (!this._yRange) {
|
||||
const isTitleBarVisible = this.layoutService.isVisible(Parts.TITLEBAR_PART);
|
||||
const yMin = isTitleBarVisible ? 0 : this.layoutService.mainContainerOffset.top;
|
||||
let yMax = 0;
|
||||
|
||||
if (isTitleBarVisible) {
|
||||
if (this.configurationService.getValue(LayoutSettings.COMMAND_CENTER) === true) {
|
||||
yMax += 35;
|
||||
} else {
|
||||
yMax += 28;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.configurationService.getValue(LayoutSettings.EDITOR_TABS_MODE) !== EditorTabsMode.NONE) {
|
||||
yMax += 35;
|
||||
}
|
||||
this._yRange = [yMin, yMax];
|
||||
}
|
||||
return this._yRange;
|
||||
}
|
||||
|
||||
private show(): void {
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
|
||||
.monaco-workbench .debug-toolbar {
|
||||
position: absolute;
|
||||
z-index: 39;
|
||||
height: 32px;
|
||||
z-index: 3000;
|
||||
height: 26px;
|
||||
display: flex;
|
||||
padding-left: 7px;
|
||||
border-radius: 4px;
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
.monaco-workbench .debug-toolbar .monaco-action-bar .action-item {
|
||||
|
||||
@@ -95,7 +95,7 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
|
||||
@INotebookService private readonly _notebookService: INotebookService,
|
||||
@IFileDialogService private readonly _fileDialogService: IFileDialogService
|
||||
) {
|
||||
const input = NotebookEditorInput.create(instantiationService, resource, 'interactive', {});
|
||||
const input = NotebookEditorInput.getOrCreate(instantiationService, resource, undefined, 'interactive', {});
|
||||
super();
|
||||
this._notebookEditorInput = input;
|
||||
this._register(this._notebookEditorInput);
|
||||
|
||||
@@ -998,7 +998,7 @@ export class DeletedElement extends SingleSideDiffElement {
|
||||
}
|
||||
|
||||
this.layoutNotebookCell();
|
||||
});
|
||||
}, DOM.getWindow(this._diffEditorContainer));
|
||||
}
|
||||
|
||||
_buildOutputRendererContainer() {
|
||||
@@ -1201,7 +1201,7 @@ export class InsertElement extends SingleSideDiffElement {
|
||||
if (this._diagonalFill) {
|
||||
this._diagonalFill.style.height = `${this.cell.layoutInfo.editorHeight + this.cell.layoutInfo.editorMargin + this.cell.layoutInfo.metadataStatusHeight + this.cell.layoutInfo.metadataHeight + this.cell.layoutInfo.outputTotalHeight + this.cell.layoutInfo.outputStatusHeight}px`;
|
||||
}
|
||||
});
|
||||
}, DOM.getWindow(this._diffEditorContainer));
|
||||
}
|
||||
|
||||
override dispose() {
|
||||
@@ -1626,7 +1626,7 @@ export class ModifiedElement extends AbstractElementRenderer {
|
||||
}
|
||||
|
||||
this.layoutNotebookCell();
|
||||
});
|
||||
}, DOM.getWindow(this._diffEditorContainer));
|
||||
}
|
||||
|
||||
override dispose() {
|
||||
|
||||
@@ -463,7 +463,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
|
||||
return diffElement.original;
|
||||
}, DiffSide.Original);
|
||||
}
|
||||
});
|
||||
}, DOM.getWindow(this._listViewContainer));
|
||||
};
|
||||
|
||||
this._localStore.add(this._list.onDidChangeContentHeight(() => {
|
||||
@@ -763,7 +763,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
|
||||
|
||||
DOM.scheduleAtNextAnimationFrame(() => {
|
||||
webview?.ackHeight([{ cellId: cellInfo.cellId, outputId, height }]);
|
||||
}, 10);
|
||||
}, DOM.getWindow(this._listViewContainer), 10);
|
||||
}
|
||||
|
||||
private pendingLayouts = new WeakMap<DiffElementViewModelBase, IDisposable>();
|
||||
@@ -784,7 +784,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
|
||||
|
||||
relayout(cell, height);
|
||||
r();
|
||||
});
|
||||
}, DOM.getWindow(this._listViewContainer));
|
||||
|
||||
this.pendingLayouts.set(cell, toDisposable(() => {
|
||||
layoutDisposable.dispose();
|
||||
|
||||
@@ -114,7 +114,7 @@ export class NotebookDiffOverviewRuler extends Themable {
|
||||
|
||||
private _scheduleRender(): void {
|
||||
if (this._renderAnimationFrame === null) {
|
||||
this._renderAnimationFrame = DOM.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), 16);
|
||||
this._renderAnimationFrame = DOM.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), DOM.getWindow(this._domNode.domNode), 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ class NotebookDiffEditorSerializer implements IEditorSerializer {
|
||||
}
|
||||
|
||||
}
|
||||
type SerializedNotebookEditorData = { resource: URI; viewType: string; options?: NotebookEditorInputOptions };
|
||||
type SerializedNotebookEditorData = { resource: URI; preferredResource: URI; viewType: string; options?: NotebookEditorInputOptions };
|
||||
class NotebookEditorSerializer implements IEditorSerializer {
|
||||
canSerialize(): boolean {
|
||||
return true;
|
||||
@@ -189,6 +189,7 @@ class NotebookEditorSerializer implements IEditorSerializer {
|
||||
assertType(input instanceof NotebookEditorInput);
|
||||
const data: SerializedNotebookEditorData = {
|
||||
resource: input.resource,
|
||||
preferredResource: input.preferredResource,
|
||||
viewType: input.viewType,
|
||||
options: input.options
|
||||
};
|
||||
@@ -199,12 +200,12 @@ class NotebookEditorSerializer implements IEditorSerializer {
|
||||
if (!data) {
|
||||
return undefined;
|
||||
}
|
||||
const { resource, viewType, options } = data;
|
||||
const { resource, preferredResource, viewType, options } = data;
|
||||
if (!data || !URI.isUri(resource) || typeof viewType !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const input = NotebookEditorInput.create(instantiationService, resource, viewType, options);
|
||||
const input = NotebookEditorInput.getOrCreate(instantiationService, resource, preferredResource, viewType, options);
|
||||
return input;
|
||||
}
|
||||
}
|
||||
@@ -639,7 +640,7 @@ class SimpleNotebookWorkingCopyEditorHandler extends Disposable implements IWork
|
||||
}
|
||||
|
||||
createEditor(workingCopy: IWorkingCopyIdentifier): EditorInput {
|
||||
return NotebookEditorInput.create(this._instantiationService, workingCopy.resource, this._getViewType(workingCopy)!);
|
||||
return NotebookEditorInput.getOrCreate(this._instantiationService, workingCopy.resource, undefined, this._getViewType(workingCopy)!);
|
||||
}
|
||||
|
||||
private async _installHandler(): Promise<void> {
|
||||
|
||||
@@ -1454,7 +1454,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
|
||||
this._localStore.add(DOM.scheduleAtNextAnimationFrame(() => {
|
||||
hasPendingChangeContentHeight = false;
|
||||
this._updateScrollHeight();
|
||||
}, 100));
|
||||
}, DOM.getWindow(this._body), 100));
|
||||
}));
|
||||
|
||||
this._localStore.add(this._list.onDidRemoveOutputs(outputs => {
|
||||
@@ -2259,7 +2259,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
|
||||
};
|
||||
|
||||
if (this._list.inRenderingTransaction) {
|
||||
const layoutDisposable = DOM.scheduleAtNextAnimationFrame(doLayout);
|
||||
const layoutDisposable = DOM.scheduleAtNextAnimationFrame(doLayout, DOM.getWindow(this._body));
|
||||
|
||||
this._pendingLayouts?.set(cell, toDisposable(() => {
|
||||
layoutDisposable.dispose();
|
||||
@@ -2973,7 +2973,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
|
||||
this._webview?.ackHeight([...this._pendingOutputHeightAcks.values()]);
|
||||
|
||||
this._pendingOutputHeightAcks.clear();
|
||||
}, -1); // -1 priority because this depends on calls to layoutNotebookCell, and that may be called multiple times before this runs
|
||||
}, DOM.getWindow(this._body), -1); // -1 priority because this depends on calls to layoutNotebookCell, and that may be called multiple times before this runs
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ import { DiffEditorInputFactoryFunction, EditorInputFactoryFunction, EditorInput
|
||||
import { IExtensionService, isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { InstallRecommendedExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
|
||||
|
||||
export class NotebookProviderInfoStore extends Disposable {
|
||||
|
||||
@@ -62,7 +63,8 @@ export class NotebookProviderInfoStore extends Disposable {
|
||||
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
@INotebookEditorModelResolverService private readonly _notebookEditorModelResolverService: INotebookEditorModelResolverService
|
||||
@INotebookEditorModelResolverService private readonly _notebookEditorModelResolverService: INotebookEditorModelResolverService,
|
||||
@IUriIdentityService private readonly uriIdentService: IUriIdentityService,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -178,12 +180,18 @@ export class NotebookProviderInfoStore extends Disposable {
|
||||
};
|
||||
const notebookEditorInputFactory: EditorInputFactoryFunction = ({ resource, options }) => {
|
||||
const data = CellUri.parse(resource);
|
||||
let notebookUri: URI = resource;
|
||||
let notebookUri: URI;
|
||||
|
||||
let cellOptions: IResourceEditorInput | undefined;
|
||||
let preferredResource = resource;
|
||||
|
||||
if (data) {
|
||||
notebookUri = data.notebook;
|
||||
// resource is a notebook cell
|
||||
notebookUri = this.uriIdentService.asCanonicalUri(data.notebook);
|
||||
preferredResource = data.notebook;
|
||||
cellOptions = { resource, options };
|
||||
} else {
|
||||
notebookUri = this.uriIdentService.asCanonicalUri(resource);
|
||||
}
|
||||
|
||||
if (!cellOptions) {
|
||||
@@ -191,8 +199,10 @@ export class NotebookProviderInfoStore extends Disposable {
|
||||
}
|
||||
|
||||
const notebookOptions = { ...options, cellOptions } as INotebookEditorOptions;
|
||||
return { editor: NotebookEditorInput.create(this._instantiationService, notebookUri, notebookProviderInfo.id), options: notebookOptions };
|
||||
const editor = NotebookEditorInput.getOrCreate(this._instantiationService, notebookUri, preferredResource, notebookProviderInfo.id);
|
||||
return { editor, options: notebookOptions };
|
||||
};
|
||||
|
||||
const notebookUntitledEditorFactory: UntitledEditorInputFactoryFunction = async ({ resource, options }) => {
|
||||
const ref = await this._notebookEditorModelResolverService.resolve({ untitledResource: resource }, notebookProviderInfo.id);
|
||||
|
||||
@@ -202,7 +212,7 @@ export class NotebookProviderInfoStore extends Disposable {
|
||||
ref!.dispose();
|
||||
});
|
||||
|
||||
return { editor: NotebookEditorInput.create(this._instantiationService, ref.object.resource, notebookProviderInfo.id), options };
|
||||
return { editor: NotebookEditorInput.getOrCreate(this._instantiationService, ref.object.resource, undefined, notebookProviderInfo.id), options };
|
||||
};
|
||||
const notebookDiffEditorInputFactory: DiffEditorInputFactoryFunction = ({ modified, original, label, description }) => {
|
||||
return { editor: NotebookDiffEditorInput.create(this._instantiationService, modified.resource!, label, description, original.resource!, notebookProviderInfo.id) };
|
||||
|
||||
@@ -128,18 +128,19 @@ export class CellPartsCollection extends Disposable {
|
||||
private _scheduledOverlayUpdateExecutionState = this._register(new MutableDisposable());
|
||||
|
||||
constructor(
|
||||
private readonly targetWindow: Window,
|
||||
private readonly contentParts: readonly CellContentPart[],
|
||||
private readonly overlayParts: readonly CellOverlayPart[]
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
concatContentPart(other: readonly CellContentPart[]): CellPartsCollection {
|
||||
return new CellPartsCollection(this.contentParts.concat(other), this.overlayParts);
|
||||
concatContentPart(other: readonly CellContentPart[], targetWindow: Window): CellPartsCollection {
|
||||
return new CellPartsCollection(targetWindow, this.contentParts.concat(other), this.overlayParts);
|
||||
}
|
||||
|
||||
concatOverlayPart(other: readonly CellOverlayPart[]): CellPartsCollection {
|
||||
return new CellPartsCollection(this.contentParts, this.overlayParts.concat(other));
|
||||
concatOverlayPart(other: readonly CellOverlayPart[], targetWindow: Window): CellPartsCollection {
|
||||
return new CellPartsCollection(targetWindow, this.contentParts, this.overlayParts.concat(other));
|
||||
}
|
||||
|
||||
scheduleRenderCell(element: ICellViewModel): void {
|
||||
@@ -161,7 +162,7 @@ export class CellPartsCollection extends Disposable {
|
||||
for (const part of this.overlayParts) {
|
||||
part.renderCell(element);
|
||||
}
|
||||
});
|
||||
}, this.targetWindow);
|
||||
}
|
||||
|
||||
unrenderCell(element: ICellViewModel): void {
|
||||
@@ -203,7 +204,7 @@ export class CellPartsCollection extends Disposable {
|
||||
for (const part of this.overlayParts) {
|
||||
part.updateState(viewCell, e);
|
||||
}
|
||||
});
|
||||
}, this.targetWindow);
|
||||
}
|
||||
|
||||
updateForExecutionState(viewCell: ICellViewModel, e: ICellExecutionStateChangedEvent) {
|
||||
@@ -215,6 +216,6 @@ export class CellPartsCollection extends Disposable {
|
||||
for (const part of this.overlayParts) {
|
||||
part.updateForExecutionState(viewCell, e);
|
||||
}
|
||||
});
|
||||
}, this.targetWindow);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ export class CodeCell extends Disposable {
|
||||
|
||||
const cellEditorOptions = this._register(new CellEditorOptions(this.notebookEditor.getBaseCellEditorOptions(viewCell.language), this.notebookEditor.notebookOptions, this.configurationService));
|
||||
this._outputContainerRenderer = this.instantiationService.createInstance(CellOutputContainer, notebookEditor, viewCell, templateData, { limit: outputDisplayLimit });
|
||||
this.cellParts = this._register(templateData.cellParts.concatContentPart([cellEditorOptions, this._outputContainerRenderer]));
|
||||
this.cellParts = this._register(templateData.cellParts.concatContentPart([cellEditorOptions, this._outputContainerRenderer], DOM.getWindow(notebookEditor.getDomNode())));
|
||||
|
||||
// this.viewCell.layoutInfo.editorHeight or estimation when this.viewCell.layoutInfo.editorHeight === 0
|
||||
const editorHeight = this.calculateInitEditorHeight();
|
||||
@@ -146,7 +146,7 @@ export class CodeCell extends Disposable {
|
||||
this._pendingLayout?.dispose();
|
||||
this._pendingLayout = DOM.modify(() => {
|
||||
this.cellParts.updateInternalLayoutNow(this.viewCell);
|
||||
});
|
||||
}, DOM.getWindow(this.templateData.container));
|
||||
}
|
||||
|
||||
private updateForOutputHover() {
|
||||
|
||||
@@ -289,7 +289,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
|
||||
if (this._isInLayout) {
|
||||
DOM.scheduleAtNextAnimationFrame(() => {
|
||||
updateVisibleRanges();
|
||||
});
|
||||
}, DOM.getWindow(container));
|
||||
}
|
||||
updateVisibleRanges();
|
||||
}));
|
||||
@@ -297,7 +297,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
|
||||
if (this._isInLayout) {
|
||||
DOM.scheduleAtNextAnimationFrame(() => {
|
||||
updateVisibleRanges();
|
||||
});
|
||||
}, DOM.getWindow(container));
|
||||
}
|
||||
updateVisibleRanges();
|
||||
}));
|
||||
@@ -369,7 +369,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
|
||||
}
|
||||
|
||||
this._updateElementsInWebview(viewDiffs);
|
||||
}));
|
||||
}, DOM.getWindow(this.rowsContainer)));
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ export class MarkupCellRenderer extends AbstractCellRenderer implements IListRen
|
||||
this.notebookEditor));
|
||||
const focusIndicatorBottom = new FastDomNode(DOM.append(container, $('.cell-focus-indicator.cell-focus-indicator-bottom')));
|
||||
|
||||
const cellParts = new CellPartsCollection([
|
||||
const cellParts = new CellPartsCollection(DOM.getWindow(rootContainer), [
|
||||
templateDisposables.add(scopedInstaService.createInstance(CellEditorStatusBar, this.notebookEditor, container, editorPart, undefined)),
|
||||
templateDisposables.add(new CellFocusIndicator(this.notebookEditor, titleToolbar, focusIndicatorTop, focusIndicatorLeft, focusIndicatorRight, focusIndicatorBottom)),
|
||||
templateDisposables.add(new FoldedCellHint(this.notebookEditor, DOM.append(container, $('.notebook-folded-hint')))),
|
||||
@@ -306,7 +306,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
||||
this.notebookEditor));
|
||||
|
||||
const focusIndicatorPart = templateDisposables.add(new CellFocusIndicator(this.notebookEditor, titleToolbar, focusIndicatorTop, focusIndicatorLeft, focusIndicatorRight, focusIndicatorBottom));
|
||||
const cellParts = new CellPartsCollection([
|
||||
const cellParts = new CellPartsCollection(DOM.getWindow(rootContainer), [
|
||||
focusIndicatorPart,
|
||||
templateDisposables.add(scopedInstaService.createInstance(CellEditorStatusBar, this.notebookEditor, container, editorPart, editor)),
|
||||
templateDisposables.add(scopedInstaService.createInstance(CellProgressBar, editorPart, cellInputCollapsedContainer)),
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@ export class NotebookEditorContextKeys {
|
||||
|
||||
layoutDisposable.add(DOM.scheduleAtNextAnimationFrame(() => {
|
||||
recomputeOutputsExistence();
|
||||
}));
|
||||
}, DOM.getWindow(this._editor.getDomNode())));
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ class NotebookDiffEditorModel extends EditorModel implements INotebookDiffEditor
|
||||
|
||||
export class NotebookDiffEditorInput extends DiffEditorInput {
|
||||
static create(instantiationService: IInstantiationService, resource: URI, name: string | undefined, description: string | undefined, originalResource: URI, viewType: string) {
|
||||
const original = NotebookEditorInput.create(instantiationService, originalResource, viewType);
|
||||
const modified = NotebookEditorInput.create(instantiationService, resource, viewType);
|
||||
const original = NotebookEditorInput.getOrCreate(instantiationService, originalResource, undefined, viewType);
|
||||
const modified = NotebookEditorInput.getOrCreate(instantiationService, resource, undefined, viewType);
|
||||
return instantiationService.createInstance(NotebookDiffEditorInput, name, description, original, modified, viewType);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,8 +41,24 @@ export interface NotebookEditorInputOptions {
|
||||
|
||||
export class NotebookEditorInput extends AbstractResourceEditorInput {
|
||||
|
||||
static create(instantiationService: IInstantiationService, resource: URI, viewType: string, options: NotebookEditorInputOptions = {}) {
|
||||
return instantiationService.createInstance(NotebookEditorInput, resource, viewType, options);
|
||||
private static EditorCache: Record<string, NotebookEditorInput> = {};
|
||||
|
||||
static getOrCreate(instantiationService: IInstantiationService, resource: URI, preferredResource: URI | undefined, viewType: string, options: NotebookEditorInputOptions = {}) {
|
||||
const cacheId = `${resource.toString()}|${viewType}|${options._workingCopy?.typeId}`;
|
||||
let editor = NotebookEditorInput.EditorCache[cacheId];
|
||||
|
||||
if (!editor) {
|
||||
editor = instantiationService.createInstance(NotebookEditorInput, resource, preferredResource, viewType, options);
|
||||
NotebookEditorInput.EditorCache[cacheId] = editor;
|
||||
|
||||
editor.onWillDispose(() => {
|
||||
delete NotebookEditorInput.EditorCache[cacheId];
|
||||
});
|
||||
} else if (preferredResource) {
|
||||
editor.setPreferredResource(preferredResource);
|
||||
}
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
static readonly ID: string = 'workbench.input.notebook';
|
||||
@@ -53,19 +69,19 @@ export class NotebookEditorInput extends AbstractResourceEditorInput {
|
||||
|
||||
constructor(
|
||||
resource: URI,
|
||||
preferredResource: URI | undefined,
|
||||
public readonly viewType: string,
|
||||
public readonly options: NotebookEditorInputOptions,
|
||||
@INotebookService private readonly _notebookService: INotebookService,
|
||||
@INotebookEditorModelResolverService private readonly _notebookModelResolverService: INotebookEditorModelResolverService,
|
||||
@IFileDialogService private readonly _fileDialogService: IFileDialogService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@ILabelService labelService: ILabelService,
|
||||
@IFileService fileService: IFileService,
|
||||
@IFilesConfigurationService filesConfigurationService: IFilesConfigurationService,
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IEditorService editorService: IEditorService
|
||||
) {
|
||||
super(resource, undefined, labelService, fileService, filesConfigurationService);
|
||||
super(resource, preferredResource, labelService, fileService, filesConfigurationService);
|
||||
this._defaultDirtyState = !!options.startDirty;
|
||||
|
||||
// Automatically resolve this input when the "wanted" model comes to life via
|
||||
@@ -253,20 +269,12 @@ export class NotebookEditorInput extends AbstractResourceEditorInput {
|
||||
// called when users rename a notebook document
|
||||
override async rename(group: GroupIdentifier, target: URI): Promise<IMoveResult | undefined> {
|
||||
if (this._editorModelReference) {
|
||||
const contributedNotebookProviders = this._notebookService.getContributedNotebookTypes(target);
|
||||
return { editor: { resource: target }, options: { override: this.viewType } };
|
||||
|
||||
if (contributedNotebookProviders.find(provider => provider.id === this._editorModelReference!.object.viewType)) {
|
||||
return this._move(group, target);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private _move(_group: GroupIdentifier, newResource: URI): { editor: EditorInput } {
|
||||
const editorInput = NotebookEditorInput.create(this._instantiationService, newResource, this.viewType);
|
||||
return { editor: editorInput };
|
||||
}
|
||||
|
||||
override async revert(_group: GroupIdentifier, options?: IRevertOptions): Promise<void> {
|
||||
if (this._editorModelReference && this._editorModelReference.object.isDirty()) {
|
||||
await this._editorModelReference.object.revert(options);
|
||||
@@ -336,7 +344,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput {
|
||||
|
||||
override toUntyped(): IResourceEditorInput {
|
||||
return {
|
||||
resource: this.preferredResource,
|
||||
resource: this.resource,
|
||||
options: {
|
||||
override: this.viewType
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
|
||||
import { NotebookProviderInfoStore } from 'vs/workbench/contrib/notebook/browser/services/notebookServiceImpl';
|
||||
import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService';
|
||||
import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
|
||||
@@ -43,7 +44,8 @@ suite('NotebookProviderInfoStore', function () {
|
||||
new class extends mock<IFileService>() {
|
||||
override hasProvider() { return true; }
|
||||
},
|
||||
new class extends mock<INotebookEditorModelResolverService>() { }
|
||||
new class extends mock<INotebookEditorModelResolverService>() { },
|
||||
new class extends mock<IUriIdentityService>() { }
|
||||
);
|
||||
disposables.add(store);
|
||||
|
||||
|
||||
@@ -239,28 +239,24 @@
|
||||
|
||||
.scm-view .scm-input {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 11px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.scm-view .scm-input .actions {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
right: 20px;
|
||||
z-index: 2;
|
||||
.scm-view .scm-input .scm-editor .scm-editor-toolbar {
|
||||
padding: 1px 3px 1px 1px;
|
||||
}
|
||||
|
||||
.scm-view .scm-input .actions .actions-container {
|
||||
background-color: var(--vscode-input-background);
|
||||
.scm-view .scm-input .scm-editor .scm-editor-toolbar.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.scm-view .scm-input .actions .action-label {
|
||||
border-radius: 5px;
|
||||
outline: 1px dashed var(--vscode-toolbar-hoverOutline);
|
||||
outline-offset: -1px;
|
||||
.scm-view .scm-input .scm-editor .scm-editor-toolbar.scroll-decoration {
|
||||
box-shadow: var(--vscode-scrollbar-shadow) 0 6px 6px -6px inset;
|
||||
}
|
||||
|
||||
.scm-view .scm-input .actions .action-label.codicon.codicon-debug-stop {
|
||||
.scm-view .scm-input .scm-editor .scm-editor-toolbar .action-label.codicon.codicon-debug-stop {
|
||||
color: var(--vscode-icon-foreground) !important;
|
||||
}
|
||||
|
||||
@@ -275,10 +271,12 @@
|
||||
.scm-view .scm-editor {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid var(--vscode-input-border, transparent);
|
||||
background-color: var(--vscode-input-background);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.scm-view .button-container {
|
||||
@@ -329,31 +327,23 @@
|
||||
outline: 1px solid var(--vscode-panelInput-border);
|
||||
}
|
||||
|
||||
.scm-view .scm-editor-container {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--vscode-input-background);
|
||||
border: 1px solid var(--vscode-input-border, transparent);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.scm-view .scm-editor-container.synthetic-focus,
|
||||
.monaco-workbench .part.panel .scm-view .scm-editor-container.synthetic-focus {
|
||||
.scm-view .scm-editor.synthetic-focus,
|
||||
.monaco-workbench .part.panel .scm-view .scm-editor.synthetic-focus {
|
||||
outline: 1px solid var(--vscode-focusBorder);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.scm-view .scm-editor-container.validation-info {
|
||||
.scm-view .scm-editor.validation-info {
|
||||
outline: 1px solid var(--vscode-inputValidation-infoBorder) !important;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.scm-view .scm-editor-container.validation-warning {
|
||||
.scm-view .scm-editor.validation-warning {
|
||||
outline: 1px solid var(--vscode-inputValidation-warningBorder) !important;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.scm-view .scm-editor-container.validation-error {
|
||||
.scm-view .scm-editor.validation-error {
|
||||
outline: 1px solid var(--vscode-inputValidation-errorBorder) !important;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
@@ -267,6 +267,11 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
|
||||
markdownDescription: localize('inputFontSize', "Controls the font size for the input message in pixels."),
|
||||
default: 13
|
||||
},
|
||||
'scm.inputMaxLines': {
|
||||
type: 'number',
|
||||
markdownDescription: localize('inputMaxLines', "Controls the maximum number of lines that the input will auto-grow to."),
|
||||
default: 10
|
||||
},
|
||||
'scm.alwaysShowRepositories': {
|
||||
type: 'boolean',
|
||||
markdownDescription: localize('alwaysShowRepository', "Controls whether repositories should always be visible in the Source Control view."),
|
||||
|
||||
@@ -96,6 +96,7 @@ import { fillEditorsDragData } from 'vs/workbench/browser/dnd';
|
||||
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
|
||||
import { CodeDataTransfers } from 'vs/platform/dnd/browser/dnd';
|
||||
import { FormatOnType } from 'vs/editor/contrib/format/browser/formatActions';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
|
||||
type TreeElement = ISCMRepository | ISCMInput | ISCMActionButton | ISCMResourceGroup | IResourceNode<ISCMResource, ISCMResourceGroup> | ISCMResource;
|
||||
|
||||
@@ -1808,6 +1809,7 @@ class SCMInputWidget {
|
||||
private editorContainer: HTMLElement;
|
||||
private placeholderTextContainer: HTMLElement;
|
||||
private inputEditor: CodeEditorWidget;
|
||||
private toolbarContainer: HTMLElement;
|
||||
private actionBar: ActionBar;
|
||||
private readonly disposables = new DisposableStore();
|
||||
|
||||
@@ -1837,7 +1839,7 @@ class SCMInputWidget {
|
||||
}
|
||||
|
||||
this.clearValidation();
|
||||
this.editorContainer.classList.remove('synthetic-focus');
|
||||
this.element.classList.remove('synthetic-focus');
|
||||
|
||||
this.repositoryDisposables.clear();
|
||||
this.repositoryIdContextKey.set(input?.repository.id);
|
||||
@@ -1958,11 +1960,8 @@ class SCMInputWidget {
|
||||
this.repositoryDisposables.add(input.onDidChangeEnablement(enabled => updateEnablement(enabled)));
|
||||
updateEnablement(input.enabled);
|
||||
|
||||
// ActionBar
|
||||
// Toolbar
|
||||
const onDidChangeActionButton = () => {
|
||||
// Update placeholder width to accommodate for the action bar
|
||||
this.placeholderTextContainer.style.width = input.actionButton ? 'calc(100% - 26px)' : '100%';
|
||||
|
||||
this.actionBar.clear();
|
||||
if (!input.actionButton) {
|
||||
return;
|
||||
@@ -1976,6 +1975,7 @@ class SCMInputWidget {
|
||||
() => this.commandService.executeCommand(input.actionButton!.command.id, ...(input.actionButton!.command.arguments || [])));
|
||||
|
||||
this.actionBar.push(action, { icon: true, label: false });
|
||||
this.layout();
|
||||
};
|
||||
|
||||
this.repositoryDisposables.add(input.onDidChangeActionButton(onDidChangeActionButton, this));
|
||||
@@ -2027,6 +2027,7 @@ class SCMInputWidget {
|
||||
this.element = append(container, $('.scm-editor'));
|
||||
this.editorContainer = append(this.element, $('.scm-editor-container'));
|
||||
this.placeholderTextContainer = append(this.editorContainer, $('.scm-editor-placeholder'));
|
||||
this.toolbarContainer = append(this.element, $('.scm-editor-toolbar'));
|
||||
|
||||
const fontFamily = this.getInputEditorFontFamily();
|
||||
const fontSize = this.getInputEditorFontSize();
|
||||
@@ -2049,7 +2050,10 @@ class SCMInputWidget {
|
||||
wrappingIndent: 'none',
|
||||
padding: { top: 2, bottom: 2 },
|
||||
quickSuggestions: false,
|
||||
scrollbar: { alwaysConsumeMouseWheel: false },
|
||||
scrollbar: {
|
||||
alwaysConsumeMouseWheel: false,
|
||||
vertical: 'hidden'
|
||||
},
|
||||
overflowWidgetsDomNode,
|
||||
formatOnType: true,
|
||||
renderWhitespace: 'none',
|
||||
@@ -2076,9 +2080,6 @@ class SCMInputWidget {
|
||||
])
|
||||
};
|
||||
|
||||
this.actionBar = new ActionBar(append(this.element, $('.actions')));
|
||||
this.disposables.add(this.actionBar);
|
||||
|
||||
const services = new ServiceCollection([IContextKeyService, contextKeyService2]);
|
||||
const instantiationService2 = instantiationService.createChild(services);
|
||||
this.inputEditor = instantiationService2.createInstance(CodeEditorWidget, this.editorContainer, editorOptions, codeEditorWidgetOptions);
|
||||
@@ -2089,11 +2090,11 @@ class SCMInputWidget {
|
||||
this.scmViewService.focus(this.input.repository);
|
||||
}
|
||||
|
||||
this.editorContainer.classList.add('synthetic-focus');
|
||||
this.element.classList.add('synthetic-focus');
|
||||
this.renderValidation();
|
||||
}));
|
||||
this.disposables.add(this.inputEditor.onDidBlurEditorText(() => {
|
||||
this.editorContainer.classList.remove('synthetic-focus');
|
||||
this.element.classList.remove('synthetic-focus');
|
||||
|
||||
setTimeout(() => {
|
||||
if (!this.validation || !this.validationHasFocus) {
|
||||
@@ -2113,6 +2114,9 @@ class SCMInputWidget {
|
||||
firstLineKey.set(viewPosition.lineNumber === 1 && viewPosition.column === 1);
|
||||
lastLineKey.set(viewPosition.lineNumber === lastLineNumber && viewPosition.column === lastLineCol);
|
||||
}));
|
||||
this.disposables.add(this.inputEditor.onDidScrollChange(e => {
|
||||
this.toolbarContainer.classList.toggle('scroll-decoration', e.scrollTop > 0);
|
||||
}));
|
||||
|
||||
const relevantSettings = [
|
||||
'scm.inputFontFamily',
|
||||
@@ -2153,16 +2157,23 @@ class SCMInputWidget {
|
||||
}));
|
||||
|
||||
this.onDidChangeContentHeight = Event.signal(Event.filter(this.inputEditor.onDidContentSizeChange, e => e.contentHeightChanged, this.disposables));
|
||||
|
||||
// Toolbar
|
||||
this.actionBar = new ActionBar(this.toolbarContainer);
|
||||
this.disposables.add(this.actionBar);
|
||||
}
|
||||
|
||||
getContentHeight(): number {
|
||||
const editorContentHeight = this.inputEditor.getContentHeight();
|
||||
return Math.min(editorContentHeight, 134);
|
||||
const editorContextHeightMax = this.getInputEditorMaxHeight();
|
||||
|
||||
return Math.min(editorContentHeight, editorContextHeightMax);
|
||||
}
|
||||
|
||||
layout(): void {
|
||||
const editorHeight = this.getContentHeight();
|
||||
const dimension = new Dimension(this.element.clientWidth - 2, editorHeight);
|
||||
const toolbarWidth = this.toolbarContainer.clientWidth;
|
||||
const dimension = new Dimension(this.element.clientWidth - toolbarWidth, editorHeight);
|
||||
|
||||
if (dimension.width < 0) {
|
||||
this.lastLayoutWasTrash = true;
|
||||
@@ -2171,6 +2182,8 @@ class SCMInputWidget {
|
||||
|
||||
this.lastLayoutWasTrash = false;
|
||||
this.inputEditor.layout(dimension);
|
||||
this.placeholderTextContainer.style.width = `${dimension.width}px`;
|
||||
this.toolbarContainer.classList.toggle('hidden', this.input?.actionButton === undefined);
|
||||
this.renderValidation();
|
||||
|
||||
if (this.shouldFocusAfterLayout) {
|
||||
@@ -2187,7 +2200,7 @@ class SCMInputWidget {
|
||||
}
|
||||
|
||||
this.inputEditor.focus();
|
||||
this.editorContainer.classList.add('synthetic-focus');
|
||||
this.element.classList.add('synthetic-focus');
|
||||
}
|
||||
|
||||
hasFocus(): boolean {
|
||||
@@ -2197,9 +2210,9 @@ class SCMInputWidget {
|
||||
private renderValidation(): void {
|
||||
this.clearValidation();
|
||||
|
||||
this.editorContainer.classList.toggle('validation-info', this.validation?.type === InputValidationType.Information);
|
||||
this.editorContainer.classList.toggle('validation-warning', this.validation?.type === InputValidationType.Warning);
|
||||
this.editorContainer.classList.toggle('validation-error', this.validation?.type === InputValidationType.Error);
|
||||
this.element.classList.toggle('validation-info', this.validation?.type === InputValidationType.Information);
|
||||
this.element.classList.toggle('validation-warning', this.validation?.type === InputValidationType.Warning);
|
||||
this.element.classList.toggle('validation-error', this.validation?.type === InputValidationType.Error);
|
||||
|
||||
if (!this.validation || !this.inputEditor.hasTextFocus()) {
|
||||
return;
|
||||
@@ -2208,16 +2221,16 @@ class SCMInputWidget {
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
this.validationDisposable = this.contextViewService.showContextView({
|
||||
getAnchor: () => this.editorContainer,
|
||||
getAnchor: () => this.element,
|
||||
render: container => {
|
||||
this.editorContainer.style.borderBottomLeftRadius = '0';
|
||||
this.editorContainer.style.borderBottomRightRadius = '0';
|
||||
this.element.style.borderBottomLeftRadius = '0';
|
||||
this.element.style.borderBottomRightRadius = '0';
|
||||
|
||||
const validationContainer = append(container, $('.scm-editor-validation-container'));
|
||||
validationContainer.classList.toggle('validation-info', this.validation!.type === InputValidationType.Information);
|
||||
validationContainer.classList.toggle('validation-warning', this.validation!.type === InputValidationType.Warning);
|
||||
validationContainer.classList.toggle('validation-error', this.validation!.type === InputValidationType.Error);
|
||||
validationContainer.style.width = `${this.editorContainer.clientWidth + 2}px`;
|
||||
validationContainer.style.width = `${this.element.clientWidth + 2}px`;
|
||||
const element = append(validationContainer, $('.scm-editor-validation'));
|
||||
|
||||
const message = this.validation!.message;
|
||||
@@ -2229,8 +2242,8 @@ class SCMInputWidget {
|
||||
disposables.add(tracker.onDidFocus(() => (this.validationHasFocus = true)));
|
||||
disposables.add(tracker.onDidBlur(() => {
|
||||
this.validationHasFocus = false;
|
||||
this.editorContainer.style.borderBottomLeftRadius = '2px';
|
||||
this.editorContainer.style.borderBottomRightRadius = '2px';
|
||||
this.element.style.borderBottomLeftRadius = '2px';
|
||||
this.element.style.borderBottomRightRadius = '2px';
|
||||
this.contextViewService.hideContextView();
|
||||
}));
|
||||
|
||||
@@ -2239,8 +2252,8 @@ class SCMInputWidget {
|
||||
actionHandler: {
|
||||
callback: (link) => {
|
||||
openLinkFromMarkdown(this.openerService, link, message.isTrusted);
|
||||
this.editorContainer.style.borderBottomLeftRadius = '2px';
|
||||
this.editorContainer.style.borderBottomRightRadius = '2px';
|
||||
this.element.style.borderBottomLeftRadius = '2px';
|
||||
this.element.style.borderBottomRightRadius = '2px';
|
||||
this.contextViewService.hideContextView();
|
||||
},
|
||||
disposables: disposables
|
||||
@@ -2253,8 +2266,8 @@ class SCMInputWidget {
|
||||
const actionbar = new ActionBar(actionsContainer);
|
||||
const action = new Action('scmInputWidget.validationMessage.close', localize('label.close', "Close"), ThemeIcon.asClassName(Codicon.close), true, () => {
|
||||
this.contextViewService.hideContextView();
|
||||
this.editorContainer.style.borderBottomLeftRadius = '2px';
|
||||
this.editorContainer.style.borderBottomRightRadius = '2px';
|
||||
this.element.style.borderBottomLeftRadius = '2px';
|
||||
this.element.style.borderBottomRightRadius = '2px';
|
||||
});
|
||||
disposables.add(actionbar);
|
||||
actionbar.push(action, { icon: true, label: false });
|
||||
@@ -2263,8 +2276,8 @@ class SCMInputWidget {
|
||||
},
|
||||
onHide: () => {
|
||||
this.validationHasFocus = false;
|
||||
this.editorContainer.style.borderBottomLeftRadius = '2px';
|
||||
this.editorContainer.style.borderBottomRightRadius = '2px';
|
||||
this.element.style.borderBottomLeftRadius = '2px';
|
||||
this.element.style.borderBottomRightRadius = '2px';
|
||||
disposables.dispose();
|
||||
},
|
||||
anchorAlignment: AnchorAlignment.LEFT
|
||||
@@ -2289,6 +2302,19 @@ class SCMInputWidget {
|
||||
return this.configurationService.getValue<number>('scm.inputFontSize');
|
||||
}
|
||||
|
||||
private getInputEditorMaxLines(): number {
|
||||
return this.configurationService.getValue<number>('scm.inputMaxLines');
|
||||
}
|
||||
|
||||
private getInputEditorMaxHeight(): number {
|
||||
const maxLines = this.getInputEditorMaxLines();
|
||||
const fontSize = this.getInputEditorFontSize();
|
||||
const lineHeight = this.computeLineHeight(fontSize);
|
||||
const { top, bottom } = this.inputEditor.getOption(EditorOption.padding);
|
||||
|
||||
return maxLines * lineHeight + top + bottom;
|
||||
}
|
||||
|
||||
private computeLineHeight(fontSize: number): number {
|
||||
return Math.round(fontSize * 1.5);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import 'vs/css!./media/scm';
|
||||
import { localize } from 'vs/nls';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { VIEWLET_ID } from 'vs/workbench/contrib/scm/common/scm';
|
||||
import { ISCMViewService, VIEWLET_ID } from 'vs/workbench/contrib/scm/common/scm';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
@@ -21,6 +21,7 @@ import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneCont
|
||||
export class SCMViewPaneContainer extends ViewPaneContainer {
|
||||
|
||||
constructor(
|
||||
@ISCMViewService private readonly scmViewService: ISCMViewService,
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@@ -47,4 +48,9 @@ export class SCMViewPaneContainer extends ViewPaneContainer {
|
||||
override getTitle(): string {
|
||||
return localize('source control', "Source Control");
|
||||
}
|
||||
|
||||
override getActionsContext(): unknown {
|
||||
return this.scmViewService.visibleRepositories.length === 1 ? this.scmViewService.visibleRepositories[0].provider : undefined;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/
|
||||
import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/services/search/common/queryBuilder';
|
||||
import { IPatternInfo, ITextQuery, VIEW_ID } from 'vs/workbench/services/search/common/search';
|
||||
|
||||
export const TEXT_SEARCH_QUICK_ACCESS_PREFIX = '% ';
|
||||
export const TEXT_SEARCH_QUICK_ACCESS_PREFIX = '%';
|
||||
|
||||
const DEFAULT_TEXT_QUERY_BUILDER_OPTIONS: ITextQueryBuilderOptions = {
|
||||
_reason: 'quickAccessSearch',
|
||||
@@ -83,6 +83,9 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
|
||||
|
||||
override provide(picker: IQuickPick<IPickerQuickAccessItem>, token: CancellationToken, runOptions?: IQuickAccessProviderRunOptions): IDisposable {
|
||||
const disposables = new DisposableStore();
|
||||
if (TEXT_SEARCH_QUICK_ACCESS_PREFIX.length < picker.value.length) {
|
||||
picker.valueSelection = [TEXT_SEARCH_QUICK_ACCESS_PREFIX.length, picker.value.length];
|
||||
}
|
||||
disposables.add(super.provide(picker, token, runOptions));
|
||||
disposables.add(picker.onDidHide(() => this.searchModel.searchResult.toggleHighlights(false)));
|
||||
disposables.add(picker.onDidAccept(() => this.searchModel.searchResult.toggleHighlights(false)));
|
||||
@@ -272,7 +275,9 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<IPickerQuic
|
||||
return {
|
||||
picks: syncResult,
|
||||
additionalPicks: allMatches.asyncResults
|
||||
.then(asyncResults => this._getPicksFromMatches(asyncResults, MAX_FILES_SHOWN - matches.length))
|
||||
.then(asyncResults => (asyncResults.length + syncResult.length === 0) ? [{
|
||||
label: localize('noAnythingResults', "No matching results")
|
||||
}] : this._getPicksFromMatches(asyncResults, MAX_FILES_SHOWN - matches.length))
|
||||
.then(picks => {
|
||||
if (picks.length > 0) {
|
||||
this.searchModel.searchResult.toggleHighlights(true);
|
||||
|
||||
@@ -41,7 +41,7 @@ import { CellSearchModel, ICellMatch, contentMatchesToTextSearchMatches, isIFile
|
||||
import { INotebookSearchService } from 'vs/workbench/contrib/search/common/notebookSearch';
|
||||
import { ReplacePattern } from 'vs/workbench/services/search/common/replace';
|
||||
import { IFileMatch, IPatternInfo, ISearchComplete, ISearchConfigurationProperties, ISearchProgressItem, ISearchRange, ISearchService, ITextQuery, ITextSearchContext, ITextSearchMatch, ITextSearchPreviewOptions, ITextSearchResult, ITextSearchStats, OneLineRange, resultIsMatch, SearchCompletionExitCode, SearchSortOrder } from 'vs/workbench/services/search/common/search';
|
||||
import { addContextToEditorMatches, editorMatchesToTextSearchResults } from 'vs/workbench/services/search/common/searchHelpers';
|
||||
import { getTextSearchMatchWithModelContext, editorMatchesToTextSearchResults } from 'vs/workbench/services/search/common/searchHelpers';
|
||||
|
||||
export class Match {
|
||||
|
||||
@@ -245,7 +245,7 @@ export class CellMatch {
|
||||
return;
|
||||
}
|
||||
this.cell.resolveTextModel().then((textModel) => {
|
||||
const textResultsWithContext = addContextToEditorMatches(textSearchMatches, textModel, this.parent.parent().query!);
|
||||
const textResultsWithContext = getTextSearchMatchWithModelContext(textSearchMatches, textModel, this.parent.parent().query!);
|
||||
const contexts = textResultsWithContext.filter((result => !resultIsMatch(result)) as ((a: any) => a is ITextSearchContext));
|
||||
contexts.map(context => ({ ...context, lineNumber: context.lineNumber + 1 }))
|
||||
.forEach((context) => { this._context.set(context.lineNumber, context.text); });
|
||||
@@ -567,10 +567,7 @@ export class FileMatch extends Disposable implements IFileMatch {
|
||||
});
|
||||
});
|
||||
|
||||
this.addContext(
|
||||
addContextToEditorMatches(textSearchResults, model, this.parent().parent().query!)
|
||||
.filter((result => !resultIsMatch(result)) as ((a: any) => a is ITextSearchContext))
|
||||
.map(context => ({ ...context, lineNumber: context.lineNumber + 1 })));
|
||||
this.addContext(getTextSearchMatchWithModelContext(textSearchResults, model, this.parent().parent().query!));
|
||||
|
||||
this._onChange.fire({ forceUpdateModel: modelChange });
|
||||
this.updateHighlights();
|
||||
@@ -1041,7 +1038,7 @@ export class FolderMatch extends Disposable {
|
||||
}
|
||||
|
||||
public createIntermediateFolderMatch(resource: URI, id: string, index: number, query: ITextQuery, baseWorkspaceFolder: FolderMatchWorkspaceRoot): FolderMatchWithResource {
|
||||
const folderMatch = this.instantiationService.createInstance(FolderMatchWithResource, resource, id, index, query, this, this._searchResult, baseWorkspaceFolder);
|
||||
const folderMatch = this._register(this.instantiationService.createInstance(FolderMatchWithResource, resource, id, index, query, this, this._searchResult, baseWorkspaceFolder));
|
||||
this.configureIntermediateMatch(folderMatch);
|
||||
this.doAddFolder(folderMatch);
|
||||
return folderMatch;
|
||||
@@ -1049,7 +1046,7 @@ export class FolderMatch extends Disposable {
|
||||
|
||||
public configureIntermediateMatch(folderMatch: FolderMatchWithResource) {
|
||||
const disposable = folderMatch.onChange((event) => this.onFolderChange(folderMatch, event));
|
||||
folderMatch.onDispose(() => disposable.dispose());
|
||||
this._register(folderMatch.onDispose(() => disposable.dispose()));
|
||||
}
|
||||
|
||||
clear(clearingAll = false): void {
|
||||
@@ -1176,7 +1173,9 @@ export class FolderMatch extends Disposable {
|
||||
|
||||
updated.push(existingFileMatch);
|
||||
|
||||
existingFileMatch.addContext(rawFileMatch.results);
|
||||
if (rawFileMatch.results && rawFileMatch.results.length > 0) {
|
||||
existingFileMatch.addContext(rawFileMatch.results);
|
||||
}
|
||||
} else {
|
||||
if (this instanceof FolderMatchWorkspaceRoot || this instanceof FolderMatchNoRoot) {
|
||||
const fileMatch = this.createAndConfigureFileMatch(rawFileMatch, searchInstanceID);
|
||||
@@ -1379,7 +1378,7 @@ export class FolderMatchWorkspaceRoot extends FolderMatchWithResource {
|
||||
);
|
||||
parent.doAddFile(fileMatch);
|
||||
const disposable = fileMatch.onChange(({ didRemove }) => parent.onFileChange(fileMatch, didRemove));
|
||||
fileMatch.onDispose(() => disposable.dispose());
|
||||
this._register(fileMatch.onDispose(() => disposable.dispose()));
|
||||
return fileMatch;
|
||||
}
|
||||
|
||||
@@ -1431,17 +1430,17 @@ export class FolderMatchNoRoot extends FolderMatch {
|
||||
}
|
||||
|
||||
createAndConfigureFileMatch(rawFileMatch: IFileMatch, searchInstanceID: string): FileMatch {
|
||||
const fileMatch = this.instantiationService.createInstance(
|
||||
const fileMatch = this._register(this.instantiationService.createInstance(
|
||||
FileMatch,
|
||||
this._query.contentPattern,
|
||||
this._query.previewOptions,
|
||||
this._query.maxResults,
|
||||
this, rawFileMatch,
|
||||
null,
|
||||
searchInstanceID);
|
||||
searchInstanceID));
|
||||
this.doAddFile(fileMatch);
|
||||
const disposable = fileMatch.onChange(({ didRemove }) => this.onFileChange(fileMatch, didRemove));
|
||||
fileMatch.onDispose(() => disposable.dispose());
|
||||
this._register(fileMatch.onDispose(() => disposable.dispose()));
|
||||
return fileMatch;
|
||||
}
|
||||
}
|
||||
@@ -1590,7 +1589,7 @@ export class SearchResult extends Disposable {
|
||||
private _showHighlights: boolean = false;
|
||||
private _query: ITextQuery | null = null;
|
||||
private _rangeHighlightDecorations: RangeHighlightDecorations;
|
||||
private disposePastResults: () => void = () => { };
|
||||
private disposePastResults: () => Promise<void> = () => Promise.resolve();
|
||||
private _isDirty = false;
|
||||
private _onWillChangeModelListener: IDisposable | undefined;
|
||||
private _onDidChangeModelListener: IDisposable | undefined;
|
||||
@@ -1674,10 +1673,11 @@ export class SearchResult extends Disposable {
|
||||
set query(query: ITextQuery | null) {
|
||||
// When updating the query we could change the roots, so keep a reference to them to clean up when we trigger `disposePastResults`
|
||||
const oldFolderMatches = this.folderMatches();
|
||||
new Promise<void>(resolve => this.disposePastResults = resolve)
|
||||
.then(() => oldFolderMatches.forEach(match => match.clear()))
|
||||
.then(() => oldFolderMatches.forEach(match => match.dispose()))
|
||||
.then(() => this._isDirty = false);
|
||||
this.disposePastResults = async () => {
|
||||
oldFolderMatches.forEach(match => match.clear());
|
||||
oldFolderMatches.forEach(match => match.dispose());
|
||||
this._isDirty = false;
|
||||
};
|
||||
|
||||
this._rangeHighlightDecorations.removeHighlightRange();
|
||||
this._folderMatchesMap = TernarySearchTree.forUris<FolderMatchWithResource>(key => this.uriIdentityService.extUri.ignorePathCasing(key));
|
||||
@@ -1736,12 +1736,12 @@ export class SearchResult extends Disposable {
|
||||
private _createBaseFolderMatch(resource: URI | null, id: string, index: number, query: ITextQuery): FolderMatch {
|
||||
let folderMatch: FolderMatch;
|
||||
if (resource) {
|
||||
folderMatch = this.instantiationService.createInstance(FolderMatchWorkspaceRoot, resource, id, index, query, this);
|
||||
folderMatch = this._register(this.instantiationService.createInstance(FolderMatchWorkspaceRoot, resource, id, index, query, this));
|
||||
} else {
|
||||
folderMatch = this.instantiationService.createInstance(FolderMatchNoRoot, id, index, query, this);
|
||||
folderMatch = this._register(this.instantiationService.createInstance(FolderMatchNoRoot, id, index, query, this));
|
||||
}
|
||||
const disposable = folderMatch.onChange((event) => this._onChange.fire(event));
|
||||
folderMatch.onDispose(() => disposable.dispose());
|
||||
this._register(folderMatch.onDispose(() => disposable.dispose()));
|
||||
return folderMatch;
|
||||
}
|
||||
|
||||
@@ -1922,13 +1922,13 @@ export class SearchResult extends Disposable {
|
||||
this._rangeHighlightDecorations.removeHighlightRange();
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
override async dispose(): Promise<void> {
|
||||
this._onWillChangeModelListener?.dispose();
|
||||
this._onDidChangeModelListener?.dispose();
|
||||
this.disposePastResults();
|
||||
this.disposeMatches();
|
||||
this._rangeHighlightDecorations.dispose();
|
||||
this.disposeMatches();
|
||||
super.dispose();
|
||||
await this.disposePastResults();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2080,7 +2080,7 @@ export class SearchModel extends Disposable {
|
||||
|
||||
this._searchResult.query = this._searchQuery;
|
||||
|
||||
const progressEmitter = new Emitter<void>();
|
||||
const progressEmitter = this._register(new Emitter<void>());
|
||||
this._replacePattern = new ReplacePattern(this.replaceString, this._searchQuery.contentPattern);
|
||||
|
||||
// In search on type case, delay the streaming of results just a bit, so that we don't flash the only "local results" fast path
|
||||
@@ -2099,14 +2099,21 @@ export class SearchModel extends Disposable {
|
||||
}
|
||||
|
||||
const start = Date.now();
|
||||
let event: IDisposable | undefined;
|
||||
|
||||
Promise.race([asyncResults, Event.toPromise(progressEmitter.event)]).finally(() => {
|
||||
const progressEmitterPromise = new Promise(resolve => {
|
||||
event = Event.once(progressEmitter.event)(resolve);
|
||||
return event;
|
||||
});
|
||||
|
||||
Promise.race([asyncResults, progressEmitterPromise]).finally(() => {
|
||||
/* __GDPR__
|
||||
"searchResultsFirstRender" : {
|
||||
"owner": "roblourens",
|
||||
"duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }
|
||||
}
|
||||
*/
|
||||
event?.dispose();
|
||||
this.telemetryService.publicLog('searchResultsFirstRender', { duration: Date.now() - start });
|
||||
});
|
||||
|
||||
@@ -2331,9 +2338,9 @@ export class RangeHighlightDecorations implements IDisposable {
|
||||
dispose() {
|
||||
if (this._model) {
|
||||
this.removeHighlightRange();
|
||||
this._modelDisposables.dispose();
|
||||
this._model = null;
|
||||
}
|
||||
this._modelDisposables.dispose();
|
||||
}
|
||||
|
||||
private static readonly _RANGE_HIGHLIGHT_DECORATION = ModelDecorationOptions.register({
|
||||
|
||||
@@ -1281,13 +1281,6 @@ export class SearchView extends ViewPane {
|
||||
}
|
||||
|
||||
editor = editor ?? this.editorService.activeTextEditorControl;
|
||||
if (isDiffEditor(editor)) {
|
||||
if (editor.getOriginalEditor().hasTextFocus()) {
|
||||
editor = editor.getOriginalEditor();
|
||||
} else {
|
||||
editor = editor.getModifiedEditor();
|
||||
}
|
||||
}
|
||||
|
||||
if (!editor) {
|
||||
return null;
|
||||
@@ -2147,7 +2140,17 @@ export function getEditorSelectionFromMatch(element: FileMatchOrMatch, viewModel
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getSelectionTextFromEditor(allowUnselectedWord: boolean, editor: IEditor): string | null {
|
||||
export function getSelectionTextFromEditor(allowUnselectedWord: boolean, activeEditor: IEditor): string | null {
|
||||
|
||||
let editor = activeEditor;
|
||||
|
||||
if (isDiffEditor(editor)) {
|
||||
if (editor.getOriginalEditor().hasTextFocus()) {
|
||||
editor = editor.getOriginalEditor();
|
||||
} else {
|
||||
editor = editor.getModifiedEditor();
|
||||
}
|
||||
}
|
||||
|
||||
if (!isCodeEditor(editor) || !editor.hasModel()) {
|
||||
return null;
|
||||
|
||||
@@ -18,16 +18,18 @@ import { MockObjectTree } from 'vs/workbench/contrib/search/test/browser/mockSea
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService';
|
||||
import { createFileUriFromPathFromRoot, stubModelService, stubNotebookEditorService } from 'vs/workbench/contrib/search/test/browser/searchTestCommon';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
suite('Search Actions', () => {
|
||||
|
||||
let instantiationService: TestInstantiationService;
|
||||
let counter: number;
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
|
||||
setup(() => {
|
||||
instantiationService = new TestInstantiationService();
|
||||
instantiationService.stub(IModelService, stubModelService(instantiationService));
|
||||
instantiationService.stub(INotebookEditorService, stubNotebookEditorService(instantiationService));
|
||||
instantiationService.stub(IModelService, stubModelService(instantiationService, (e) => store.add(e)));
|
||||
instantiationService.stub(INotebookEditorService, stubNotebookEditorService(instantiationService, (e) => store.add(e)));
|
||||
instantiationService.stub(IKeybindingService, {});
|
||||
instantiationService.stub(ILabelService, { getUriBasenameLabel: (uri: URI) => '' });
|
||||
instantiationService.stub(IKeybindingService, 'resolveKeybinding', (keybinding: Keybinding) => USLayoutResolvedKeybinding.resolveKeybinding(keybinding, OS));
|
||||
@@ -113,14 +115,18 @@ suite('Search Actions', () => {
|
||||
};
|
||||
|
||||
const searchModel = instantiationService.createInstance(SearchModel);
|
||||
store.add(searchModel);
|
||||
const folderMatch = instantiationService.createInstance(FolderMatch, URI.file('somepath'), '', 0, {
|
||||
type: QueryType.Text, folderQueries: [{ folder: createFileUriFromPathFromRoot() }], contentPattern: {
|
||||
pattern: ''
|
||||
}
|
||||
}, searchModel.searchResult, searchModel.searchResult, null);
|
||||
return instantiationService.createInstance(FileMatch, {
|
||||
store.add(folderMatch);
|
||||
const fileMatch = instantiationService.createInstance(FileMatch, {
|
||||
pattern: ''
|
||||
}, undefined, undefined, folderMatch, rawMatch, null, '');
|
||||
store.add(fileMatch);
|
||||
return fileMatch;
|
||||
}
|
||||
|
||||
function aMatch(fileMatch: FileMatch): Match {
|
||||
|
||||
@@ -40,6 +40,7 @@ import { INotebookSearchService } from 'vs/workbench/contrib/search/common/noteb
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
const nullEvent = new class {
|
||||
id: number = -1;
|
||||
@@ -65,6 +66,7 @@ const lineOneRange = new OneLineRange(1, 0, 1);
|
||||
suite('SearchModel', () => {
|
||||
|
||||
let instantiationService: TestInstantiationService;
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
|
||||
const testSearchStats: IFileSearchStats = {
|
||||
fromCache: false,
|
||||
@@ -92,7 +94,11 @@ suite('SearchModel', () => {
|
||||
instantiationService.stub(INotebookEditorService, stubNotebookEditorService(instantiationService));
|
||||
instantiationService.stub(ISearchService, {});
|
||||
instantiationService.stub(ISearchService, 'textSearch', Promise.resolve({ results: [] }));
|
||||
instantiationService.stub(IUriIdentityService, new UriIdentityService(new FileService(new NullLogService())));
|
||||
const fileService = new FileService(new NullLogService());
|
||||
store.add(fileService);
|
||||
const uriIdentityService = new UriIdentityService(fileService);
|
||||
store.add(uriIdentityService);
|
||||
instantiationService.stub(IUriIdentityService, uriIdentityService);
|
||||
instantiationService.stub(ILogService, new NullLogService());
|
||||
});
|
||||
|
||||
@@ -164,12 +170,18 @@ suite('SearchModel', () => {
|
||||
function canceleableSearchService(tokenSource: CancellationTokenSource): ISearchService {
|
||||
return <ISearchService>{
|
||||
textSearch(query: ITextQuery, token?: CancellationToken, onProgress?: (result: ISearchProgressItem) => void): Promise<ISearchComplete> {
|
||||
token?.onCancellationRequested(() => tokenSource.cancel());
|
||||
const disposable = token?.onCancellationRequested(() => tokenSource.cancel());
|
||||
if (disposable) {
|
||||
store.add(disposable);
|
||||
}
|
||||
|
||||
return this.textSearchSplitSyncAsync(query, token, onProgress).asyncResults;
|
||||
},
|
||||
fileSearch(query: IFileQuery, token?: CancellationToken): Promise<ISearchComplete> {
|
||||
token?.onCancellationRequested(() => tokenSource.cancel());
|
||||
const disposable = token?.onCancellationRequested(() => tokenSource.cancel());
|
||||
if (disposable) {
|
||||
store.add(disposable);
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
queueMicrotask(() => {
|
||||
resolve(<any>{});
|
||||
@@ -177,7 +189,10 @@ suite('SearchModel', () => {
|
||||
});
|
||||
},
|
||||
textSearchSplitSyncAsync(query: ITextQuery, token?: CancellationToken | undefined, onProgress?: ((result: ISearchProgressItem) => void) | undefined): { syncResults: ISearchComplete; asyncResults: Promise<ISearchComplete> } {
|
||||
token?.onCancellationRequested(() => tokenSource.cancel());
|
||||
const disposable = token?.onCancellationRequested(() => tokenSource.cancel());
|
||||
if (disposable) {
|
||||
store.add(disposable);
|
||||
}
|
||||
return {
|
||||
syncResults: {
|
||||
results: [],
|
||||
@@ -219,7 +234,10 @@ suite('SearchModel', () => {
|
||||
completeData: Promise<ISearchComplete>;
|
||||
allScannedFiles: Promise<ResourceSet>;
|
||||
} {
|
||||
token?.onCancellationRequested(() => tokenSource?.cancel());
|
||||
const disposable = token?.onCancellationRequested(() => tokenSource?.cancel());
|
||||
if (disposable) {
|
||||
store.add(disposable);
|
||||
}
|
||||
const localResults = new ResourceMap<IFileMatchWithCells | null>(uri => uri.path);
|
||||
|
||||
results.forEach(r => {
|
||||
@@ -252,6 +270,7 @@ suite('SearchModel', () => {
|
||||
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
|
||||
|
||||
const testObject: SearchModel = instantiationService.createInstance(SearchModel);
|
||||
store.add(testObject);
|
||||
await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
|
||||
|
||||
const actual = testObject.searchResult.matches();
|
||||
@@ -352,6 +371,7 @@ suite('SearchModel', () => {
|
||||
const notebookSearchService = instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([aRawMatchWithCells('/1', cellMatchMd, cellMatchCode)], undefined));
|
||||
const notebookSearch = sinon.spy(notebookSearchService, "notebookSearch");
|
||||
const model: SearchModel = instantiationService.createInstance(SearchModel);
|
||||
store.add(model);
|
||||
await model.search({ contentPattern: { pattern: 'test' }, type: QueryType.Text, folderQueries }).asyncResults;
|
||||
const actual = model.searchResult.matches();
|
||||
|
||||
@@ -404,6 +424,7 @@ suite('SearchModel', () => {
|
||||
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
|
||||
|
||||
const testObject: SearchModel = instantiationService.createInstance(SearchModel);
|
||||
store.add(testObject);
|
||||
await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
|
||||
|
||||
assert.ok(target.calledThrice);
|
||||
@@ -421,6 +442,7 @@ suite('SearchModel', () => {
|
||||
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
|
||||
|
||||
const testObject = instantiationService.createInstance(SearchModel);
|
||||
store.add(testObject);
|
||||
const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
|
||||
|
||||
return result.then(() => {
|
||||
@@ -443,6 +465,7 @@ suite('SearchModel', () => {
|
||||
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
|
||||
|
||||
const testObject = instantiationService.createInstance(SearchModel);
|
||||
store.add(testObject);
|
||||
const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
|
||||
|
||||
return result.then(() => {
|
||||
@@ -466,6 +489,7 @@ suite('SearchModel', () => {
|
||||
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
|
||||
|
||||
const testObject = instantiationService.createInstance(SearchModel);
|
||||
store.add(testObject);
|
||||
const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
|
||||
|
||||
return result.then(() => { }, () => {
|
||||
@@ -488,6 +512,7 @@ suite('SearchModel', () => {
|
||||
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
|
||||
|
||||
const testObject = instantiationService.createInstance(SearchModel);
|
||||
store.add(testObject);
|
||||
const result = testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
|
||||
|
||||
deferredPromise.cancel();
|
||||
@@ -511,6 +536,7 @@ suite('SearchModel', () => {
|
||||
instantiationService.stub(ISearchService, searchServiceWithResults(results, { limitHit: false, messages: [], results: [] }));
|
||||
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
|
||||
const testObject: SearchModel = instantiationService.createInstance(SearchModel);
|
||||
store.add(testObject);
|
||||
await testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries }).asyncResults;
|
||||
assert.ok(!testObject.searchResult.isEmpty());
|
||||
|
||||
@@ -522,9 +548,11 @@ suite('SearchModel', () => {
|
||||
|
||||
test('Search Model: Previous search is cancelled when new search is called', async () => {
|
||||
const tokenSource = new CancellationTokenSource();
|
||||
store.add(tokenSource);
|
||||
instantiationService.stub(ISearchService, canceleableSearchService(tokenSource));
|
||||
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], tokenSource));
|
||||
const testObject: SearchModel = instantiationService.createInstance(SearchModel);
|
||||
store.add(testObject);
|
||||
testObject.search({ contentPattern: { pattern: 'somestring' }, type: QueryType.Text, folderQueries });
|
||||
instantiationService.stub(ISearchService, searchServiceWithResults([]));
|
||||
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
|
||||
@@ -542,6 +570,7 @@ suite('SearchModel', () => {
|
||||
instantiationService.stub(INotebookSearchService, notebookSearchServiceWithInfo([], undefined));
|
||||
|
||||
const testObject: SearchModel = instantiationService.createInstance(SearchModel);
|
||||
store.add(testObject);
|
||||
await testObject.search({ contentPattern: { pattern: 're' }, type: QueryType.Text, folderQueries }).asyncResults;
|
||||
testObject.replaceString = 'hello';
|
||||
let match = testObject.searchResult.matches()[0].matches()[0];
|
||||
@@ -578,14 +607,18 @@ suite('SearchModel', () => {
|
||||
const config = new TestConfigurationService();
|
||||
config.setUserConfiguration('search', { searchOnType: true });
|
||||
instantiationService.stub(IConfigurationService, config);
|
||||
return instantiationService.createInstance(ModelService);
|
||||
const modelService = instantiationService.createInstance(ModelService);
|
||||
store.add(modelService);
|
||||
return modelService;
|
||||
}
|
||||
|
||||
function stubNotebookEditorService(instantiationService: TestInstantiationService): INotebookEditorService {
|
||||
instantiationService.stub(IEditorGroupsService, new TestEditorGroupsService());
|
||||
instantiationService.stub(IContextKeyService, new MockContextKeyService());
|
||||
instantiationService.stub(IEditorService, new TestEditorService());
|
||||
return instantiationService.createInstance(NotebookEditorWidgetService);
|
||||
const notebookEditorWidgetService = instantiationService.createInstance(NotebookEditorWidgetService);
|
||||
store.add(notebookEditorWidgetService);
|
||||
return notebookEditorWidgetService;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/
|
||||
import { createFileUriFromPathFromRoot, stubModelService, stubNotebookEditorService } from 'vs/workbench/contrib/search/test/browser/searchTestCommon';
|
||||
import { IModelService } from 'vs/editor/common/services/model';
|
||||
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
suite('searchNotebookHelpers', () => {
|
||||
let instantiationService: TestInstantiationService;
|
||||
@@ -28,12 +29,16 @@ suite('searchNotebookHelpers', () => {
|
||||
let markdownContentResults: ITextSearchMatch[];
|
||||
let codeContentResults: ITextSearchMatch[];
|
||||
let codeWebviewResults: ITextSearchMatch[];
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
let counter: number = 0;
|
||||
setup(() => {
|
||||
|
||||
instantiationService = new TestInstantiationService();
|
||||
instantiationService.stub(IModelService, stubModelService(instantiationService));
|
||||
instantiationService.stub(INotebookEditorService, stubNotebookEditorService(instantiationService));
|
||||
store.add(instantiationService);
|
||||
const modelService = stubModelService(instantiationService, (e) => store.add(e));
|
||||
const notebookEditorService = stubNotebookEditorService(instantiationService, (e) => store.add(e));
|
||||
instantiationService.stub(IModelService, modelService);
|
||||
instantiationService.stub(INotebookEditorService, notebookEditorService);
|
||||
mdInputCell = {
|
||||
cellKind: CellKind.Markup, textBuffer: <IReadonlyTextBuffer>{
|
||||
getLineContent(lineNumber: number): string {
|
||||
@@ -201,14 +206,19 @@ suite('searchNotebookHelpers', () => {
|
||||
};
|
||||
|
||||
const searchModel = instantiationService.createInstance(SearchModel);
|
||||
store.add(searchModel);
|
||||
const folderMatch = instantiationService.createInstance(FolderMatch, URI.file('somepath'), '', 0, {
|
||||
type: QueryType.Text, folderQueries: [{ folder: createFileUriFromPathFromRoot() }], contentPattern: {
|
||||
pattern: ''
|
||||
}
|
||||
}, searchModel.searchResult, searchModel.searchResult, null);
|
||||
return instantiationService.createInstance(FileMatch, {
|
||||
const fileMatch = instantiationService.createInstance(FileMatch, {
|
||||
pattern: ''
|
||||
}, undefined, undefined, folderMatch, rawMatch, null, '');
|
||||
store.add(folderMatch);
|
||||
store.add(fileMatch);
|
||||
|
||||
return fileMatch;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,19 +35,25 @@ import { addToSearchResult, createFileUriFromPathFromRoot, getRootName } from 'v
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
const lineOneRange = new OneLineRange(1, 0, 1);
|
||||
|
||||
suite('SearchResult', () => {
|
||||
|
||||
let instantiationService: TestInstantiationService;
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
|
||||
setup(() => {
|
||||
instantiationService = new TestInstantiationService();
|
||||
instantiationService.stub(ITelemetryService, NullTelemetryService);
|
||||
instantiationService.stub(IModelService, stubModelService(instantiationService));
|
||||
instantiationService.stub(INotebookEditorService, stubNotebookEditorService(instantiationService));
|
||||
instantiationService.stub(IUriIdentityService, new UriIdentityService(new FileService(new NullLogService())));
|
||||
const fileService = new FileService(new NullLogService());
|
||||
store.add(fileService);
|
||||
const uriIdentityService = new UriIdentityService(fileService);
|
||||
store.add(uriIdentityService);
|
||||
instantiationService.stub(IUriIdentityService, uriIdentityService);
|
||||
instantiationService.stubPromise(IReplaceService, {});
|
||||
instantiationService.stub(IReplaceService, 'replace', () => Promise.resolve(null));
|
||||
instantiationService.stub(ILabelService, new MockLabelService());
|
||||
@@ -164,7 +170,9 @@ suite('SearchResult', () => {
|
||||
test('Match -> FileMatch -> SearchResult hierarchy exists', function () {
|
||||
|
||||
const searchModel = instantiationService.createInstance(SearchModel);
|
||||
store.add(searchModel);
|
||||
const searchResult = instantiationService.createInstance(SearchResult, searchModel);
|
||||
store.add(searchResult);
|
||||
const fileMatch = aFileMatch('far/boo', searchResult);
|
||||
const lineMatch = new Match(fileMatch, ['foo bar'], new OneLineRange(0, 0, 3), new OneLineRange(1, 0, 3));
|
||||
|
||||
@@ -283,8 +291,8 @@ suite('SearchResult', () => {
|
||||
aRawMatch('/2',
|
||||
new TextSearchMatch('preview 2', lineOneRange))]);
|
||||
|
||||
testObject.matches()[0].onDispose(target1);
|
||||
testObject.matches()[1].onDispose(target2);
|
||||
store.add(testObject.matches()[0].onDispose(target1));
|
||||
store.add(testObject.matches()[1].onDispose(target2));
|
||||
|
||||
testObject.dispose();
|
||||
|
||||
@@ -300,7 +308,7 @@ suite('SearchResult', () => {
|
||||
aRawMatch('/1',
|
||||
new TextSearchMatch('preview 1', lineOneRange))]);
|
||||
const objectToRemove = testObject.matches()[0];
|
||||
testObject.onChange(target);
|
||||
store.add(testObject.onChange(target));
|
||||
|
||||
testObject.remove(objectToRemove);
|
||||
|
||||
@@ -317,7 +325,7 @@ suite('SearchResult', () => {
|
||||
aRawMatch('/2',
|
||||
new TextSearchMatch('preview 2', lineOneRange))]);
|
||||
const arrayToRemove = testObject.matches();
|
||||
testObject.onChange(target);
|
||||
store.add(testObject.onChange(target));
|
||||
|
||||
testObject.remove(arrayToRemove);
|
||||
|
||||
@@ -362,7 +370,8 @@ suite('SearchResult', () => {
|
||||
addToSearchResult(testObject, [
|
||||
aRawMatch('/1',
|
||||
new TextSearchMatch('preview 1', lineOneRange))]);
|
||||
testObject.onChange(target);
|
||||
|
||||
store.add(testObject.onChange(target));
|
||||
const objectToRemove = testObject.matches()[0];
|
||||
|
||||
testObject.replace(objectToRemove);
|
||||
@@ -399,7 +408,7 @@ suite('SearchResult', () => {
|
||||
const arrayToRemove = [folderMatch, fileMatch, match];
|
||||
const expectedArrayResult = folderMatch.allDownstreamFileMatches().concat([fileMatch, match.parent()]);
|
||||
|
||||
testObject.onChange(target);
|
||||
store.add(testObject.onChange(target));
|
||||
testObject.batchRemove(arrayToRemove);
|
||||
|
||||
assert.ok(target.calledOnce);
|
||||
@@ -428,7 +437,7 @@ suite('SearchResult', () => {
|
||||
|
||||
const arrayToRemove = [folderMatch, fileMatch, match];
|
||||
|
||||
testObject.onChange(target);
|
||||
store.add(testObject.onChange(target));
|
||||
await testObject.batchReplace(arrayToRemove);
|
||||
|
||||
assert.ok(target.calledOnce);
|
||||
@@ -491,7 +500,7 @@ suite('SearchResult', () => {
|
||||
|
||||
const expectedArrayResult = folderMatch.allDownstreamFileMatches();
|
||||
|
||||
testObject.onChange(target);
|
||||
store.add(testObject.onChange(target));
|
||||
testObject.remove(folderMatch);
|
||||
assert.ok(target.calledOnce);
|
||||
assert.deepStrictEqual([{ elements: expectedArrayResult, removed: true, added: false, clearingAll: false }], target.args[0]);
|
||||
@@ -505,7 +514,7 @@ suite('SearchResult', () => {
|
||||
|
||||
const expectedArrayResult = folderMatch.allDownstreamFileMatches();
|
||||
|
||||
testObject.onChange(target);
|
||||
store.add(testObject.onChange(target));
|
||||
await testObject.batchReplace([folderMatch]);
|
||||
assert.deepStrictEqual([{ elements: expectedArrayResult, removed: true, added: false }], target.args[0]);
|
||||
|
||||
@@ -520,13 +529,17 @@ suite('SearchResult', () => {
|
||||
results: lineMatches
|
||||
};
|
||||
const root = searchResult?.folderMatches()[0];
|
||||
return instantiationService.createInstance(FileMatch, {
|
||||
const fileMatch = instantiationService.createInstance(FileMatch, {
|
||||
pattern: ''
|
||||
}, undefined, undefined, root, rawMatch, null, '');
|
||||
|
||||
store.add(fileMatch);
|
||||
return fileMatch;
|
||||
}
|
||||
|
||||
function aSearchResult(): SearchResult {
|
||||
const searchModel = instantiationService.createInstance(SearchModel);
|
||||
store.add(searchModel);
|
||||
searchModel.searchResult.query = {
|
||||
type: QueryType.Text, folderQueries: [{ folder: createFileUriFromPathFromRoot() }], contentPattern: {
|
||||
pattern: ''
|
||||
@@ -551,14 +564,18 @@ suite('SearchResult', () => {
|
||||
const config = new TestConfigurationService();
|
||||
config.setUserConfiguration('search', { searchOnType: true });
|
||||
instantiationService.stub(IConfigurationService, config);
|
||||
return instantiationService.createInstance(ModelService);
|
||||
const modelService = instantiationService.createInstance(ModelService);
|
||||
store.add(modelService);
|
||||
return modelService;
|
||||
}
|
||||
|
||||
function stubNotebookEditorService(instantiationService: TestInstantiationService): INotebookEditorService {
|
||||
instantiationService.stub(IEditorGroupsService, new TestEditorGroupsService());
|
||||
instantiationService.stub(IContextKeyService, new MockContextKeyService());
|
||||
instantiationService.stub(IEditorService, new TestEditorService());
|
||||
return instantiationService.createInstance(NotebookEditorWidgetService);
|
||||
const notebookEditorWidgetService = instantiationService.createInstance(NotebookEditorWidgetService);
|
||||
store.add(notebookEditorWidgetService);
|
||||
return notebookEditorWidgetService;
|
||||
}
|
||||
|
||||
function getPopulatedSearchResult() {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IModelService } from 'vs/editor/common/services/model';
|
||||
@@ -43,19 +44,23 @@ export function getRootName(): string {
|
||||
}
|
||||
}
|
||||
|
||||
export function stubModelService(instantiationService: TestInstantiationService): IModelService {
|
||||
export function stubModelService(instantiationService: TestInstantiationService, addDisposable: (e: IDisposable) => void): IModelService {
|
||||
instantiationService.stub(IThemeService, new TestThemeService());
|
||||
const config = new TestConfigurationService();
|
||||
config.setUserConfiguration('search', { searchOnType: true });
|
||||
instantiationService.stub(IConfigurationService, config);
|
||||
return instantiationService.createInstance(ModelService);
|
||||
const modelService = instantiationService.createInstance(ModelService);
|
||||
addDisposable(modelService);
|
||||
return modelService;
|
||||
}
|
||||
|
||||
export function stubNotebookEditorService(instantiationService: TestInstantiationService): INotebookEditorService {
|
||||
export function stubNotebookEditorService(instantiationService: TestInstantiationService, addDisposable: (e: IDisposable) => void): INotebookEditorService {
|
||||
instantiationService.stub(IEditorGroupsService, new TestEditorGroupsService());
|
||||
instantiationService.stub(IContextKeyService, new MockContextKeyService());
|
||||
instantiationService.stub(IEditorService, new TestEditorService());
|
||||
return instantiationService.createInstance(NotebookEditorWidgetService);
|
||||
const notebookEditorWidgetService = instantiationService.createInstance(NotebookEditorWidgetService);
|
||||
addDisposable(notebookEditorWidgetService);
|
||||
return notebookEditorWidgetService;
|
||||
}
|
||||
|
||||
export function addToSearchResult(searchResult: SearchResult, allRaw: IFileMatch[], searchInstanceID = '') {
|
||||
|
||||
@@ -6,16 +6,11 @@ import * as assert from 'assert';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
|
||||
import { IModelService } from 'vs/editor/common/services/model';
|
||||
import { ModelService } from 'vs/editor/common/services/modelService';
|
||||
import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { FileService } from 'vs/platform/files/common/fileService';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
|
||||
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
|
||||
import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentityService';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
@@ -25,25 +20,25 @@ import { MockLabelService } from 'vs/workbench/services/label/test/common/mockLa
|
||||
import { IFileMatch, ITextSearchMatch, OneLineRange, QueryType, SearchSortOrder } from 'vs/workbench/services/search/common/search';
|
||||
import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { TestEditorGroupsService, TestEditorService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { NotebookEditorWidgetService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorServiceImpl';
|
||||
import { createFileUriFromPathFromRoot, getRootName } from 'vs/workbench/contrib/search/test/browser/searchTestCommon';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { createFileUriFromPathFromRoot, getRootName, stubModelService, stubNotebookEditorService } from 'vs/workbench/contrib/search/test/browser/searchTestCommon';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
suite('Search - Viewlet', () => {
|
||||
let instantiation: TestInstantiationService;
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
|
||||
setup(() => {
|
||||
instantiation = new TestInstantiationService();
|
||||
instantiation.stub(ILanguageConfigurationService, TestLanguageConfigurationService);
|
||||
instantiation.stub(IModelService, stubModelService(instantiation));
|
||||
instantiation.stub(INotebookEditorService, stubNotebookEditorService(instantiation));
|
||||
instantiation.stub(IModelService, stubModelService(instantiation, (e) => store.add(e)));
|
||||
instantiation.stub(INotebookEditorService, stubNotebookEditorService(instantiation, (e) => store.add(e)));
|
||||
|
||||
instantiation.set(IWorkspaceContextService, new TestContextService(TestWorkspace));
|
||||
instantiation.stub(IUriIdentityService, new UriIdentityService(new FileService(new NullLogService())));
|
||||
const fileService = new FileService(new NullLogService());
|
||||
store.add(fileService);
|
||||
const uriIdentityService = new UriIdentityService(fileService);
|
||||
store.add(uriIdentityService);
|
||||
instantiation.stub(IUriIdentityService, uriIdentityService);
|
||||
instantiation.stub(ILabelService, new MockLabelService());
|
||||
instantiation.stub(ILogService, new NullLogService());
|
||||
});
|
||||
@@ -182,22 +177,29 @@ suite('Search - Viewlet', () => {
|
||||
resource: URI.file('/' + path),
|
||||
results: lineMatches
|
||||
};
|
||||
return instantiation.createInstance(FileMatch, {
|
||||
const fileMatch = instantiation.createInstance(FileMatch, {
|
||||
pattern: ''
|
||||
}, undefined, undefined, parentFolder ?? aFolderMatch('', 0), rawMatch, null, '');
|
||||
store.add(fileMatch);
|
||||
return fileMatch;
|
||||
}
|
||||
|
||||
function aFolderMatch(path: string, index: number, parent?: SearchResult): FolderMatch {
|
||||
const searchModel = instantiation.createInstance(SearchModel);
|
||||
return instantiation.createInstance(FolderMatch, createFileUriFromPathFromRoot(path), path, index, {
|
||||
store.add(searchModel);
|
||||
const folderMatch = instantiation.createInstance(FolderMatch, createFileUriFromPathFromRoot(path), path, index, {
|
||||
type: QueryType.Text, folderQueries: [{ folder: createFileUriFromPathFromRoot() }], contentPattern: {
|
||||
pattern: ''
|
||||
}
|
||||
}, parent ?? aSearchResult().folderMatches()[0], searchModel.searchResult, null);
|
||||
store.add(folderMatch);
|
||||
return folderMatch;
|
||||
}
|
||||
|
||||
function aSearchResult(): SearchResult {
|
||||
const searchModel = instantiation.createInstance(SearchModel);
|
||||
store.add(searchModel);
|
||||
|
||||
searchModel.searchResult.query = {
|
||||
type: QueryType.Text, folderQueries: [{ folder: createFileUriFromPathFromRoot() }], contentPattern: {
|
||||
pattern: ''
|
||||
@@ -205,21 +207,4 @@ suite('Search - Viewlet', () => {
|
||||
};
|
||||
return searchModel.searchResult;
|
||||
}
|
||||
|
||||
function stubModelService(instantiationService: TestInstantiationService): IModelService {
|
||||
instantiationService.stub(IThemeService, new TestThemeService());
|
||||
|
||||
const config = new TestConfigurationService();
|
||||
config.setUserConfiguration('search', { searchOnType: true });
|
||||
instantiationService.stub(IConfigurationService, config);
|
||||
|
||||
return instantiationService.createInstance(ModelService);
|
||||
}
|
||||
|
||||
function stubNotebookEditorService(instantiationService: TestInstantiationService): INotebookEditorService {
|
||||
instantiationService.stub(IEditorGroupsService, new TestEditorGroupsService());
|
||||
instantiationService.stub(IContextKeyService, new MockContextKeyService());
|
||||
instantiationService.stub(IEditorService, new TestEditorService());
|
||||
return instantiationService.createInstance(NotebookEditorWidgetService);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -53,7 +53,6 @@ export class TerminalViewPane extends ViewPane {
|
||||
private _parentDomElement: HTMLElement | undefined;
|
||||
private _terminalTabbedView?: TerminalTabbedView;
|
||||
get terminalTabbedView(): TerminalTabbedView | undefined { return this._terminalTabbedView; }
|
||||
private _isWelcomeShowing: boolean = false;
|
||||
private _isInitialized: boolean = false;
|
||||
private _newDropdown: DropdownWithPrimaryActionViewItem | undefined;
|
||||
private readonly _dropdownMenu: IMenu;
|
||||
@@ -87,13 +86,18 @@ export class TerminalViewPane extends ViewPane {
|
||||
}));
|
||||
|
||||
this._register(this._terminalService.onDidChangeInstances(() => {
|
||||
if (!this._isWelcomeShowing) {
|
||||
return;
|
||||
// If the first terminal is opened, hide the welcome view
|
||||
// and if the last one is closed, show it again
|
||||
if (this._hasWelcomeScreen() && this._terminalService.instances.length <= 1) {
|
||||
this._onDidChangeViewWelcomeState.fire();
|
||||
}
|
||||
this._isWelcomeShowing = true;
|
||||
this._onDidChangeViewWelcomeState.fire();
|
||||
if (!this._terminalTabbedView && this._parentDomElement) {
|
||||
if (!this._parentDomElement) { return; }
|
||||
// If we do not have the tab view yet, create it now.
|
||||
if (!this._terminalTabbedView) {
|
||||
this._createTabsView();
|
||||
}
|
||||
// If we just opened our first terminal, layout
|
||||
if (this._terminalService.instances.length === 1) {
|
||||
this.layoutBody(this._parentDomElement.offsetHeight, this._parentDomElement.offsetWidth);
|
||||
}
|
||||
}));
|
||||
@@ -200,7 +204,7 @@ export class TerminalViewPane extends ViewPane {
|
||||
this._register(this.onDidChangeBodyVisibility(async visible => {
|
||||
this._viewShowing.set(visible);
|
||||
if (visible) {
|
||||
if (!this._terminalService.isProcessSupportRegistered) {
|
||||
if (this._hasWelcomeScreen()) {
|
||||
this._onDidChangeViewWelcomeState.fire();
|
||||
}
|
||||
this._initializeTerminal(false);
|
||||
@@ -319,9 +323,12 @@ export class TerminalViewPane extends ViewPane {
|
||||
}
|
||||
}
|
||||
|
||||
private _hasWelcomeScreen(): boolean {
|
||||
return !this._terminalService.isProcessSupportRegistered;
|
||||
}
|
||||
|
||||
override shouldShowWelcome(): boolean {
|
||||
this._isWelcomeShowing = !this._terminalService.isProcessSupportRegistered && this._terminalService.instances.length === 0;
|
||||
return this._isWelcomeShowing;
|
||||
return this._hasWelcomeScreen() && this._terminalService.instances.length === 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user