mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-04-05 19:40:30 -04:00
Merge from vscode e5834d3280fcd04898efeac32b9cf1b893f9b127 (#9385)
* Merge from vscode e5834d3280fcd04898efeac32b9cf1b893f9b127 * distro
This commit is contained in:
@@ -103,7 +103,8 @@ const indentationFilter = [
|
|||||||
'!extensions/mssql/notebooks/**',
|
'!extensions/mssql/notebooks/**',
|
||||||
'!extensions/integration-tests/testData/**',
|
'!extensions/integration-tests/testData/**',
|
||||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts',
|
'!extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts',
|
||||||
'!extensions/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts'
|
'!extensions/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts',
|
||||||
|
'!resources/linux/snap/electron-launch'
|
||||||
];
|
];
|
||||||
|
|
||||||
const copyrightFilter = [
|
const copyrightFilter = [
|
||||||
|
|||||||
@@ -1825,37 +1825,37 @@
|
|||||||
},
|
},
|
||||||
"viewsWelcome": [
|
"viewsWelcome": [
|
||||||
{
|
{
|
||||||
"view": "workbench.scm",
|
"view": "scm",
|
||||||
"contents": "%view.workbench.scm.disabled%",
|
"contents": "%view.workbench.scm.disabled%",
|
||||||
"when": "!config.git.enabled"
|
"when": "!config.git.enabled"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"view": "workbench.scm",
|
"view": "scm",
|
||||||
"contents": "%view.workbench.scm.missing%",
|
"contents": "%view.workbench.scm.missing%",
|
||||||
"when": "config.git.enabled && git.missing"
|
"when": "config.git.enabled && git.missing"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"view": "workbench.scm",
|
"view": "scm",
|
||||||
"contents": "%view.workbench.scm.empty%",
|
"contents": "%view.workbench.scm.empty%",
|
||||||
"when": "config.git.enabled && !git.missing && workbenchState == empty"
|
"when": "config.git.enabled && !git.missing && workbenchState == empty"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"view": "workbench.scm",
|
"view": "scm",
|
||||||
"contents": "%view.workbench.scm.folder%",
|
"contents": "%view.workbench.scm.folder%",
|
||||||
"when": "config.git.enabled && !git.missing && workbenchState == folder"
|
"when": "config.git.enabled && !git.missing && workbenchState == folder"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"view": "workbench.scm",
|
"view": "scm",
|
||||||
"contents": "%view.workbench.scm.workspace%",
|
"contents": "%view.workbench.scm.workspace%",
|
||||||
"when": "config.git.enabled && !git.missing && workbenchState == workspace && workspaceFolderCount != 0"
|
"when": "config.git.enabled && !git.missing && workbenchState == workspace && workspaceFolderCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"view": "workbench.scm",
|
"view": "scm",
|
||||||
"contents": "%view.workbench.scm.emptyWorkspace%",
|
"contents": "%view.workbench.scm.emptyWorkspace%",
|
||||||
"when": "config.git.enabled && !git.missing && workbenchState == workspace && workspaceFolderCount == 0"
|
"when": "config.git.enabled && !git.missing && workbenchState == workspace && workspaceFolderCount == 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"view": "workbench.explorer.emptyView",
|
"view": "explorer",
|
||||||
"contents": "%view.workbench.cloneRepository%"
|
"contents": "%view.workbench.cloneRepository%"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -150,11 +150,11 @@
|
|||||||
"colors.ignored": "Color for ignored resources.",
|
"colors.ignored": "Color for ignored resources.",
|
||||||
"colors.conflict": "Color for resources with conflicts.",
|
"colors.conflict": "Color for resources with conflicts.",
|
||||||
"colors.submodule": "Color for submodule resources.",
|
"colors.submodule": "Color for submodule resources.",
|
||||||
"view.workbench.scm.missing": "A valid git installation was not detected, more details can be found in the [git output](command:git.showOutput).\nPlease [install git](https://git-scm.com/), or learn more about how to use Git and source control in Azure Data Studio in [our docs](https://aka.ms/vscode-scm).\nIf you're using a different version control system, you can [search the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22) for additional extensions.",
|
"view.workbench.scm.missing": "A valid git installation was not detected, more details can be found in the [git output](command:git.showOutput).\nPlease [install git](https://git-scm.com/), or learn more about how to use git and source control in Azure Data Studio in [our docs](https://aka.ms/vscode-scm).\nIf you're using a different version control system, you can [search the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22) for additional extensions.",
|
||||||
"view.workbench.scm.disabled": "If you would like to use git features, please enable git in your [settings](command:workbench.action.openSettings?%5B%22git.enabled%22%5D).\nTo learn more about how to use Git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
"view.workbench.scm.disabled": "If you would like to use git features, please enable git in your [settings](command:workbench.action.openSettings?%5B%22git.enabled%22%5D).\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||||
"view.workbench.scm.empty": "In order to use git features, you can open a folder containing a git repository or clone from a URL.\n[Open Folder](command:vscode.openFolder)\n[Clone Repository](command:git.clone)\nTo learn more about how to use Git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
"view.workbench.scm.empty": "In order to use git features, you can open a folder containing a git repository or clone from a URL.\n[Open Folder](command:vscode.openFolder)\n[Clone Repository](command:git.clone)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||||
"view.workbench.scm.folder": "The folder currently open doesn't have a git repository.\n[Initialize Repository](command:git.init?%5Btrue%5D)\nTo learn more about how to use Git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
"view.workbench.scm.folder": "The folder currently open doesn't have a git repository.\n[Initialize Repository](command:git.init?%5Btrue%5D)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||||
"view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Initialize Repository](command:git.init)\nTo learn more about how to use Git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
"view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Initialize Repository](command:git.init)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||||
"view.workbench.scm.emptyWorkspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Add Folder to Workspace](command:workbench.action.addRootFolder)\nTo learn more about how to use Git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
"view.workbench.scm.emptyWorkspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Add Folder to Workspace](command:workbench.action.addRootFolder)\nTo learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).",
|
||||||
"view.workbench.cloneRepository": "You can also clone a repository from a URL. To learn more about how to use Git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).\n[Clone Repository](command:git.clone)"
|
"view.workbench.cloneRepository": "You can also clone a repository from a URL. To learn more about how to use git and source control in Azure Data Studio [read our docs](https://aka.ms/vscode-scm).\n[Clone Repository](command:git.clone)"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1397,12 +1397,16 @@ export class CommandCenter {
|
|||||||
opts.signoff = true;
|
opts.signoff = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const smartCommitChanges = config.get<'all' | 'tracked'>('smartCommitChanges');
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
// no changes
|
// no changes
|
||||||
(noStagedChanges && noUnstagedChanges)
|
(noStagedChanges && noUnstagedChanges)
|
||||||
// or no staged changes and not `all`
|
// or no staged changes and not `all`
|
||||||
|| (!opts.all && noStagedChanges)
|
|| (!opts.all && noStagedChanges)
|
||||||
|
// no staged changes and no tracked unstaged changes
|
||||||
|
|| (noStagedChanges && smartCommitChanges === 'tracked' && repository.workingTreeGroup.resourceStates.every(r => r.type === Status.UNTRACKED))
|
||||||
)
|
)
|
||||||
&& !opts.empty
|
&& !opts.empty
|
||||||
) {
|
) {
|
||||||
@@ -1416,7 +1420,7 @@ export class CommandCenter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.all && config.get<'all' | 'tracked'>('smartCommitChanges') === 'tracked') {
|
if (opts.all && smartCommitChanges === 'tracked') {
|
||||||
opts.all = 'tracked';
|
opts.all = 'tracked';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2353,7 +2357,7 @@ export class CommandCenter {
|
|||||||
else if (item.previousRef === 'HEAD' && item.ref === '~') {
|
else if (item.previousRef === 'HEAD' && item.ref === '~') {
|
||||||
title = localize('git.title.index', '{0} (Index)', basename);
|
title = localize('git.title.index', '{0} (Index)', basename);
|
||||||
} else {
|
} else {
|
||||||
title = localize('git.title.diffRefs', '{0} ({1}) \u27f7 {0} ({2})', basename, item.shortPreviousRef, item.shortRef);
|
title = localize('git.title.diffRefs', '{0} ({1}) ⟷ {0} ({2})', basename, item.shortPreviousRef, item.shortRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
return commands.executeCommand('vscode.diff', toGitUri(uri, item.previousRef), item.ref === '' ? uri : toGitUri(uri, item.ref), title);
|
return commands.executeCommand('vscode.diff', toGitUri(uri, item.previousRef), item.ref === '' ? uri : toGitUri(uri, item.ref), title);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
await loginService.initialize();
|
await loginService.initialize();
|
||||||
|
|
||||||
vscode.authentication.registerAuthenticationProvider({
|
vscode.authentication.registerAuthenticationProvider({
|
||||||
id: 'GitHub',
|
id: 'github',
|
||||||
displayName: 'GitHub',
|
displayName: 'GitHub',
|
||||||
onDidChangeSessions: onDidChangeSessions.event,
|
onDidChangeSessions: onDidChangeSessions.event,
|
||||||
getSessions: () => Promise.resolve(loginService.sessions),
|
getSessions: () => Promise.resolve(loginService.sessions),
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export class GitHubAuthenticationProvider {
|
|||||||
id: session.id,
|
id: session.id,
|
||||||
accountName: session.accountName,
|
accountName: session.accountName,
|
||||||
scopes: session.scopes,
|
scopes: session.scopes,
|
||||||
accessToken: () => Promise.resolve(session.accessToken)
|
getAccessToken: () => Promise.resolve(session.accessToken)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -84,7 +84,7 @@ export class GitHubAuthenticationProvider {
|
|||||||
|
|
||||||
private async storeSessions(): Promise<void> {
|
private async storeSessions(): Promise<void> {
|
||||||
const sessionData: SessionData[] = await Promise.all(this._sessions.map(async session => {
|
const sessionData: SessionData[] = await Promise.all(this._sessions.map(async session => {
|
||||||
const resolvedAccessToken = await session.accessToken();
|
const resolvedAccessToken = await session.getAccessToken();
|
||||||
return {
|
return {
|
||||||
id: session.id,
|
id: session.id,
|
||||||
accountName: session.accountName,
|
accountName: session.accountName,
|
||||||
@@ -111,7 +111,7 @@ export class GitHubAuthenticationProvider {
|
|||||||
const userInfo = await this._githubServer.getUserInfo(token);
|
const userInfo = await this._githubServer.getUserInfo(token);
|
||||||
return {
|
return {
|
||||||
id: userInfo.id,
|
id: userInfo.id,
|
||||||
accessToken: () => Promise.resolve(token),
|
getAccessToken: () => Promise.resolve(token),
|
||||||
accountName: userInfo.accountName,
|
accountName: userInfo.accountName,
|
||||||
scopes: scopes
|
scopes: scopes
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"Other"
|
"Other"
|
||||||
],
|
],
|
||||||
"activationEvents": [
|
"activationEvents": [
|
||||||
"onWebviewEditor:imagePreview.previewEditor",
|
"onCustomEditor:imagePreview.previewEditor",
|
||||||
"onCommand:imagePreview.zoomIn",
|
"onCommand:imagePreview.zoomIn",
|
||||||
"onCommand:imagePreview.zoomOut"
|
"onCommand:imagePreview.zoomOut"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
"onCommand:markdown.api.render",
|
"onCommand:markdown.api.render",
|
||||||
"onCommand:notebook.showPreview",
|
"onCommand:notebook.showPreview",
|
||||||
"onWebviewPanel:markdown.preview",
|
"onWebviewPanel:markdown.preview",
|
||||||
"onWebviewEditor:vscode.markdown.preview.editor"
|
"onCustomEditor:vscode.markdown.preview.editor"
|
||||||
],
|
],
|
||||||
"contributes": {
|
"contributes": {
|
||||||
"commands": [
|
"commands": [
|
||||||
|
|||||||
@@ -39,5 +39,8 @@
|
|||||||
"tslint": "^5.12.1",
|
"tslint": "^5.12.1",
|
||||||
"@types/node": "^10.12.21",
|
"@types/node": "^10.12.21",
|
||||||
"@types/keytar": "^4.0.1"
|
"@types/keytar": "^4.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vscode-nls": "^4.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"displayName": "Microsoft Account",
|
"displayName": "Microsoft Account",
|
||||||
"description": "Microsoft authentication provider",
|
"description": "Microsoft authentication provider",
|
||||||
"signIn": "Sign in",
|
"signIn": "Sign In",
|
||||||
"signOut": "Sign out"
|
"signOut": "Sign Out"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ export class AzureActiveDirectoryService {
|
|||||||
private convertToSession(token: IToken): vscode.AuthenticationSession {
|
private convertToSession(token: IToken): vscode.AuthenticationSession {
|
||||||
return {
|
return {
|
||||||
id: token.sessionId,
|
id: token.sessionId,
|
||||||
accessToken: () => this.resolveAccessToken(token),
|
getAccessToken: () => this.resolveAccessToken(token),
|
||||||
accountName: token.accountName,
|
accountName: token.accountName,
|
||||||
scopes: token.scope.split(' ')
|
scopes: token.scope.split(' ')
|
||||||
};
|
};
|
||||||
@@ -192,7 +192,9 @@ export class AzureActiveDirectoryService {
|
|||||||
|
|
||||||
private async resolveAccessToken(token: IToken): Promise<string> {
|
private async resolveAccessToken(token: IToken): Promise<string> {
|
||||||
if (token.accessToken && (!token.expiresAt || token.expiresAt > Date.now())) {
|
if (token.accessToken && (!token.expiresAt || token.expiresAt > Date.now())) {
|
||||||
Logger.info('Token available from cache');
|
token.expiresAt
|
||||||
|
? Logger.info(`Token available from cache, expires in ${token.expiresAt - Date.now()} milliseconds`)
|
||||||
|
: Logger.info('Token available from cache');
|
||||||
return Promise.resolve(token.accessToken);
|
return Promise.resolve(token.accessToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { AzureActiveDirectoryService, onDidChangeSessions } from './AADHelper';
|
import { AzureActiveDirectoryService, onDidChangeSessions } from './AADHelper';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export const DEFAULT_SCOPES = 'https://management.core.windows.net/.default offline_access';
|
export const DEFAULT_SCOPES = 'https://management.core.windows.net/.default offline_access';
|
||||||
|
|
||||||
@@ -15,7 +18,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
await loginService.initialize();
|
await loginService.initialize();
|
||||||
|
|
||||||
context.subscriptions.push(vscode.authentication.registerAuthenticationProvider({
|
context.subscriptions.push(vscode.authentication.registerAuthenticationProvider({
|
||||||
id: 'MSA',
|
id: 'microsoft',
|
||||||
displayName: 'Microsoft',
|
displayName: 'Microsoft',
|
||||||
onDidChangeSessions: onDidChangeSessions.event,
|
onDidChangeSessions: onDidChangeSessions.event,
|
||||||
getSessions: () => Promise.resolve(loginService.sessions),
|
getSessions: () => Promise.resolve(loginService.sessions),
|
||||||
@@ -45,6 +48,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
if (sessions.length === 1) {
|
if (sessions.length === 1) {
|
||||||
await loginService.logout(loginService.sessions[0].id);
|
await loginService.logout(loginService.sessions[0].id);
|
||||||
onDidChangeSessions.fire();
|
onDidChangeSessions.fire();
|
||||||
|
vscode.window.showInformationMessage(localize('signedOut', "Successfully signed out."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +62,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
if (selectedSession) {
|
if (selectedSession) {
|
||||||
await loginService.logout(selectedSession.id);
|
await loginService.logout(selectedSession.id);
|
||||||
onDidChangeSessions.fire();
|
onDidChangeSessions.fire();
|
||||||
|
vscode.window.showInformationMessage(localize('signedOut', "Successfully signed out."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -635,6 +635,11 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||||
|
|
||||||
|
vscode-nls@^4.1.1:
|
||||||
|
version "4.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c"
|
||||||
|
integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A==
|
||||||
|
|
||||||
which-pm-runs@^1.0.0:
|
which-pm-runs@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
|
resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "azuredatastudio",
|
"name": "azuredatastudio",
|
||||||
"version": "1.16.0",
|
"version": "1.16.0",
|
||||||
"distro": "4672f37b373e16688fc9cda03d25a138669718e9",
|
"distro": "4e85ca0eb0c1b17aceab11996f7c2cf460868e8a",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Microsoft Corporation"
|
"name": "Microsoft Corporation"
|
||||||
},
|
},
|
||||||
@@ -184,7 +184,7 @@
|
|||||||
"vinyl": "^2.0.0",
|
"vinyl": "^2.0.0",
|
||||||
"vinyl-fs": "^3.0.0",
|
"vinyl-fs": "^3.0.0",
|
||||||
"vsce": "1.48.0",
|
"vsce": "1.48.0",
|
||||||
"vscode-debugprotocol": "1.39.0-pre.0",
|
"vscode-debugprotocol": "1.39.0",
|
||||||
"vscode-nls-dev": "^3.3.1",
|
"vscode-nls-dev": "^3.3.1",
|
||||||
"webpack": "^4.16.5",
|
"webpack": "^4.16.5",
|
||||||
"webpack-cli": "^3.3.8",
|
"webpack-cli": "^3.3.8",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# On Fedora $SNAP is under /var and there is some magic to map it to /snap.
|
# On Fedora $SNAP is under /var and there is some magic to map it to /snap.
|
||||||
# We need to handle that case and reset $SNAP
|
# We need to handle that case and reset $SNAP
|
||||||
SNAP=$(echo $SNAP | sed -e "s|/var/lib/snapd||g")
|
SNAP=$(echo "$SNAP" | sed -e "s|/var/lib/snapd||g")
|
||||||
|
|
||||||
if [ "$SNAP_ARCH" == "amd64" ]; then
|
if [ "$SNAP_ARCH" == "amd64" ]; then
|
||||||
ARCH="x86_64-linux-gnu"
|
ARCH="x86_64-linux-gnu"
|
||||||
@@ -14,21 +14,21 @@ else
|
|||||||
ARCH="$SNAP_ARCH-linux-gnu"
|
ARCH="$SNAP_ARCH-linux-gnu"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export XDG_CACHE_HOME=$SNAP_USER_COMMON/.cache
|
GDK_CACHE_DIR="$SNAP_USER_COMMON/.cache"
|
||||||
if [[ -d $SNAP_USER_DATA/.cache && ! -e $XDG_CACHE_HOME ]]; then
|
if [[ -d "$SNAP_USER_DATA/.cache" && ! -e "$GDK_CACHE_DIR" ]]; then
|
||||||
# the .cache directory used to be stored under $SNAP_USER_DATA, migrate it
|
# the .cache directory used to be stored under $SNAP_USER_DATA, migrate it
|
||||||
mv $SNAP_USER_DATA/.cache $SNAP_USER_COMMON/
|
mv "$SNAP_USER_DATA/.cache" "$SNAP_USER_COMMON/"
|
||||||
fi
|
fi
|
||||||
mkdir -p $XDG_CACHE_HOME
|
[ ! -d "$GDK_CACHE_DIR" ] && mkdir -p "$GDK_CACHE_DIR"
|
||||||
|
|
||||||
# Gdk-pixbuf loaders
|
# Gdk-pixbuf loaders
|
||||||
export GDK_PIXBUF_MODULE_FILE=$XDG_CACHE_HOME/gdk-pixbuf-loaders.cache
|
export GDK_PIXBUF_MODULE_FILE="$GDK_CACHE_DIR/gdk-pixbuf-loaders.cache"
|
||||||
export GDK_PIXBUF_MODULEDIR=$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/2.10.0/loaders
|
export GDK_PIXBUF_MODULEDIR="$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/2.10.0/loaders"
|
||||||
if [ -f $SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders ]; then
|
if [ -f "$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" ]; then
|
||||||
$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders > $GDK_PIXBUF_MODULE_FILE
|
"$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" > "$GDK_PIXBUF_MODULE_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create $XDG_RUNTIME_DIR if not exists (to be removed when https://pad.lv/1656340 is fixed)
|
# Create $XDG_RUNTIME_DIR if not exists (to be removed when https://pad.lv/1656340 is fixed)
|
||||||
[ -n "$XDG_RUNTIME_DIR" ] && mkdir -p $XDG_RUNTIME_DIR -m 700
|
[ -n "$XDG_RUNTIME_DIR" ] && mkdir -p "$XDG_RUNTIME_DIR" -m 700
|
||||||
|
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "codicon";
|
font-family: "codicon";
|
||||||
src: url("./codicon.ttf?279add2ec8b3d516ca20a123230cbf9f") format("truetype");
|
src: url("./codicon.ttf?b5dd8f5aa953889dc1f4c9fa9b44d3dd") format("truetype");
|
||||||
}
|
}
|
||||||
|
|
||||||
.codicon[class*='codicon-'] {
|
.codicon[class*='codicon-'] {
|
||||||
@@ -415,5 +415,6 @@
|
|||||||
.codicon-group-by-ref-type:before { content: "\eb97" }
|
.codicon-group-by-ref-type:before { content: "\eb97" }
|
||||||
.codicon-ungroup-by-ref-type:before { content: "\eb98" }
|
.codicon-ungroup-by-ref-type:before { content: "\eb98" }
|
||||||
.codicon-bell-dot:before { content: "\f101" }
|
.codicon-bell-dot:before { content: "\f101" }
|
||||||
.codicon-debug-alt-2:before { content: "\f102" }
|
.codicon-bell-progress:before { content: "\f102" }
|
||||||
.codicon-debug-alt:before { content: "\f103" }
|
.codicon-debug-alt-2:before { content: "\f103" }
|
||||||
|
.codicon-debug-alt:before { content: "\f104" }
|
||||||
|
|||||||
Binary file not shown.
@@ -554,7 +554,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
|||||||
|
|
||||||
if (!item.row) {
|
if (!item.row) {
|
||||||
item.row = this.cache.alloc(item.templateId);
|
item.row = this.cache.alloc(item.templateId);
|
||||||
const role = this.ariaProvider.getRole ? this.ariaProvider.getRole(item.element) : 'treeitem';
|
const role = this.ariaProvider.getRole ? this.ariaProvider.getRole(item.element) : 'listitem';
|
||||||
item.row!.domNode!.setAttribute('role', role);
|
item.row!.domNode!.setAttribute('role', role);
|
||||||
const checked = this.ariaProvider.isChecked ? this.ariaProvider.isChecked(item.element) : undefined;
|
const checked = this.ariaProvider.isChecked ? this.ariaProvider.isChecked(item.element) : undefined;
|
||||||
if (typeof checked !== 'undefined') {
|
if (typeof checked !== 'undefined') {
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ function asListOptions<T, TFilterData, TRef>(modelProvider: () => ITreeModel<T,
|
|||||||
} : undefined,
|
} : undefined,
|
||||||
getRole: options.ariaProvider && options.ariaProvider.getRole ? (node) => {
|
getRole: options.ariaProvider && options.ariaProvider.getRole ? (node) => {
|
||||||
return options.ariaProvider!.getRole!(node.element);
|
return options.ariaProvider!.getRole!(node.element);
|
||||||
} : undefined
|
} : () => 'treeitem'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
|
|||||||
},
|
},
|
||||||
getRole: options.ariaProvider!.getRole ? (el) => {
|
getRole: options.ariaProvider!.getRole ? (el) => {
|
||||||
return options.ariaProvider!.getRole!(el.element as T);
|
return options.ariaProvider!.getRole!(el.element as T);
|
||||||
} : undefined,
|
} : () => 'treeitem',
|
||||||
isChecked: options.ariaProvider!.isChecked ? (e) => {
|
isChecked: options.ariaProvider!.isChecked ? (e) => {
|
||||||
return options.ariaProvider?.isChecked!(e.element as T);
|
return options.ariaProvider?.isChecked!(e.element as T);
|
||||||
} : undefined
|
} : undefined
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export class LinkedText {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const LINK_REGEX = /\[([^\]]+)\]\(((?:https?:\/\/|command:)[^\)\s]+)(?: "([^"]+)")?\)/gi;
|
const LINK_REGEX = /\[([^\]]+)\]\(((?:https?:\/\/|command:)[^\)\s]+)(?: ("|')([^\3]+)(\3))?\)/gi;
|
||||||
|
|
||||||
export function parseLinkedText(text: string): LinkedText {
|
export function parseLinkedText(text: string): LinkedText {
|
||||||
const result: LinkedTextNode[] = [];
|
const result: LinkedTextNode[] = [];
|
||||||
@@ -36,7 +36,7 @@ export function parseLinkedText(text: string): LinkedText {
|
|||||||
result.push(text.substring(index, match.index));
|
result.push(text.substring(index, match.index));
|
||||||
}
|
}
|
||||||
|
|
||||||
const [, label, href, title] = match;
|
const [, label, href, , title] = match;
|
||||||
|
|
||||||
if (title) {
|
if (title) {
|
||||||
result.push({ label, href, title });
|
result.push({ label, href, title });
|
||||||
|
|||||||
@@ -21,4 +21,5 @@ export class CompositeDragAndDropData implements IDragAndDropData {
|
|||||||
export interface ICompositeDragAndDrop {
|
export interface ICompositeDragAndDrop {
|
||||||
drop(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): void;
|
drop(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): void;
|
||||||
onDragOver(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): boolean;
|
onDragOver(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): boolean;
|
||||||
|
onDragEnter(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
|||||||
private _valueSelection: Readonly<[number, number]> | undefined;
|
private _valueSelection: Readonly<[number, number]> | undefined;
|
||||||
private valueSelectionUpdated = true;
|
private valueSelectionUpdated = true;
|
||||||
private _validationMessage: string | undefined;
|
private _validationMessage: string | undefined;
|
||||||
private _ok = false;
|
private _ok: boolean | 'default' = 'default';
|
||||||
private _customButton = false;
|
private _customButton = false;
|
||||||
private _customButtonLabel: string | undefined;
|
private _customButtonLabel: string | undefined;
|
||||||
private _customButtonHover: string | undefined;
|
private _customButtonHover: string | undefined;
|
||||||
@@ -566,7 +566,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
|||||||
return this._ok;
|
return this._ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
set ok(showOkButton: boolean) {
|
set ok(showOkButton: boolean | 'default') {
|
||||||
this._ok = showOkButton;
|
this._ok = showOkButton;
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
@@ -575,6 +575,10 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
|||||||
return this.visible ? this.ui.inputBox.hasFocus() : false;
|
return this.visible ? this.ui.inputBox.hasFocus() : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public focusOnInput() {
|
||||||
|
this.ui.inputBox.setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
onDidChangeSelection = this.onDidChangeSelectionEmitter.event;
|
onDidChangeSelection = this.onDidChangeSelectionEmitter.event;
|
||||||
|
|
||||||
onDidTriggerItemButton = this.onDidTriggerItemButtonEmitter.event;
|
onDidTriggerItemButton = this.onDidTriggerItemButtonEmitter.event;
|
||||||
@@ -753,7 +757,8 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
|||||||
if (!this.visible) {
|
if (!this.visible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.ui.setVisibilities(this.canSelectMany ? { title: !!this.title || !!this.step, description: !!this.description, checkAll: true, inputBox: true, visibleCount: true, count: true, ok: this.ok, list: true, message: !!this.validationMessage, customButton: this.customButton } : { title: !!this.title || !!this.step, description: !!this.description, inputBox: true, visibleCount: true, list: true, message: !!this.validationMessage, customButton: this.customButton, ok: this.ok });
|
const ok = this.ok === 'default' ? this.canSelectMany : this.ok;
|
||||||
|
this.ui.setVisibilities(this.canSelectMany ? { title: !!this.title || !!this.step, description: !!this.description, checkAll: true, inputBox: true, visibleCount: true, count: true, ok, list: true, message: !!this.validationMessage, customButton: this.customButton } : { title: !!this.title || !!this.step, description: !!this.description, inputBox: true, visibleCount: true, list: true, message: !!this.validationMessage, customButton: this.customButton, ok });
|
||||||
super.update();
|
super.update();
|
||||||
if (this.ui.inputBox.value !== this.value) {
|
if (this.ui.inputBox.value !== this.value) {
|
||||||
this.ui.inputBox.value = this.value;
|
this.ui.inputBox.value = this.value;
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export interface IInputOptions {
|
|||||||
placeHolder?: string;
|
placeHolder?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set to true to show a password prompt that will not show the typed value
|
* Controls if a password input is shown. Password input hides the typed text.
|
||||||
*/
|
*/
|
||||||
password?: boolean;
|
password?: boolean;
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ export interface IQuickPick<T extends IQuickPickItem> extends IQuickInput {
|
|||||||
|
|
||||||
readonly onDidAccept: Event<void>;
|
readonly onDidAccept: Event<void>;
|
||||||
|
|
||||||
ok: boolean;
|
ok: boolean | 'default';
|
||||||
|
|
||||||
readonly onDidCustom: Event<void>;
|
readonly onDidCustom: Event<void>;
|
||||||
|
|
||||||
@@ -209,6 +209,8 @@ export interface IQuickPick<T extends IQuickPickItem> extends IQuickInput {
|
|||||||
validationMessage: string | undefined;
|
validationMessage: string | undefined;
|
||||||
|
|
||||||
inputHasFocus(): boolean;
|
inputHasFocus(): boolean;
|
||||||
|
|
||||||
|
focusOnInput(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IInputBox extends IQuickInput {
|
export interface IInputBox extends IQuickInput {
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ export interface IUpdateRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IStorageItemsChangeEvent {
|
export interface IStorageItemsChangeEvent {
|
||||||
items: Map<string, string>;
|
changed?: Map<string, string>;
|
||||||
|
deleted?: Set<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IStorageDatabase {
|
export interface IStorageDatabase {
|
||||||
@@ -104,10 +105,11 @@ export class Storage extends Disposable implements IStorage {
|
|||||||
// items that change external require us to update our
|
// items that change external require us to update our
|
||||||
// caches with the values. we just accept the value and
|
// caches with the values. we just accept the value and
|
||||||
// emit an event if there is a change.
|
// emit an event if there is a change.
|
||||||
e.items.forEach((value, key) => this.accept(key, value));
|
e.changed?.forEach((value, key) => this.accept(key, value));
|
||||||
|
e.deleted?.forEach(key => this.accept(key, undefined));
|
||||||
}
|
}
|
||||||
|
|
||||||
private accept(key: string, value: string): void {
|
private accept(key: string, value: string | undefined): void {
|
||||||
if (this.state === StorageState.Closed) {
|
if (this.state === StorageState.Closed) {
|
||||||
return; // Return early if we are already closed
|
return; // Return early if we are already closed
|
||||||
}
|
}
|
||||||
@@ -315,4 +317,4 @@ export class InMemoryStorageDatabase implements IStorageDatabase {
|
|||||||
close(): Promise<void> {
|
close(): Promise<void> {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,28 +124,27 @@ suite('Storage Library', () => {
|
|||||||
changes.clear();
|
changes.clear();
|
||||||
|
|
||||||
// Nothing happens if changing to same value
|
// Nothing happens if changing to same value
|
||||||
const change = new Map<string, string>();
|
const changed = new Map<string, string>();
|
||||||
change.set('foo', 'bar');
|
changed.set('foo', 'bar');
|
||||||
database.fireDidChangeItemsExternal({ items: change });
|
database.fireDidChangeItemsExternal({ changed });
|
||||||
equal(changes.size, 0);
|
equal(changes.size, 0);
|
||||||
|
|
||||||
// Change is accepted if valid
|
// Change is accepted if valid
|
||||||
change.set('foo', 'bar1');
|
changed.set('foo', 'bar1');
|
||||||
database.fireDidChangeItemsExternal({ items: change });
|
database.fireDidChangeItemsExternal({ changed });
|
||||||
ok(changes.has('foo'));
|
ok(changes.has('foo'));
|
||||||
equal(storage.get('foo'), 'bar1');
|
equal(storage.get('foo'), 'bar1');
|
||||||
changes.clear();
|
changes.clear();
|
||||||
|
|
||||||
// Delete is accepted
|
// Delete is accepted
|
||||||
change.set('foo', undefined!);
|
const deleted = new Set<string>(['foo']);
|
||||||
database.fireDidChangeItemsExternal({ items: change });
|
database.fireDidChangeItemsExternal({ deleted });
|
||||||
ok(changes.has('foo'));
|
ok(changes.has('foo'));
|
||||||
equal(storage.get('foo', null!), null);
|
equal(storage.get('foo', undefined), undefined);
|
||||||
changes.clear();
|
changes.clear();
|
||||||
|
|
||||||
// Nothing happens if changing to same value
|
// Nothing happens if changing to same value
|
||||||
change.set('foo', undefined!);
|
database.fireDidChangeItemsExternal({ deleted });
|
||||||
database.fireDidChangeItemsExternal({ items: change });
|
|
||||||
equal(changes.size, 0);
|
equal(changes.size, 0);
|
||||||
|
|
||||||
await storage.close();
|
await storage.close();
|
||||||
|
|||||||
@@ -21,6 +21,21 @@ suite('LinkedText', () => {
|
|||||||
{ label: 'link text', href: 'http://link.href', title: 'and a title' },
|
{ label: 'link text', href: 'http://link.href', title: 'and a title' },
|
||||||
'.'
|
'.'
|
||||||
]);
|
]);
|
||||||
|
assert.deepEqual(parseLinkedText('Some message with [link text](http://link.href \'and a title\').').nodes, [
|
||||||
|
'Some message with ',
|
||||||
|
{ label: 'link text', href: 'http://link.href', title: 'and a title' },
|
||||||
|
'.'
|
||||||
|
]);
|
||||||
|
assert.deepEqual(parseLinkedText('Some message with [link text](http://link.href "and a \'title\'").').nodes, [
|
||||||
|
'Some message with ',
|
||||||
|
{ label: 'link text', href: 'http://link.href', title: 'and a \'title\'' },
|
||||||
|
'.'
|
||||||
|
]);
|
||||||
|
assert.deepEqual(parseLinkedText('Some message with [link text](http://link.href \'and a "title"\').').nodes, [
|
||||||
|
'Some message with ',
|
||||||
|
{ label: 'link text', href: 'http://link.href', title: 'and a "title"' },
|
||||||
|
'.'
|
||||||
|
]);
|
||||||
assert.deepEqual(parseLinkedText('Some message with [link text](random stuff).').nodes, [
|
assert.deepEqual(parseLinkedText('Some message with [link text](random stuff).').nodes, [
|
||||||
'Some message with [link text](random stuff).'
|
'Some message with [link text](random stuff).'
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -75,7 +75,11 @@ function getProcessItem(processes: FormattedProcessItem[], item: ProcessItem, in
|
|||||||
|
|
||||||
// Recurse into children if any
|
// Recurse into children if any
|
||||||
if (Array.isArray(item.children)) {
|
if (Array.isArray(item.children)) {
|
||||||
item.children.forEach(child => getProcessItem(processes, child, indent + 1, isLocal));
|
item.children.forEach(child => {
|
||||||
|
if (child) {
|
||||||
|
getProcessItem(processes, child, indent + 1, isLocal);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
|||||||
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
|
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
|
||||||
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
||||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||||
|
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
||||||
|
|
||||||
const RUN_TEXTMATE_IN_WORKER = false;
|
const RUN_TEXTMATE_IN_WORKER = false;
|
||||||
|
|
||||||
@@ -100,7 +101,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
|||||||
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
|
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
|
||||||
@IBackupMainService private readonly backupMainService: IBackupMainService,
|
@IBackupMainService private readonly backupMainService: IBackupMainService,
|
||||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||||
@IDialogMainService private readonly dialogMainService: IDialogMainService
|
@IDialogMainService private readonly dialogMainService: IDialogMainService,
|
||||||
|
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -244,6 +246,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
|||||||
|
|
||||||
get isExtensionTestHost(): boolean { return !!(this.config && this.config.extensionTestsPath); }
|
get isExtensionTestHost(): boolean { return !!(this.config && this.config.extensionTestsPath); }
|
||||||
|
|
||||||
|
get isExtensionDevelopmentTestFromCli(): boolean { return this.isExtensionDevelopmentHost && this.isExtensionTestHost && !this.config?.debugId; }
|
||||||
|
|
||||||
setRepresentedFilename(filename: string): void {
|
setRepresentedFilename(filename: string): void {
|
||||||
if (isMacintosh) {
|
if (isMacintosh) {
|
||||||
this.win.setRepresentedFilename(filename);
|
this.win.setRepresentedFilename(filename);
|
||||||
@@ -447,6 +451,15 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
|||||||
private onWindowError(error: WindowError): void {
|
private onWindowError(error: WindowError): void {
|
||||||
this.logService.error(error === WindowError.CRASHED ? '[VS Code]: render process crashed!' : '[VS Code]: detected unresponsive');
|
this.logService.error(error === WindowError.CRASHED ? '[VS Code]: render process crashed!' : '[VS Code]: detected unresponsive');
|
||||||
|
|
||||||
|
// If we run extension tests from CLI, showing a dialog is not
|
||||||
|
// very helpful in this case. Rather, we bring down the test run
|
||||||
|
// to signal back a failing run.
|
||||||
|
if (this.isExtensionDevelopmentTestFromCli) {
|
||||||
|
this.lifecycleMainService.kill(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Telemetry
|
||||||
type WindowErrorClassification = {
|
type WindowErrorClassification = {
|
||||||
type: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
type: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export interface IBulkEditOptions {
|
|||||||
progress?: IProgress<IProgressStep>;
|
progress?: IProgress<IProgressStep>;
|
||||||
showPreview?: boolean;
|
showPreview?: boolean;
|
||||||
label?: string;
|
label?: string;
|
||||||
|
quotableLabel?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IBulkEditResult {
|
export interface IBulkEditResult {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class MinimapOptions {
|
|||||||
|
|
||||||
public readonly renderMinimap: RenderMinimap;
|
public readonly renderMinimap: RenderMinimap;
|
||||||
|
|
||||||
public readonly mode: 'actual' | 'cover' | 'contain';
|
public readonly size: 'proportional' | 'fill' | 'fit';
|
||||||
|
|
||||||
public readonly minimapHeightIsEditorHeight: boolean;
|
public readonly minimapHeightIsEditorHeight: boolean;
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ class MinimapOptions {
|
|||||||
const minimapOpts = options.get(EditorOption.minimap);
|
const minimapOpts = options.get(EditorOption.minimap);
|
||||||
|
|
||||||
this.renderMinimap = layoutInfo.renderMinimap | 0;
|
this.renderMinimap = layoutInfo.renderMinimap | 0;
|
||||||
this.mode = minimapOpts.mode;
|
this.size = minimapOpts.size;
|
||||||
this.minimapHeightIsEditorHeight = layoutInfo.minimapHeightIsEditorHeight;
|
this.minimapHeightIsEditorHeight = layoutInfo.minimapHeightIsEditorHeight;
|
||||||
this.scrollBeyondLastLine = options.get(EditorOption.scrollBeyondLastLine);
|
this.scrollBeyondLastLine = options.get(EditorOption.scrollBeyondLastLine);
|
||||||
this.showSlider = minimapOpts.showSlider;
|
this.showSlider = minimapOpts.showSlider;
|
||||||
@@ -144,7 +144,7 @@ class MinimapOptions {
|
|||||||
|
|
||||||
public equals(other: MinimapOptions): boolean {
|
public equals(other: MinimapOptions): boolean {
|
||||||
return (this.renderMinimap === other.renderMinimap
|
return (this.renderMinimap === other.renderMinimap
|
||||||
&& this.mode === other.mode
|
&& this.size === other.size
|
||||||
&& this.minimapHeightIsEditorHeight === other.minimapHeightIsEditorHeight
|
&& this.minimapHeightIsEditorHeight === other.minimapHeightIsEditorHeight
|
||||||
&& this.scrollBeyondLastLine === other.scrollBeyondLastLine
|
&& this.scrollBeyondLastLine === other.scrollBeyondLastLine
|
||||||
&& this.showSlider === other.showSlider
|
&& this.showSlider === other.showSlider
|
||||||
@@ -1111,7 +1111,7 @@ class InnerMinimap extends Disposable {
|
|||||||
if (!this._lastRenderData) {
|
if (!this._lastRenderData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this._model.options.minimapHeightIsEditorHeight) {
|
if (this._model.options.size !== 'proportional') {
|
||||||
if (e.leftButton && this._lastRenderData) {
|
if (e.leftButton && this._lastRenderData) {
|
||||||
// pretend the click occured in the center of the slider
|
// pretend the click occured in the center of the slider
|
||||||
const position = dom.getDomNodePagePosition(this._slider.domNode);
|
const position = dom.getDomNodePagePosition(this._slider.domNode);
|
||||||
|
|||||||
@@ -617,10 +617,11 @@ export class DiffReview extends Disposable {
|
|||||||
header.setAttribute('role', 'listitem');
|
header.setAttribute('role', 'listitem');
|
||||||
container.appendChild(header);
|
container.appendChild(header);
|
||||||
|
|
||||||
|
const lineHeight = modifiedOptions.get(EditorOption.lineHeight);
|
||||||
let modLine = minModifiedLine;
|
let modLine = minModifiedLine;
|
||||||
for (let i = 0, len = diffs.length; i < len; i++) {
|
for (let i = 0, len = diffs.length; i < len; i++) {
|
||||||
const diffEntry = diffs[i];
|
const diffEntry = diffs[i];
|
||||||
DiffReview._renderSection(container, diffEntry, modLine, this._width, originalOptions, originalModel, originalModelOpts, modifiedOptions, modifiedModel, modifiedModelOpts);
|
DiffReview._renderSection(container, diffEntry, modLine, lineHeight, this._width, originalOptions, originalModel, originalModelOpts, modifiedOptions, modifiedModel, modifiedModelOpts);
|
||||||
if (diffEntry.modifiedLineStart !== 0) {
|
if (diffEntry.modifiedLineStart !== 0) {
|
||||||
modLine = diffEntry.modifiedLineEnd;
|
modLine = diffEntry.modifiedLineEnd;
|
||||||
}
|
}
|
||||||
@@ -632,7 +633,7 @@ export class DiffReview extends Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static _renderSection(
|
private static _renderSection(
|
||||||
dest: HTMLElement, diffEntry: DiffEntry, modLine: number, width: number,
|
dest: HTMLElement, diffEntry: DiffEntry, modLine: number, lineHeight: number, width: number,
|
||||||
originalOptions: IComputedEditorOptions, originalModel: ITextModel, originalModelOpts: TextModelResolvedOptions,
|
originalOptions: IComputedEditorOptions, originalModel: ITextModel, originalModelOpts: TextModelResolvedOptions,
|
||||||
modifiedOptions: IComputedEditorOptions, modifiedModel: ITextModel, modifiedModelOpts: TextModelResolvedOptions
|
modifiedOptions: IComputedEditorOptions, modifiedModel: ITextModel, modifiedModelOpts: TextModelResolvedOptions
|
||||||
): void {
|
): void {
|
||||||
@@ -641,17 +642,18 @@ export class DiffReview extends Disposable {
|
|||||||
|
|
||||||
let rowClassName: string = 'diff-review-row';
|
let rowClassName: string = 'diff-review-row';
|
||||||
let lineNumbersExtraClassName: string = '';
|
let lineNumbersExtraClassName: string = '';
|
||||||
let spacerClassName: string = 'diff-review-spacer';
|
const spacerClassName: string = 'diff-review-spacer';
|
||||||
|
let spacerCodiconName: string | null = null;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DiffEntryType.Insert:
|
case DiffEntryType.Insert:
|
||||||
rowClassName = 'diff-review-row line-insert';
|
rowClassName = 'diff-review-row line-insert';
|
||||||
lineNumbersExtraClassName = ' char-insert';
|
lineNumbersExtraClassName = ' char-insert';
|
||||||
spacerClassName = 'diff-review-spacer insert-sign';
|
spacerCodiconName = 'codicon codicon-add';
|
||||||
break;
|
break;
|
||||||
case DiffEntryType.Delete:
|
case DiffEntryType.Delete:
|
||||||
rowClassName = 'diff-review-row line-delete';
|
rowClassName = 'diff-review-row line-delete';
|
||||||
lineNumbersExtraClassName = ' char-delete';
|
lineNumbersExtraClassName = ' char-delete';
|
||||||
spacerClassName = 'diff-review-spacer delete-sign';
|
spacerCodiconName = 'codicon codicon-remove';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,6 +688,7 @@ export class DiffReview extends Disposable {
|
|||||||
|
|
||||||
let cell = document.createElement('div');
|
let cell = document.createElement('div');
|
||||||
cell.className = 'diff-review-cell';
|
cell.className = 'diff-review-cell';
|
||||||
|
cell.style.height = `${lineHeight}px`;
|
||||||
row.appendChild(cell);
|
row.appendChild(cell);
|
||||||
|
|
||||||
const originalLineNumber = document.createElement('span');
|
const originalLineNumber = document.createElement('span');
|
||||||
@@ -713,7 +716,15 @@ export class DiffReview extends Disposable {
|
|||||||
|
|
||||||
const spacer = document.createElement('span');
|
const spacer = document.createElement('span');
|
||||||
spacer.className = spacerClassName;
|
spacer.className = spacerClassName;
|
||||||
spacer.innerHTML = '  ';
|
|
||||||
|
if (spacerCodiconName) {
|
||||||
|
const spacerCodicon = document.createElement('span');
|
||||||
|
spacerCodicon.className = spacerCodiconName;
|
||||||
|
spacerCodicon.innerHTML = '  ';
|
||||||
|
spacer.appendChild(spacerCodicon);
|
||||||
|
} else {
|
||||||
|
spacer.innerHTML = '  ';
|
||||||
|
}
|
||||||
cell.appendChild(spacer);
|
cell.appendChild(spacer);
|
||||||
|
|
||||||
let lineContent: string;
|
let lineContent: string;
|
||||||
|
|||||||
@@ -37,13 +37,14 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.monaco-diff-editor .diff-review-cell {
|
|
||||||
display: table-cell;
|
|
||||||
}
|
|
||||||
|
|
||||||
.monaco-diff-editor .diff-review-spacer {
|
.monaco-diff-editor .diff-review-spacer {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 10px;
|
width: 10px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.monaco-diff-editor .diff-review-spacer > .codicon {
|
||||||
|
font-size: 9px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.monaco-diff-editor .diff-review-actions {
|
.monaco-diff-editor .diff-review-actions {
|
||||||
|
|||||||
@@ -510,7 +510,7 @@ export interface IEditorOptions {
|
|||||||
* Controls whether clicking on the empty content after a folded line will unfold the line.
|
* Controls whether clicking on the empty content after a folded line will unfold the line.
|
||||||
* Defaults to false.
|
* Defaults to false.
|
||||||
*/
|
*/
|
||||||
unfoldOnClickInEmptyContent?: boolean;
|
unfoldOnClickAfterEndOfLine?: boolean;
|
||||||
/**
|
/**
|
||||||
* Enable highlighting of matching brackets.
|
* Enable highlighting of matching brackets.
|
||||||
* Defaults to 'always'.
|
* Defaults to 'always'.
|
||||||
@@ -1808,7 +1808,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
|||||||
const minimapRenderCharacters = minimap.renderCharacters;
|
const minimapRenderCharacters = minimap.renderCharacters;
|
||||||
let minimapScale = (pixelRatio >= 2 ? Math.round(minimap.scale * 2) : minimap.scale);
|
let minimapScale = (pixelRatio >= 2 ? Math.round(minimap.scale * 2) : minimap.scale);
|
||||||
const minimapMaxColumn = minimap.maxColumn | 0;
|
const minimapMaxColumn = minimap.maxColumn | 0;
|
||||||
const minimapMode = minimap.mode;
|
const minimapSize = minimap.size;
|
||||||
|
|
||||||
const scrollbar = options.get(EditorOption.scrollbar);
|
const scrollbar = options.get(EditorOption.scrollbar);
|
||||||
const verticalScrollbarWidth = scrollbar.verticalScrollbarSize | 0;
|
const verticalScrollbarWidth = scrollbar.verticalScrollbarSize | 0;
|
||||||
@@ -1872,7 +1872,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
|||||||
let minimapCharWidth = minimapScale / pixelRatio;
|
let minimapCharWidth = minimapScale / pixelRatio;
|
||||||
let minimapWidthMultiplier: number = 1;
|
let minimapWidthMultiplier: number = 1;
|
||||||
|
|
||||||
if (minimapMode === 'cover' || minimapMode === 'contain') {
|
if (minimapSize === 'fill' || minimapSize === 'fit') {
|
||||||
const viewLineCount = env.viewLineCount;
|
const viewLineCount = env.viewLineCount;
|
||||||
const { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({
|
const { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({
|
||||||
viewLineCount: viewLineCount,
|
viewLineCount: viewLineCount,
|
||||||
@@ -1893,7 +1893,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
|||||||
minimapCharWidth = minimapScale / pixelRatio;
|
minimapCharWidth = minimapScale / pixelRatio;
|
||||||
} else {
|
} else {
|
||||||
const effectiveMinimapHeight = Math.ceil((viewLineCount + extraLinesBeyondLastLine) * minimapLineHeight);
|
const effectiveMinimapHeight = Math.ceil((viewLineCount + extraLinesBeyondLastLine) * minimapLineHeight);
|
||||||
if (minimapMode === 'cover' || effectiveMinimapHeight > minimapCanvasInnerHeight) {
|
if (minimapSize === 'fill' || effectiveMinimapHeight > minimapCanvasInnerHeight) {
|
||||||
minimapHeightIsEditorHeight = true;
|
minimapHeightIsEditorHeight = true;
|
||||||
const configuredFontScale = minimapScale;
|
const configuredFontScale = minimapScale;
|
||||||
minimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio)));
|
minimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio)));
|
||||||
@@ -2080,7 +2080,7 @@ export interface IEditorMinimapOptions {
|
|||||||
* Control the minimap rendering mode.
|
* Control the minimap rendering mode.
|
||||||
* Defaults to 'actual'.
|
* Defaults to 'actual'.
|
||||||
*/
|
*/
|
||||||
mode?: 'actual' | 'cover' | 'contain';
|
size?: 'proportional' | 'fill' | 'fit';
|
||||||
/**
|
/**
|
||||||
* Control the rendering of the minimap slider.
|
* Control the rendering of the minimap slider.
|
||||||
* Defaults to 'mouseover'.
|
* Defaults to 'mouseover'.
|
||||||
@@ -2109,7 +2109,7 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
|
|||||||
constructor() {
|
constructor() {
|
||||||
const defaults: EditorMinimapOptions = {
|
const defaults: EditorMinimapOptions = {
|
||||||
enabled: false, // {{SQL CARBON EDIT}} disable minimap by default
|
enabled: false, // {{SQL CARBON EDIT}} disable minimap by default
|
||||||
mode: 'actual',
|
size: 'proportional',
|
||||||
side: 'right',
|
side: 'right',
|
||||||
showSlider: 'mouseover',
|
showSlider: 'mouseover',
|
||||||
renderCharacters: true,
|
renderCharacters: true,
|
||||||
@@ -2124,16 +2124,16 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
|
|||||||
default: defaults.enabled,
|
default: defaults.enabled,
|
||||||
description: nls.localize('minimap.enabled', "Controls whether the minimap is shown.")
|
description: nls.localize('minimap.enabled', "Controls whether the minimap is shown.")
|
||||||
},
|
},
|
||||||
'editor.minimap.mode': {
|
'editor.minimap.size': {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
enum: ['actual', 'cover', 'contain'],
|
enum: ['proportional', 'fill', 'fit'],
|
||||||
enumDescriptions: [
|
enumDescriptions: [
|
||||||
nls.localize('minimap.mode.actual', "The minimap will be displayed in its original size, so it might be higher than the editor."),
|
nls.localize('minimap.size.proportional', "The minimap has the same size as the editor contents (and might scroll)."),
|
||||||
nls.localize('minimap.mode.cover', "The minimap will always have the height of the editor and will stretch or shrink as necessary."),
|
nls.localize('minimap.size.fill', "The minimap will stretch or shrink as necessary to fill the height of the editor (no scrolling)."),
|
||||||
nls.localize('minimap.mode.contain', "The minimap will shrink as necessary to never be higher than the editor."),
|
nls.localize('minimap.size.fit', "The minimap will shrink as necessary to never be larger than the editor (no scrolling)."),
|
||||||
],
|
],
|
||||||
default: defaults.mode,
|
default: defaults.size,
|
||||||
description: nls.localize('minimap.mode', "Controls the rendering mode of the minimap.")
|
description: nls.localize('minimap.size', "Controls the size of the minimap.")
|
||||||
},
|
},
|
||||||
'editor.minimap.side': {
|
'editor.minimap.side': {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
@@ -2152,7 +2152,8 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
|
|||||||
default: defaults.scale,
|
default: defaults.scale,
|
||||||
minimum: 1,
|
minimum: 1,
|
||||||
maximum: 3,
|
maximum: 3,
|
||||||
description: nls.localize('minimap.scale', "Scale of content drawn in the minimap.")
|
enum: [1, 2, 3],
|
||||||
|
description: nls.localize('minimap.scale', "Scale of content drawn in the minimap: 1, 2 or 3.")
|
||||||
},
|
},
|
||||||
'editor.minimap.renderCharacters': {
|
'editor.minimap.renderCharacters': {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
@@ -2175,7 +2176,7 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
|
|||||||
const input = _input as IEditorMinimapOptions;
|
const input = _input as IEditorMinimapOptions;
|
||||||
return {
|
return {
|
||||||
enabled: EditorBooleanOption.boolean(input.enabled, this.defaultValue.enabled),
|
enabled: EditorBooleanOption.boolean(input.enabled, this.defaultValue.enabled),
|
||||||
mode: EditorStringEnumOption.stringSet<'actual' | 'cover' | 'contain'>(input.mode, this.defaultValue.mode, ['actual', 'cover', 'contain']),
|
size: EditorStringEnumOption.stringSet<'proportional' | 'fill' | 'fit'>(input.size, this.defaultValue.size, ['proportional', 'fill', 'fit']),
|
||||||
side: EditorStringEnumOption.stringSet<'right' | 'left'>(input.side, this.defaultValue.side, ['right', 'left']),
|
side: EditorStringEnumOption.stringSet<'right' | 'left'>(input.side, this.defaultValue.side, ['right', 'left']),
|
||||||
showSlider: EditorStringEnumOption.stringSet<'always' | 'mouseover'>(input.showSlider, this.defaultValue.showSlider, ['always', 'mouseover']),
|
showSlider: EditorStringEnumOption.stringSet<'always' | 'mouseover'>(input.showSlider, this.defaultValue.showSlider, ['always', 'mouseover']),
|
||||||
renderCharacters: EditorBooleanOption.boolean(input.renderCharacters, this.defaultValue.renderCharacters),
|
renderCharacters: EditorBooleanOption.boolean(input.renderCharacters, this.defaultValue.renderCharacters),
|
||||||
@@ -2840,9 +2841,14 @@ export interface ISuggestOptions {
|
|||||||
*/
|
*/
|
||||||
showSnippets?: boolean;
|
showSnippets?: boolean;
|
||||||
/**
|
/**
|
||||||
* Controls the visibility of the status bar at the bottom of the suggest widget.
|
* Status bar related settings.
|
||||||
*/
|
*/
|
||||||
hideStatusBar?: boolean;
|
statusBar?: {
|
||||||
|
/**
|
||||||
|
* Controls the visibility of the status bar at the bottom of the suggest widget.
|
||||||
|
*/
|
||||||
|
visible?: boolean;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type InternalSuggestOptions = Readonly<Required<ISuggestOptions>>;
|
export type InternalSuggestOptions = Readonly<Required<ISuggestOptions>>;
|
||||||
@@ -2884,7 +2890,9 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
|
|||||||
showFolders: true,
|
showFolders: true,
|
||||||
showTypeParameters: true,
|
showTypeParameters: true,
|
||||||
showSnippets: true,
|
showSnippets: true,
|
||||||
hideStatusBar: true
|
statusBar: {
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
super(
|
super(
|
||||||
EditorOption.suggest, 'suggest', defaults,
|
EditorOption.suggest, 'suggest', defaults,
|
||||||
@@ -3070,10 +3078,10 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
|
|||||||
default: true,
|
default: true,
|
||||||
markdownDescription: nls.localize('editor.suggest.showSnippets', "When enabled IntelliSense shows `snippet`-suggestions.")
|
markdownDescription: nls.localize('editor.suggest.showSnippets', "When enabled IntelliSense shows `snippet`-suggestions.")
|
||||||
},
|
},
|
||||||
'editor.suggest.hideStatusBar': {
|
'editor.suggest.statusBar.visible': {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: true,
|
default: false,
|
||||||
markdownDescription: nls.localize('editor.suggest.hideStatusBar', "Controls the visibility of the status bar at the bottom of the suggest widget.")
|
markdownDescription: nls.localize('editor.suggest.statusBar.visible', "Controls the visibility of the status bar at the bottom of the suggest widget.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -3118,7 +3126,9 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
|
|||||||
showFolders: EditorBooleanOption.boolean(input.showFolders, this.defaultValue.showFolders),
|
showFolders: EditorBooleanOption.boolean(input.showFolders, this.defaultValue.showFolders),
|
||||||
showTypeParameters: EditorBooleanOption.boolean(input.showTypeParameters, this.defaultValue.showTypeParameters),
|
showTypeParameters: EditorBooleanOption.boolean(input.showTypeParameters, this.defaultValue.showTypeParameters),
|
||||||
showSnippets: EditorBooleanOption.boolean(input.showSnippets, this.defaultValue.showSnippets),
|
showSnippets: EditorBooleanOption.boolean(input.showSnippets, this.defaultValue.showSnippets),
|
||||||
hideStatusBar: EditorBooleanOption.boolean(input.hideStatusBar, this.defaultValue.hideStatusBar),
|
statusBar: {
|
||||||
|
visible: EditorBooleanOption.boolean(input.statusBar?.visible, !!this.defaultValue.statusBar.visible)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3333,7 +3343,7 @@ export const enum EditorOption {
|
|||||||
folding,
|
folding,
|
||||||
foldingStrategy,
|
foldingStrategy,
|
||||||
foldingHighlight,
|
foldingHighlight,
|
||||||
unfoldOnClickInEmptyContent,
|
unfoldOnClickAfterEndOfLine,
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontInfo,
|
fontInfo,
|
||||||
fontLigatures,
|
fontLigatures,
|
||||||
@@ -3633,9 +3643,9 @@ export const EditorOptions = {
|
|||||||
EditorOption.foldingHighlight, 'foldingHighlight', true,
|
EditorOption.foldingHighlight, 'foldingHighlight', true,
|
||||||
{ description: nls.localize('foldingHighlight', "Controls whether the editor should highlight folded ranges.") }
|
{ description: nls.localize('foldingHighlight', "Controls whether the editor should highlight folded ranges.") }
|
||||||
)),
|
)),
|
||||||
unfoldOnClickInEmptyContent: register(new EditorBooleanOption(
|
unfoldOnClickAfterEndOfLine: register(new EditorBooleanOption(
|
||||||
EditorOption.unfoldOnClickInEmptyContent, 'unfoldOnClickInEmptyContent', false,
|
EditorOption.unfoldOnClickAfterEndOfLine, 'unfoldOnClickAfterEndOfLine', false,
|
||||||
{ description: nls.localize('unfoldOnClickInEmptyContent', "Controls whether clicking on the empty content after a folded line will unfold the line.") }
|
{ description: nls.localize('unfoldOnClickAfterEndOfLine', "Controls whether clicking on the empty content after a folded line will unfold the line.") }
|
||||||
)),
|
)),
|
||||||
fontFamily: register(new EditorStringOption(
|
fontFamily: register(new EditorStringOption(
|
||||||
EditorOption.fontFamily, 'fontFamily', EDITOR_FONT_DEFAULTS.fontFamily,
|
EditorOption.fontFamily, 'fontFamily', EDITOR_FONT_DEFAULTS.fontFamily,
|
||||||
@@ -3777,7 +3787,7 @@ export const EditorOptions = {
|
|||||||
)),
|
)),
|
||||||
definitionLinkOpensInPeek: register(new EditorBooleanOption(
|
definitionLinkOpensInPeek: register(new EditorBooleanOption(
|
||||||
EditorOption.definitionLinkOpensInPeek, 'definitionLinkOpensInPeek', false,
|
EditorOption.definitionLinkOpensInPeek, 'definitionLinkOpensInPeek', false,
|
||||||
{ description: nls.localize('definitionLinkOpensInPeek', "Controls whether the definition link opens element in the peek widget.") }
|
{ description: nls.localize('definitionLinkOpensInPeek', "Controls whether the Go to Definition mouse gesture always opens the peek widget.") }
|
||||||
)),
|
)),
|
||||||
quickSuggestions: register(new EditorQuickSuggestions()),
|
quickSuggestions: register(new EditorQuickSuggestions()),
|
||||||
quickSuggestionsDelay: register(new EditorIntOption(
|
quickSuggestionsDelay: register(new EditorIntOption(
|
||||||
|
|||||||
@@ -430,15 +430,14 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
|||||||
return this._columnSelectData;
|
return this._columnSelectData;
|
||||||
}
|
}
|
||||||
const primaryCursor = this._cursors.getPrimaryCursor();
|
const primaryCursor = this._cursors.getPrimaryCursor();
|
||||||
const primaryPos = primaryCursor.viewState.selectionStart.getStartPosition();
|
const viewSelectionStart = primaryCursor.viewState.selectionStart.getStartPosition();
|
||||||
const viewLineNumber = primaryPos.lineNumber;
|
const viewPosition = primaryCursor.viewState.position;
|
||||||
const viewVisualColumn = CursorColumns.visibleColumnFromColumn2(this.context.config, this.context.viewModel, primaryPos);
|
|
||||||
return {
|
return {
|
||||||
isReal: false,
|
isReal: false,
|
||||||
fromViewLineNumber: viewLineNumber,
|
fromViewLineNumber: viewSelectionStart.lineNumber,
|
||||||
fromViewVisualColumn: viewVisualColumn,
|
fromViewVisualColumn: CursorColumns.visibleColumnFromColumn2(this.context.config, this.context.viewModel, viewSelectionStart),
|
||||||
toViewLineNumber: viewLineNumber,
|
toViewLineNumber: viewPosition.lineNumber,
|
||||||
toViewVisualColumn: viewVisualColumn,
|
toViewVisualColumn: CursorColumns.visibleColumnFromColumn2(this.context.config, this.context.viewModel, viewPosition),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -494,7 +494,7 @@ export interface CompletionItem {
|
|||||||
preselect?: boolean;
|
preselect?: boolean;
|
||||||
/**
|
/**
|
||||||
* A string or snippet that should be inserted in a document when selecting
|
* A string or snippet that should be inserted in a document when selecting
|
||||||
* this completion. When `falsy` the [label](#CompletionItem.label)
|
* this completion.
|
||||||
* is used.
|
* is used.
|
||||||
*/
|
*/
|
||||||
insertText: string;
|
insertText: string;
|
||||||
@@ -1373,7 +1373,7 @@ export interface RenameProvider {
|
|||||||
*/
|
*/
|
||||||
export interface AuthenticationSession {
|
export interface AuthenticationSession {
|
||||||
id: string;
|
id: string;
|
||||||
accessToken(): Promise<string>;
|
getAccessToken(): Thenable<string>;
|
||||||
accountName: string;
|
accountName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ export enum EditorOption {
|
|||||||
folding = 31,
|
folding = 31,
|
||||||
foldingStrategy = 32,
|
foldingStrategy = 32,
|
||||||
foldingHighlight = 33,
|
foldingHighlight = 33,
|
||||||
unfoldOnClickInEmptyContent = 34,
|
unfoldOnClickAfterEndOfLine = 34,
|
||||||
fontFamily = 35,
|
fontFamily = 35,
|
||||||
fontInfo = 36,
|
fontInfo = 36,
|
||||||
fontLigatures = 37,
|
fontLigatures = 37,
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ class ExecCommandPasteAction extends ExecCommandAction {
|
|||||||
kbExpr: EditorContextKeys.textInputFocus,
|
kbExpr: EditorContextKeys.textInputFocus,
|
||||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_V,
|
primary: KeyMod.CtrlCmd | KeyCode.KEY_V,
|
||||||
win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_V, secondary: [KeyMod.Shift | KeyCode.Insert] },
|
win: { primary: KeyMod.CtrlCmd | KeyCode.KEY_V, secondary: [KeyMod.Shift | KeyCode.Insert] },
|
||||||
|
linux: { primary: KeyMod.CtrlCmd | KeyCode.KEY_V, secondary: [KeyMod.Shift | KeyCode.Insert] },
|
||||||
weight: KeybindingWeight.EditorContrib
|
weight: KeybindingWeight.EditorContrib
|
||||||
};
|
};
|
||||||
// Do not bind paste keybindings in the browser,
|
// Do not bind paste keybindings in the browser,
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ export async function applyCodeAction(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (action.edit) {
|
if (action.edit) {
|
||||||
await bulkEditService.apply(action.edit, { editor });
|
await bulkEditService.apply(action.edit, { editor, label: action.title });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.command) {
|
if (action.command) {
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
|||||||
private readonly editor: ICodeEditor;
|
private readonly editor: ICodeEditor;
|
||||||
private _isEnabled: boolean;
|
private _isEnabled: boolean;
|
||||||
private _useFoldingProviders: boolean;
|
private _useFoldingProviders: boolean;
|
||||||
private _unfoldOnClickInEmptyContent: boolean;
|
private _unfoldOnClickAfterEndOfLine: boolean;
|
||||||
|
|
||||||
private readonly foldingDecorationProvider: FoldingDecorationProvider;
|
private readonly foldingDecorationProvider: FoldingDecorationProvider;
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
|||||||
const options = this.editor.getOptions();
|
const options = this.editor.getOptions();
|
||||||
this._isEnabled = options.get(EditorOption.folding);
|
this._isEnabled = options.get(EditorOption.folding);
|
||||||
this._useFoldingProviders = options.get(EditorOption.foldingStrategy) !== 'indentation';
|
this._useFoldingProviders = options.get(EditorOption.foldingStrategy) !== 'indentation';
|
||||||
this._unfoldOnClickInEmptyContent = options.get(EditorOption.unfoldOnClickInEmptyContent);
|
this._unfoldOnClickAfterEndOfLine = options.get(EditorOption.unfoldOnClickAfterEndOfLine);
|
||||||
|
|
||||||
this.foldingModel = null;
|
this.foldingModel = null;
|
||||||
this.hiddenRangeModel = null;
|
this.hiddenRangeModel = null;
|
||||||
@@ -114,8 +114,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
|||||||
|
|
||||||
this._register(this.editor.onDidChangeConfiguration((e: ConfigurationChangedEvent) => {
|
this._register(this.editor.onDidChangeConfiguration((e: ConfigurationChangedEvent) => {
|
||||||
if (e.hasChanged(EditorOption.folding)) {
|
if (e.hasChanged(EditorOption.folding)) {
|
||||||
const options = this.editor.getOptions();
|
this._isEnabled = this.editor.getOptions().get(EditorOption.folding);
|
||||||
this._isEnabled = options.get(EditorOption.folding);
|
|
||||||
this.foldingEnabled.set(this._isEnabled);
|
this.foldingEnabled.set(this._isEnabled);
|
||||||
this.onModelChanged();
|
this.onModelChanged();
|
||||||
}
|
}
|
||||||
@@ -126,12 +125,11 @@ export class FoldingController extends Disposable implements IEditorContribution
|
|||||||
this.onModelContentChanged();
|
this.onModelContentChanged();
|
||||||
}
|
}
|
||||||
if (e.hasChanged(EditorOption.foldingStrategy)) {
|
if (e.hasChanged(EditorOption.foldingStrategy)) {
|
||||||
const options = this.editor.getOptions();
|
this._useFoldingProviders = this.editor.getOptions().get(EditorOption.foldingStrategy) !== 'indentation';
|
||||||
this._useFoldingProviders = options.get(EditorOption.foldingStrategy) !== 'indentation';
|
|
||||||
this.onFoldingStrategyChanged();
|
this.onFoldingStrategyChanged();
|
||||||
}
|
}
|
||||||
if (e.hasChanged(EditorOption.unfoldOnClickInEmptyContent)) {
|
if (e.hasChanged(EditorOption.unfoldOnClickAfterEndOfLine)) {
|
||||||
this._unfoldOnClickInEmptyContent = options.get(EditorOption.unfoldOnClickInEmptyContent);
|
this._unfoldOnClickAfterEndOfLine = this.editor.getOptions().get(EditorOption.unfoldOnClickAfterEndOfLine);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
this.onModelChanged();
|
this.onModelChanged();
|
||||||
@@ -370,7 +368,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
|||||||
iconClicked = true;
|
iconClicked = true;
|
||||||
break;
|
break;
|
||||||
case MouseTargetType.CONTENT_EMPTY: {
|
case MouseTargetType.CONTENT_EMPTY: {
|
||||||
if (this._unfoldOnClickInEmptyContent && this.hiddenRangeModel.hasRanges()) {
|
if (this._unfoldOnClickAfterEndOfLine && this.hiddenRangeModel.hasRanges()) {
|
||||||
const data = e.target.detail as IEmptyContentData;
|
const data = e.target.detail as IEmptyContentData;
|
||||||
if (!data.isAfterLines) {
|
if (!data.isAfterLines) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -338,9 +338,8 @@ export class GotoDefinitionAtPositionEditorContribution implements IEditorContri
|
|||||||
|
|
||||||
private gotoDefinition(position: Position, openToSide: boolean): Promise<any> {
|
private gotoDefinition(position: Position, openToSide: boolean): Promise<any> {
|
||||||
this.editor.setPosition(position);
|
this.editor.setPosition(position);
|
||||||
const definitionLinkOpensInPeek = this.editor.getOption(EditorOption.definitionLinkOpensInPeek);
|
|
||||||
return this.editor.invokeWithinContext((accessor) => {
|
return this.editor.invokeWithinContext((accessor) => {
|
||||||
const canPeek = definitionLinkOpensInPeek && !this.isInPeekEditor(accessor);
|
const canPeek = !openToSide && this.editor.getOption(EditorOption.definitionLinkOpensInPeek) && !this.isInPeekEditor(accessor);
|
||||||
const action = new DefinitionAction({ openToSide, openInPeek: canPeek, muteMessage: true }, { alias: '', label: '', id: '', precondition: undefined });
|
const action = new DefinitionAction({ openToSide, openInPeek: canPeek, muteMessage: true }, { alias: '', label: '', id: '', precondition: undefined });
|
||||||
return action.run(accessor, this.editor);
|
return action.run(accessor, this.editor);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ export class LinksList extends Disposable {
|
|||||||
const newLinks = list.links.map(link => new Link(link, provider));
|
const newLinks = list.links.map(link => new Link(link, provider));
|
||||||
links = LinksList._union(links, newLinks);
|
links = LinksList._union(links, newLinks);
|
||||||
// register disposables
|
// register disposables
|
||||||
if (isDisposable(provider)) {
|
if (isDisposable(list)) {
|
||||||
this._register(provider);
|
this._register(list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.links = links;
|
this.links = links;
|
||||||
|
|||||||
@@ -206,7 +206,8 @@ class RenameController implements IEditorContribution {
|
|||||||
this._bulkEditService.apply(renameResult, {
|
this._bulkEditService.apply(renameResult, {
|
||||||
editor: this.editor,
|
editor: this.editor,
|
||||||
showPreview: inputFieldResult.wantsPreview,
|
showPreview: inputFieldResult.wantsPreview,
|
||||||
label: nls.localize('label', "Renaming '{0}'", loc?.text)
|
label: nls.localize('label', "Renaming '{0}'", loc?.text),
|
||||||
|
quotableLabel: nls.localize('quotableLabel', "Renaming {0}", loc?.text),
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
if (result.ariaSummary) {
|
if (result.ariaSummary) {
|
||||||
alert(nls.localize('aria', "Successfully renamed '{0}' to '{1}'. Summary: {2}", loc!.text, inputFieldResult.newName, result.ariaSummary));
|
alert(nls.localize('aria', "Successfully renamed '{0}' to '{1}'. Summary: {2}", loc!.text, inputFieldResult.newName, result.ariaSummary));
|
||||||
|
|||||||
@@ -234,7 +234,7 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
.monaco-editor .suggest-widget .monaco-list .monaco-list-row:not(.string-label) > .contents > .main > .left > .monaco-icon-label {
|
.monaco-editor .suggest-widget .monaco-list .monaco-list-row:not(.string-label) > .contents > .main > .left > .monaco-icon-label {
|
||||||
max-width: 80%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
.monaco-editor .suggest-widget .monaco-list .monaco-list-row.string-label > .contents > .main > .left > .monaco-icon-label {
|
.monaco-editor .suggest-widget .monaco-list .monaco-list-row.string-label > .contents > .main > .left > .monaco-icon-label {
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
@@ -392,6 +392,10 @@
|
|||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .docs.markdown-docs .codicon {
|
||||||
|
vertical-align: sub;
|
||||||
|
}
|
||||||
|
|
||||||
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > p:empty {
|
.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > p:empty {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -552,7 +552,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
|
|||||||
this.messageElement = append(this.element, $('.message'));
|
this.messageElement = append(this.element, $('.message'));
|
||||||
this.listElement = append(this.element, $('.tree'));
|
this.listElement = append(this.element, $('.tree'));
|
||||||
|
|
||||||
const applyStatusBarStyle = () => toggleClass(this.element, 'with-status-bar', !this.editor.getOption(EditorOption.suggest).hideStatusBar);
|
const applyStatusBarStyle = () => toggleClass(this.element, 'with-status-bar', this.editor.getOption(EditorOption.suggest).statusBar.visible);
|
||||||
applyStatusBarStyle();
|
applyStatusBarStyle();
|
||||||
|
|
||||||
this.statusBarElement = append(this.element, $('.suggest-status-bar'));
|
this.statusBarElement = append(this.element, $('.suggest-status-bar'));
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ interface IEditorLayoutProviderOpts {
|
|||||||
readonly minimapSide: 'left' | 'right';
|
readonly minimapSide: 'left' | 'right';
|
||||||
readonly minimapRenderCharacters: boolean;
|
readonly minimapRenderCharacters: boolean;
|
||||||
readonly minimapMaxColumn: number;
|
readonly minimapMaxColumn: number;
|
||||||
minimapMode?: 'actual' | 'cover' | 'contain';
|
minimapSize?: 'proportional' | 'fill' | 'fit';
|
||||||
readonly pixelRatio: number;
|
readonly pixelRatio: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
options._write(EditorOption.folding, false);
|
options._write(EditorOption.folding, false);
|
||||||
const minimapOptions: EditorMinimapOptions = {
|
const minimapOptions: EditorMinimapOptions = {
|
||||||
enabled: input.minimap,
|
enabled: input.minimap,
|
||||||
mode: input.minimapMode || 'actual',
|
size: input.minimapSize || 'proportional',
|
||||||
side: input.minimapSide,
|
side: input.minimapSide,
|
||||||
renderCharacters: input.minimapRenderCharacters,
|
renderCharacters: input.minimapRenderCharacters,
|
||||||
maxColumn: input.minimapMaxColumn,
|
maxColumn: input.minimapMaxColumn,
|
||||||
@@ -978,7 +978,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
minimapSide: 'right',
|
minimapSide: 'right',
|
||||||
minimapRenderCharacters: true,
|
minimapRenderCharacters: true,
|
||||||
minimapMaxColumn: 150,
|
minimapMaxColumn: 150,
|
||||||
minimapMode: 'cover',
|
minimapSize: 'fill',
|
||||||
pixelRatio: 2,
|
pixelRatio: 2,
|
||||||
}, {
|
}, {
|
||||||
width: 1000,
|
width: 1000,
|
||||||
@@ -1042,7 +1042,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
minimapSide: 'right',
|
minimapSide: 'right',
|
||||||
minimapRenderCharacters: true,
|
minimapRenderCharacters: true,
|
||||||
minimapMaxColumn: 150,
|
minimapMaxColumn: 150,
|
||||||
minimapMode: 'cover',
|
minimapSize: 'fill',
|
||||||
pixelRatio: 2,
|
pixelRatio: 2,
|
||||||
}, {
|
}, {
|
||||||
width: 1000,
|
width: 1000,
|
||||||
@@ -1106,7 +1106,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
minimapSide: 'right',
|
minimapSide: 'right',
|
||||||
minimapRenderCharacters: true,
|
minimapRenderCharacters: true,
|
||||||
minimapMaxColumn: 150,
|
minimapMaxColumn: 150,
|
||||||
minimapMode: 'contain',
|
minimapSize: 'fit',
|
||||||
pixelRatio: 2,
|
pixelRatio: 2,
|
||||||
}, {
|
}, {
|
||||||
width: 1000,
|
width: 1000,
|
||||||
@@ -1170,7 +1170,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
minimapSide: 'right',
|
minimapSide: 'right',
|
||||||
minimapRenderCharacters: true,
|
minimapRenderCharacters: true,
|
||||||
minimapMaxColumn: 150,
|
minimapMaxColumn: 150,
|
||||||
minimapMode: 'contain',
|
minimapSize: 'fit',
|
||||||
pixelRatio: 2,
|
pixelRatio: 2,
|
||||||
}, {
|
}, {
|
||||||
width: 1000,
|
width: 1000,
|
||||||
|
|||||||
19
src/vs/monaco.d.ts
vendored
19
src/vs/monaco.d.ts
vendored
@@ -3035,7 +3035,7 @@ declare namespace monaco.editor {
|
|||||||
* Controls whether clicking on the empty content after a folded line will unfold the line.
|
* Controls whether clicking on the empty content after a folded line will unfold the line.
|
||||||
* Defaults to false.
|
* Defaults to false.
|
||||||
*/
|
*/
|
||||||
unfoldOnClickInEmptyContent?: boolean;
|
unfoldOnClickAfterEndOfLine?: boolean;
|
||||||
/**
|
/**
|
||||||
* Enable highlighting of matching brackets.
|
* Enable highlighting of matching brackets.
|
||||||
* Defaults to 'always'.
|
* Defaults to 'always'.
|
||||||
@@ -3448,7 +3448,7 @@ declare namespace monaco.editor {
|
|||||||
* Control the minimap rendering mode.
|
* Control the minimap rendering mode.
|
||||||
* Defaults to 'actual'.
|
* Defaults to 'actual'.
|
||||||
*/
|
*/
|
||||||
mode?: 'actual' | 'cover' | 'contain';
|
size?: 'proportional' | 'fill' | 'fit';
|
||||||
/**
|
/**
|
||||||
* Control the rendering of the minimap slider.
|
* Control the rendering of the minimap slider.
|
||||||
* Defaults to 'mouseover'.
|
* Defaults to 'mouseover'.
|
||||||
@@ -3758,9 +3758,14 @@ declare namespace monaco.editor {
|
|||||||
*/
|
*/
|
||||||
showSnippets?: boolean;
|
showSnippets?: boolean;
|
||||||
/**
|
/**
|
||||||
* Controls the visibility of the status bar at the bottom of the suggest widget.
|
* Status bar related settings.
|
||||||
*/
|
*/
|
||||||
hideStatusBar?: boolean;
|
statusBar?: {
|
||||||
|
/**
|
||||||
|
* Controls the visibility of the status bar at the bottom of the suggest widget.
|
||||||
|
*/
|
||||||
|
visible?: boolean;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type InternalSuggestOptions = Readonly<Required<ISuggestOptions>>;
|
export type InternalSuggestOptions = Readonly<Required<ISuggestOptions>>;
|
||||||
@@ -3829,7 +3834,7 @@ declare namespace monaco.editor {
|
|||||||
folding = 31,
|
folding = 31,
|
||||||
foldingStrategy = 32,
|
foldingStrategy = 32,
|
||||||
foldingHighlight = 33,
|
foldingHighlight = 33,
|
||||||
unfoldOnClickInEmptyContent = 34,
|
unfoldOnClickAfterEndOfLine = 34,
|
||||||
fontFamily = 35,
|
fontFamily = 35,
|
||||||
fontInfo = 36,
|
fontInfo = 36,
|
||||||
fontLigatures = 37,
|
fontLigatures = 37,
|
||||||
@@ -3945,7 +3950,7 @@ declare namespace monaco.editor {
|
|||||||
folding: IEditorOption<EditorOption.folding, boolean>;
|
folding: IEditorOption<EditorOption.folding, boolean>;
|
||||||
foldingStrategy: IEditorOption<EditorOption.foldingStrategy, 'auto' | 'indentation'>;
|
foldingStrategy: IEditorOption<EditorOption.foldingStrategy, 'auto' | 'indentation'>;
|
||||||
foldingHighlight: IEditorOption<EditorOption.foldingHighlight, boolean>;
|
foldingHighlight: IEditorOption<EditorOption.foldingHighlight, boolean>;
|
||||||
unfoldOnClickInEmptyContent: IEditorOption<EditorOption.unfoldOnClickInEmptyContent, boolean>;
|
unfoldOnClickAfterEndOfLine: IEditorOption<EditorOption.unfoldOnClickAfterEndOfLine, boolean>;
|
||||||
fontFamily: IEditorOption<EditorOption.fontFamily, string>;
|
fontFamily: IEditorOption<EditorOption.fontFamily, string>;
|
||||||
fontInfo: IEditorOption<EditorOption.fontInfo, FontInfo>;
|
fontInfo: IEditorOption<EditorOption.fontInfo, FontInfo>;
|
||||||
fontLigatures2: IEditorOption<EditorOption.fontLigatures, string>;
|
fontLigatures2: IEditorOption<EditorOption.fontLigatures, string>;
|
||||||
@@ -5451,7 +5456,7 @@ declare namespace monaco.languages {
|
|||||||
preselect?: boolean;
|
preselect?: boolean;
|
||||||
/**
|
/**
|
||||||
* A string or snippet that should be inserted in a document when selecting
|
* A string or snippet that should be inserted in a document when selecting
|
||||||
* this completion. When `falsy` the [label](#CompletionItem.label)
|
* this completion.
|
||||||
* is used.
|
* is used.
|
||||||
*/
|
*/
|
||||||
insertText: string;
|
insertText: string;
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export class EnvironmentService implements IEnvironmentService {
|
|||||||
get settingsResource(): URI { return resources.joinPath(this.userRoamingDataHome, 'settings.json'); }
|
get settingsResource(): URI { return resources.joinPath(this.userRoamingDataHome, 'settings.json'); }
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
get userDataSyncHome(): URI { return resources.joinPath(this.userRoamingDataHome, '.sync'); }
|
get userDataSyncHome(): URI { return resources.joinPath(this.userRoamingDataHome, 'sync'); }
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
get settingsSyncPreviewResource(): URI { return resources.joinPath(this.userDataSyncHome, 'settings.json'); }
|
get settingsSyncPreviewResource(): URI { return resources.joinPath(this.userDataSyncHome, 'settings.json'); }
|
||||||
|
|||||||
@@ -101,6 +101,12 @@ export interface INotification extends INotificationProperties {
|
|||||||
* this usecase and much easier to use!
|
* this usecase and much easier to use!
|
||||||
*/
|
*/
|
||||||
actions?: INotificationActions;
|
actions?: INotificationActions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The initial set of progress properties for the notification. To update progress
|
||||||
|
* later on, access the `INotificationHandle.progress` property.
|
||||||
|
*/
|
||||||
|
progress?: INotificationProgressProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INotificationActions {
|
export interface INotificationActions {
|
||||||
@@ -119,6 +125,24 @@ export interface INotificationActions {
|
|||||||
secondary?: ReadonlyArray<IAction>;
|
secondary?: ReadonlyArray<IAction>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface INotificationProgressProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Causes the progress bar to spin infinitley.
|
||||||
|
*/
|
||||||
|
infinite?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate the total amount of work.
|
||||||
|
*/
|
||||||
|
total?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that a specific chunk of work is done.
|
||||||
|
*/
|
||||||
|
worked?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface INotificationProgress {
|
export interface INotificationProgress {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,6 +173,13 @@ export interface INotificationHandle {
|
|||||||
*/
|
*/
|
||||||
readonly onDidClose: Event<void>;
|
readonly onDidClose: Event<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will be fired whenever the visibility of the notification changes.
|
||||||
|
* A notification can either be visible as toast or inside the notification
|
||||||
|
* center if it is visible.
|
||||||
|
*/
|
||||||
|
readonly onDidChangeVisibility: Event<boolean>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to indicate progress on the notification even after the
|
* Allows to indicate progress on the notification even after the
|
||||||
* notification is already visible.
|
* notification is already visible.
|
||||||
|
|||||||
@@ -240,9 +240,36 @@ export class FileStorageDatabase extends Disposable implements IStorageDatabase
|
|||||||
private async onDidStorageChangeExternal(): Promise<void> {
|
private async onDidStorageChangeExternal(): Promise<void> {
|
||||||
const items = await this.doGetItemsFromFile();
|
const items = await this.doGetItemsFromFile();
|
||||||
|
|
||||||
|
// pervious cache, diff for changes
|
||||||
|
let changed = new Map<string, string>();
|
||||||
|
let deleted = new Set<string>();
|
||||||
|
if (this.cache) {
|
||||||
|
items.forEach((value, key) => {
|
||||||
|
const existingValue = this.cache?.get(key);
|
||||||
|
if (existingValue !== value) {
|
||||||
|
changed.set(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.cache.forEach((_, key) => {
|
||||||
|
if (!items.has(key)) {
|
||||||
|
deleted.add(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// no previous cache, consider all as changed
|
||||||
|
else {
|
||||||
|
changed = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update cache
|
||||||
this.cache = items;
|
this.cache = items;
|
||||||
|
|
||||||
this._onDidChangeItemsExternal.fire({ items });
|
// Emit as event as needed
|
||||||
|
if (changed.size > 0 || deleted.size > 0) {
|
||||||
|
this._onDidChangeItemsExternal.fire({ changed, deleted });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getItems(): Promise<Map<string, string>> {
|
async getItems(): Promise<Map<string, string>> {
|
||||||
|
|||||||
@@ -24,15 +24,16 @@ interface ISerializableUpdateRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ISerializableItemsChangeEvent {
|
interface ISerializableItemsChangeEvent {
|
||||||
items: Item[];
|
changed?: Item[];
|
||||||
|
deleted?: Key[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GlobalStorageDatabaseChannel extends Disposable implements IServerChannel {
|
export class GlobalStorageDatabaseChannel extends Disposable implements IServerChannel {
|
||||||
|
|
||||||
private static readonly STORAGE_CHANGE_DEBOUNCE_TIME = 100;
|
private static readonly STORAGE_CHANGE_DEBOUNCE_TIME = 100;
|
||||||
|
|
||||||
private readonly _onDidChangeItems: Emitter<ISerializableItemsChangeEvent> = this._register(new Emitter<ISerializableItemsChangeEvent>());
|
private readonly _onDidChangeItems = this._register(new Emitter<ISerializableItemsChangeEvent>());
|
||||||
readonly onDidChangeItems: Event<ISerializableItemsChangeEvent> = this._onDidChangeItems.event;
|
readonly onDidChangeItems = this._onDidChangeItems.event;
|
||||||
|
|
||||||
private whenReady: Promise<void>;
|
private whenReady: Promise<void>;
|
||||||
|
|
||||||
@@ -99,15 +100,18 @@ export class GlobalStorageDatabaseChannel extends Disposable implements IServerC
|
|||||||
}
|
}
|
||||||
|
|
||||||
private serializeEvents(events: IStorageChangeEvent[]): ISerializableItemsChangeEvent {
|
private serializeEvents(events: IStorageChangeEvent[]): ISerializableItemsChangeEvent {
|
||||||
const items = new Map<Key, Value>();
|
const changed = new Map<Key, Value>();
|
||||||
|
const deleted = new Set<Key>();
|
||||||
events.forEach(event => {
|
events.forEach(event => {
|
||||||
const existing = this.storageMainService.get(event.key);
|
const existing = this.storageMainService.get(event.key);
|
||||||
if (typeof existing === 'string') {
|
if (typeof existing === 'string') {
|
||||||
items.set(event.key, existing);
|
changed.set(event.key, existing);
|
||||||
|
} else {
|
||||||
|
deleted.add(event.key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return { items: mapToSerializable(items) };
|
return { changed: mapToSerializable(changed), deleted: values(deleted) };
|
||||||
}
|
}
|
||||||
|
|
||||||
listen(_: unknown, event: string): Event<any> {
|
listen(_: unknown, event: string): Event<any> {
|
||||||
@@ -170,8 +174,11 @@ export class GlobalStorageDatabaseChannelClient extends Disposable implements IS
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onDidChangeItemsOnMain(e: ISerializableItemsChangeEvent): void {
|
private onDidChangeItemsOnMain(e: ISerializableItemsChangeEvent): void {
|
||||||
if (Array.isArray(e.items)) {
|
if (Array.isArray(e.changed) || Array.isArray(e.deleted)) {
|
||||||
this._onDidChangeItemsExternal.fire({ items: serializableToMap(e.items) });
|
this._onDidChangeItemsExternal.fire({
|
||||||
|
changed: e.changed ? serializableToMap(e.changed) : undefined,
|
||||||
|
deleted: e.deleted ? new Set<string>(e.deleted) : undefined
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Emitter } from 'vs/base/common/event';
|
||||||
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
|
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
|
||||||
import { IWorkspaceStorageChangeEvent, IStorageService, StorageScope, IWillSaveStateEvent, WillSaveStateReason, logStorage } from 'vs/platform/storage/common/storage';
|
import { IWorkspaceStorageChangeEvent, IStorageService, StorageScope, IWillSaveStateEvent, WillSaveStateReason, logStorage } from 'vs/platform/storage/common/storage';
|
||||||
import { SQLiteStorageDatabase, ISQLiteStorageDatabaseLoggingOptions } from 'vs/base/parts/storage/node/storage';
|
import { SQLiteStorageDatabase, ISQLiteStorageDatabaseLoggingOptions } from 'vs/base/parts/storage/node/storage';
|
||||||
@@ -25,11 +25,11 @@ export class NativeStorageService extends Disposable implements IStorageService
|
|||||||
private static readonly WORKSPACE_STORAGE_NAME = 'state.vscdb';
|
private static readonly WORKSPACE_STORAGE_NAME = 'state.vscdb';
|
||||||
private static readonly WORKSPACE_META_NAME = 'workspace.json';
|
private static readonly WORKSPACE_META_NAME = 'workspace.json';
|
||||||
|
|
||||||
private readonly _onDidChangeStorage: Emitter<IWorkspaceStorageChangeEvent> = this._register(new Emitter<IWorkspaceStorageChangeEvent>());
|
private readonly _onDidChangeStorage = this._register(new Emitter<IWorkspaceStorageChangeEvent>());
|
||||||
readonly onDidChangeStorage: Event<IWorkspaceStorageChangeEvent> = this._onDidChangeStorage.event;
|
readonly onDidChangeStorage = this._onDidChangeStorage.event;
|
||||||
|
|
||||||
private readonly _onWillSaveState: Emitter<IWillSaveStateEvent> = this._register(new Emitter<IWillSaveStateEvent>());
|
private readonly _onWillSaveState = this._register(new Emitter<IWillSaveStateEvent>());
|
||||||
readonly onWillSaveState: Event<IWillSaveStateEvent> = this._onWillSaveState.event;
|
readonly onWillSaveState = this._onWillSaveState.event;
|
||||||
|
|
||||||
private globalStorage: IStorage;
|
private globalStorage: IStorage;
|
||||||
|
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ export class UndoRedoService implements IUndoRedoService {
|
|||||||
this._splitPastWorkspaceElement(element, element.removedResources.set);
|
this._splitPastWorkspaceElement(element, element.removedResources.set);
|
||||||
const message = nls.localize('cannotWorkspaceUndo', "Could not undo '{0}' across all files. {1}", element.label, element.removedResources.createMessage());
|
const message = nls.localize('cannotWorkspaceUndo', "Could not undo '{0}' across all files. {1}", element.label, element.removedResources.createMessage());
|
||||||
this._notificationService.info(message);
|
this._notificationService.info(message);
|
||||||
return;
|
return this.undo(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this must be the last past element in all the impacted resources!
|
// this must be the last past element in all the impacted resources!
|
||||||
@@ -281,18 +281,25 @@ export class UndoRedoService implements IUndoRedoService {
|
|||||||
const paths = cannotUndoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
|
const paths = cannotUndoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
|
||||||
const message = nls.localize('cannotWorkspaceUndoDueToChanges', "Could not undo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
|
const message = nls.localize('cannotWorkspaceUndoDueToChanges', "Could not undo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
|
||||||
this._notificationService.info(message);
|
this._notificationService.info(message);
|
||||||
return;
|
return this.undo(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._dialogService.show(
|
return this._dialogService.show(
|
||||||
Severity.Info,
|
Severity.Info,
|
||||||
nls.localize('confirmWorkspace', "Would you like to undo '{0}' across all files?", element.label),
|
nls.localize('confirmWorkspace', "Would you like to undo '{0}' across all files?", element.label),
|
||||||
[
|
[
|
||||||
nls.localize('ok', "Yes, change {0} files.", affectedEditStacks.length),
|
nls.localize('ok', "Undo In {0} Files", affectedEditStacks.length),
|
||||||
nls.localize('nok', "No, change only this file.")
|
nls.localize('nok', "Undo This File"),
|
||||||
]
|
nls.localize('cancel', "Cancel"),
|
||||||
|
],
|
||||||
|
{
|
||||||
|
cancelId: 2
|
||||||
|
}
|
||||||
).then((result) => {
|
).then((result) => {
|
||||||
if (result.choice === 0) {
|
if (result.choice === 2) {
|
||||||
|
// cancel
|
||||||
|
return;
|
||||||
|
} else if (result.choice === 0) {
|
||||||
for (const editStack of affectedEditStacks) {
|
for (const editStack of affectedEditStacks) {
|
||||||
editStack.past.pop();
|
editStack.past.pop();
|
||||||
editStack.future.push(element);
|
editStack.future.push(element);
|
||||||
@@ -344,7 +351,7 @@ export class UndoRedoService implements IUndoRedoService {
|
|||||||
this._splitFutureWorkspaceElement(element, element.removedResources.set);
|
this._splitFutureWorkspaceElement(element, element.removedResources.set);
|
||||||
const message = nls.localize('cannotWorkspaceRedo', "Could not redo '{0}' across all files. {1}", element.label, element.removedResources.createMessage());
|
const message = nls.localize('cannotWorkspaceRedo', "Could not redo '{0}' across all files. {1}", element.label, element.removedResources.createMessage());
|
||||||
this._notificationService.info(message);
|
this._notificationService.info(message);
|
||||||
return;
|
return this.redo(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this must be the last future element in all the impacted resources!
|
// this must be the last future element in all the impacted resources!
|
||||||
@@ -365,7 +372,7 @@ export class UndoRedoService implements IUndoRedoService {
|
|||||||
const paths = cannotRedoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
|
const paths = cannotRedoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
|
||||||
const message = nls.localize('cannotWorkspaceRedoDueToChanges', "Could not redo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
|
const message = nls.localize('cannotWorkspaceRedoDueToChanges', "Could not redo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
|
||||||
this._notificationService.info(message);
|
this._notificationService.info(message);
|
||||||
return;
|
return this.redo(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const editStack of affectedEditStacks) {
|
for (const editStack of affectedEditStacks) {
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export abstract class AbstractSynchroniser extends Disposable {
|
|||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.syncFolder = joinPath(environmentService.userDataSyncHome, source);
|
this.syncFolder = joinPath(environmentService.userDataSyncHome, source);
|
||||||
this.lastSyncResource = joinPath(this.syncFolder, `.lastSync${source}.json`);
|
this.lastSyncResource = joinPath(this.syncFolder, `lastSync${source}.json`);
|
||||||
this.cleanUpDelayer = new ThrottledDelayer(50);
|
this.cleanUpDelayer = new ThrottledDelayer(50);
|
||||||
this.cleanUpBackup();
|
this.cleanUpBackup();
|
||||||
}
|
}
|
||||||
@@ -202,7 +202,7 @@ export abstract class AbstractSynchroniser extends Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async backupLocal(content: VSBuffer): Promise<void> {
|
protected async backupLocal(content: VSBuffer): Promise<void> {
|
||||||
const resource = joinPath(this.syncFolder, toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, ''));
|
const resource = joinPath(this.syncFolder, `${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}.json`);
|
||||||
try {
|
try {
|
||||||
await this.fileService.writeFile(resource, content);
|
await this.fileService.writeFile(resource, content);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -213,9 +213,13 @@ export abstract class AbstractSynchroniser extends Disposable {
|
|||||||
|
|
||||||
private async cleanUpBackup(): Promise<void> {
|
private async cleanUpBackup(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
if (!(await this.fileService.exists(this.syncFolder))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const stat = await this.fileService.resolve(this.syncFolder);
|
const stat = await this.fileService.resolve(this.syncFolder);
|
||||||
if (stat.children) {
|
if (stat.children) {
|
||||||
const all = stat.children.filter(stat => stat.isFile && /^\d{8}T\d{6}$/.test(stat.name)).sort();
|
const all = stat.children.filter(stat => stat.isFile && /^\d{8}T\d{6}(\.json)?$/.test(stat.name)).sort();
|
||||||
|
console.log(all.map(a => a.name));
|
||||||
const backUpMaxAge = 1000 * 60 * 60 * 24 * (this.configurationService.getValue<number>('sync.localBackupDuration') || 30 /* Default 30 days */);
|
const backUpMaxAge = 1000 * 60 * 60 * 24 * (this.configurationService.getValue<number>('sync.localBackupDuration') || 30 /* Default 30 days */);
|
||||||
let toDelete = all.filter(stat => {
|
let toDelete = all.filter(stat => {
|
||||||
const ctime = stat.ctime || new Date(
|
const ctime = stat.ctime || new Date(
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
|
|||||||
if (added.length || removed.length || updated.length) {
|
if (added.length || removed.length || updated.length) {
|
||||||
// back up all disabled or market place extensions
|
// back up all disabled or market place extensions
|
||||||
const backUpExtensions = localExtensions.filter(e => e.disabled || !!e.identifier.uuid);
|
const backUpExtensions = localExtensions.filter(e => e.disabled || !!e.identifier.uuid);
|
||||||
await this.backupLocal(VSBuffer.fromString(JSON.stringify(backUpExtensions)));
|
await this.backupLocal(VSBuffer.fromString(JSON.stringify(backUpExtensions, null, '\t')));
|
||||||
skippedExtensions = await this.updateLocalExtensions(added, removed, updated, skippedExtensions);
|
skippedExtensions = await this.updateLocalExtensions(added, removed, updated, skippedExtensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
|
|||||||
if (local) {
|
if (local) {
|
||||||
// update local
|
// update local
|
||||||
this.logService.trace('UI State: Updating local ui state...');
|
this.logService.trace('UI State: Updating local ui state...');
|
||||||
await this.backupLocal(VSBuffer.fromString(JSON.stringify(localUserData)));
|
await this.backupLocal(VSBuffer.fromString(JSON.stringify(localUserData, null, '\t')));
|
||||||
await this.writeLocalGlobalState(local);
|
await this.writeLocalGlobalState(local);
|
||||||
this.logService.info('UI State: Updated local ui state');
|
this.logService.info('UI State: Updated local ui state');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ import { Event, Emitter } from 'vs/base/common/event';
|
|||||||
import { Disposable } from 'vs/base/common/lifecycle';
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
import { IUserDataSyncLogService, IUserDataSyncService, SyncStatus, IUserDataAutoSyncService, UserDataSyncError, UserDataSyncErrorCode, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
import { IUserDataSyncLogService, IUserDataSyncService, SyncStatus, IUserDataAutoSyncService, UserDataSyncError, UserDataSyncErrorCode, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||||
import { IAuthenticationTokenService } from 'vs/platform/authentication/common/authentication';
|
import { IAuthenticationTokenService } from 'vs/platform/authentication/common/authentication';
|
||||||
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
|
|
||||||
|
type AutoSyncTriggerClassification = {
|
||||||
|
source: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
||||||
|
};
|
||||||
|
|
||||||
export class UserDataAutoSyncService extends Disposable implements IUserDataAutoSyncService {
|
export class UserDataAutoSyncService extends Disposable implements IUserDataAutoSyncService {
|
||||||
|
|
||||||
@@ -25,6 +30,7 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto
|
|||||||
@IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService,
|
@IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService,
|
||||||
@IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
|
@IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
|
||||||
@IAuthenticationTokenService private readonly authTokenService: IAuthenticationTokenService,
|
@IAuthenticationTokenService private readonly authTokenService: IAuthenticationTokenService,
|
||||||
|
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.updateEnablement(false, true);
|
this.updateEnablement(false, true);
|
||||||
@@ -32,7 +38,7 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto
|
|||||||
this._register(Event.any<any>(authTokenService.onDidChangeToken)(() => this.updateEnablement(true, true)));
|
this._register(Event.any<any>(authTokenService.onDidChangeToken)(() => this.updateEnablement(true, true)));
|
||||||
this._register(Event.any<any>(userDataSyncService.onDidChangeStatus)(() => this.updateEnablement(true, true)));
|
this._register(Event.any<any>(userDataSyncService.onDidChangeStatus)(() => this.updateEnablement(true, true)));
|
||||||
this._register(this.userDataSyncEnablementService.onDidChangeEnablement(() => this.updateEnablement(true, false)));
|
this._register(this.userDataSyncEnablementService.onDidChangeEnablement(() => this.updateEnablement(true, false)));
|
||||||
this._register(this.userDataSyncEnablementService.onDidChangeResourceEnablement(() => this.triggerAutoSync()));
|
this._register(this.userDataSyncEnablementService.onDidChangeResourceEnablement(() => this.triggerAutoSync(['resourceEnablement'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateEnablement(stopIfDisabled: boolean, auto: boolean): Promise<void> {
|
private async updateEnablement(stopIfDisabled: boolean, auto: boolean): Promise<void> {
|
||||||
@@ -99,7 +105,8 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto
|
|||||||
this.successiveFailures = 0;
|
this.successiveFailures = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async triggerAutoSync(): Promise<void> {
|
async triggerAutoSync(sources: string[]): Promise<void> {
|
||||||
|
sources.forEach(source => this.telemetryService.publicLog2<{ source: string }, AutoSyncTriggerClassification>('sync/triggerAutoSync', { source }));
|
||||||
if (this.enabled) {
|
if (this.enabled) {
|
||||||
return this.syncDelayer.trigger(() => {
|
return this.syncDelayer.trigger(() => {
|
||||||
this.logService.info('Auto Sync: Triggered.');
|
this.logService.info('Auto Sync: Triggered.');
|
||||||
|
|||||||
@@ -278,7 +278,7 @@ export interface IUserDataSyncService {
|
|||||||
readonly conflictsSources: SyncSource[];
|
readonly conflictsSources: SyncSource[];
|
||||||
readonly onDidChangeConflicts: Event<SyncSource[]>;
|
readonly onDidChangeConflicts: Event<SyncSource[]>;
|
||||||
|
|
||||||
readonly onDidChangeLocal: Event<void>;
|
readonly onDidChangeLocal: Event<SyncSource>;
|
||||||
readonly onSyncErrors: Event<[SyncSource, UserDataSyncError][]>;
|
readonly onSyncErrors: Event<[SyncSource, UserDataSyncError][]>;
|
||||||
|
|
||||||
readonly lastSyncTime: number | undefined;
|
readonly lastSyncTime: number | undefined;
|
||||||
@@ -299,7 +299,7 @@ export const IUserDataAutoSyncService = createDecorator<IUserDataAutoSyncService
|
|||||||
export interface IUserDataAutoSyncService {
|
export interface IUserDataAutoSyncService {
|
||||||
_serviceBrand: any;
|
_serviceBrand: any;
|
||||||
readonly onError: Event<UserDataSyncError>;
|
readonly onError: Event<UserDataSyncError>;
|
||||||
triggerAutoSync(): Promise<void>;
|
triggerAutoSync(sources: string[]): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IUserDataSyncUtilService = createDecorator<IUserDataSyncUtilService>('IUserDataSyncUtilService');
|
export const IUserDataSyncUtilService = createDecorator<IUserDataSyncUtilService>('IUserDataSyncUtilService');
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export class UserDataAutoSyncChannel implements IServerChannel {
|
|||||||
|
|
||||||
call(context: any, command: string, args?: any): Promise<any> {
|
call(context: any, command: string, args?: any): Promise<any> {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case 'triggerAutoSync': return this.service.triggerAutoSync();
|
case 'triggerAutoSync': return this.service.triggerAutoSync(args[0]);
|
||||||
}
|
}
|
||||||
throw new Error('Invalid call');
|
throw new Error('Invalid call');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
|||||||
private _onDidChangeStatus: Emitter<SyncStatus> = this._register(new Emitter<SyncStatus>());
|
private _onDidChangeStatus: Emitter<SyncStatus> = this._register(new Emitter<SyncStatus>());
|
||||||
readonly onDidChangeStatus: Event<SyncStatus> = this._onDidChangeStatus.event;
|
readonly onDidChangeStatus: Event<SyncStatus> = this._onDidChangeStatus.event;
|
||||||
|
|
||||||
readonly onDidChangeLocal: Event<void>;
|
readonly onDidChangeLocal: Event<SyncSource>;
|
||||||
|
|
||||||
private _conflictsSources: SyncSource[] = [];
|
private _conflictsSources: SyncSource[] = [];
|
||||||
get conflictsSources(): SyncSource[] { return this._conflictsSources; }
|
get conflictsSources(): SyncSource[] { return this._conflictsSources; }
|
||||||
@@ -74,7 +74,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._lastSyncTime = this.storageService.getNumber(LAST_SYNC_TIME_KEY, StorageScope.GLOBAL, undefined);
|
this._lastSyncTime = this.storageService.getNumber(LAST_SYNC_TIME_KEY, StorageScope.GLOBAL, undefined);
|
||||||
this.onDidChangeLocal = Event.any(...this.synchronisers.map(s => s.onDidChangeLocal));
|
this.onDidChangeLocal = Event.any(...this.synchronisers.map(s => Event.map(s.onDidChangeLocal, () => s.source)));
|
||||||
}
|
}
|
||||||
|
|
||||||
async pull(): Promise<void> {
|
async pull(): Promise<void> {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { Event } from 'vs/base/common/event';
|
|||||||
import { IElectronService } from 'vs/platform/electron/node/electron';
|
import { IElectronService } from 'vs/platform/electron/node/electron';
|
||||||
import { UserDataAutoSyncService as BaseUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataAutoSyncService';
|
import { UserDataAutoSyncService as BaseUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataAutoSyncService';
|
||||||
import { IAuthenticationTokenService } from 'vs/platform/authentication/common/authentication';
|
import { IAuthenticationTokenService } from 'vs/platform/authentication/common/authentication';
|
||||||
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
|
|
||||||
export class UserDataAutoSyncService extends BaseUserDataAutoSyncService {
|
export class UserDataAutoSyncService extends BaseUserDataAutoSyncService {
|
||||||
|
|
||||||
@@ -17,15 +18,15 @@ export class UserDataAutoSyncService extends BaseUserDataAutoSyncService {
|
|||||||
@IElectronService electronService: IElectronService,
|
@IElectronService electronService: IElectronService,
|
||||||
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
@IUserDataSyncLogService logService: IUserDataSyncLogService,
|
||||||
@IAuthenticationTokenService authTokenService: IAuthenticationTokenService,
|
@IAuthenticationTokenService authTokenService: IAuthenticationTokenService,
|
||||||
|
@ITelemetryService telemetryService: ITelemetryService,
|
||||||
) {
|
) {
|
||||||
super(userDataSyncEnablementService, userDataSyncService, logService, authTokenService);
|
super(userDataSyncEnablementService, userDataSyncService, logService, authTokenService, telemetryService);
|
||||||
|
|
||||||
// Sync immediately if there is a local change.
|
this._register(Event.debounce<string, string[]>(Event.any<string>(
|
||||||
this._register(Event.debounce(Event.any<any>(
|
Event.map(electronService.onWindowFocus, () => 'windowFocus'),
|
||||||
electronService.onWindowFocus,
|
Event.map(electronService.onWindowOpen, () => 'windowOpen'),
|
||||||
electronService.onWindowOpen,
|
|
||||||
userDataSyncService.onDidChangeLocal,
|
userDataSyncService.onDidChangeLocal,
|
||||||
), () => undefined, 500)(() => this.triggerAutoSync()));
|
), (last, source) => last ? [...last, source] : [source], 1000)(sources => this.triggerAutoSync(sources)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
29
src/vs/vscode.d.ts
vendored
29
src/vs/vscode.d.ts
vendored
@@ -1500,7 +1500,7 @@ declare module 'vscode' {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A file system watcher notifies about changes to files and folders
|
* A file system watcher notifies about changes to files and folders
|
||||||
* on disk.
|
* on disk or from other [FileSystemProviders](#FileSystemProvider).
|
||||||
*
|
*
|
||||||
* To get an instance of a `FileSystemWatcher` use
|
* To get an instance of a `FileSystemWatcher` use
|
||||||
* [createFileSystemWatcher](#workspace.createFileSystemWatcher).
|
* [createFileSystemWatcher](#workspace.createFileSystemWatcher).
|
||||||
@@ -1806,7 +1806,7 @@ declare module 'vscode' {
|
|||||||
placeHolder?: string;
|
placeHolder?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to `true` to show a password prompt that will not show the typed value.
|
* Controls if a password input is shown. Password input hides the typed text.
|
||||||
*/
|
*/
|
||||||
password?: boolean;
|
password?: boolean;
|
||||||
|
|
||||||
@@ -2020,7 +2020,7 @@ declare module 'vscode' {
|
|||||||
* Base kind for source actions: `source`
|
* Base kind for source actions: `source`
|
||||||
*
|
*
|
||||||
* Source code actions apply to the entire file. They must be explicitly requested and will not show in the
|
* Source code actions apply to the entire file. They must be explicitly requested and will not show in the
|
||||||
* normal [light bulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) menu. Source actions
|
* normal [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) menu. Source actions
|
||||||
* can be run on save using `editor.codeActionsOnSave` and are also shown in the `source` context menu.
|
* can be run on save using `editor.codeActionsOnSave` and are also shown in the `source` context menu.
|
||||||
*/
|
*/
|
||||||
static readonly Source: CodeActionKind;
|
static readonly Source: CodeActionKind;
|
||||||
@@ -2086,7 +2086,7 @@ declare module 'vscode' {
|
|||||||
/**
|
/**
|
||||||
* Requested kind of actions to return.
|
* Requested kind of actions to return.
|
||||||
*
|
*
|
||||||
* Actions not of this kind are filtered out before being shown by the lightbulb.
|
* Actions not of this kind are filtered out before being shown by the [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action).
|
||||||
*/
|
*/
|
||||||
readonly only?: CodeActionKind;
|
readonly only?: CodeActionKind;
|
||||||
}
|
}
|
||||||
@@ -2138,7 +2138,15 @@ declare module 'vscode' {
|
|||||||
/**
|
/**
|
||||||
* Marks that the code action cannot currently be applied.
|
* Marks that the code action cannot currently be applied.
|
||||||
*
|
*
|
||||||
* Disabled code actions will be surfaced in the refactor UI but cannot be applied.
|
* - Disabled code actions are not shown in automatic [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)
|
||||||
|
* code action menu.
|
||||||
|
*
|
||||||
|
* - Disabled actions are shown as faded out in the code action menu when the user request a more specific type
|
||||||
|
* of code action, such as refactorings.
|
||||||
|
*
|
||||||
|
* - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions)
|
||||||
|
* that auto applies a code action and only a disabled code actions are returned, VS Code will show the user a
|
||||||
|
* message with `reason` in the editor.
|
||||||
*/
|
*/
|
||||||
disabled?: {
|
disabled?: {
|
||||||
/**
|
/**
|
||||||
@@ -2163,7 +2171,7 @@ declare module 'vscode' {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The code action interface defines the contract between extensions and
|
* The code action interface defines the contract between extensions and
|
||||||
* the [light bulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) feature.
|
* the [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) feature.
|
||||||
*
|
*
|
||||||
* A code action can be any command that is [known](#commands.getCommands) to the system.
|
* A code action can be any command that is [known](#commands.getCommands) to the system.
|
||||||
*/
|
*/
|
||||||
@@ -2495,16 +2503,18 @@ declare module 'vscode' {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The evaluatable expression provider interface defines the contract between extensions and
|
* The evaluatable expression provider interface defines the contract between extensions and
|
||||||
* the debug hover.
|
* the debug hover. In this contract the provider returns an evaluatable expression for a given position
|
||||||
|
* in a document and VS Code evaluates this expression in the active debug session and shows the result in a debug hover.
|
||||||
*/
|
*/
|
||||||
export interface EvaluatableExpressionProvider {
|
export interface EvaluatableExpressionProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide an evaluatable expression for the given document and position.
|
* Provide an evaluatable expression for the given document and position.
|
||||||
|
* VS Code will evaluate this expression in the active debug session and will show the result in the debug hover.
|
||||||
* The expression can be implicitly specified by the range in the underlying document or by explicitly returning an expression.
|
* The expression can be implicitly specified by the range in the underlying document or by explicitly returning an expression.
|
||||||
*
|
*
|
||||||
* @param document The document in which the debug hover is opened.
|
* @param document The document for which the debug hover is about to appear.
|
||||||
* @param position The position in the document where the debug hover is opened.
|
* @param position The line and character position in the document where the debug hover is about to appear.
|
||||||
* @param token A cancellation token.
|
* @param token A cancellation token.
|
||||||
* @return An EvaluatableExpression or a thenable that resolves to such. The lack of a result can be
|
* @return An EvaluatableExpression or a thenable that resolves to such. The lack of a result can be
|
||||||
* signaled by returning `undefined` or `null`.
|
* signaled by returning `undefined` or `null`.
|
||||||
@@ -9174,6 +9184,7 @@ declare module 'vscode' {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a provider that locates evaluatable expressions in text documents.
|
* Register a provider that locates evaluatable expressions in text documents.
|
||||||
|
* VS Code will evaluate the expression in the active debug session and will show the result in the debug hover.
|
||||||
*
|
*
|
||||||
* If multiple providers are registered for a language an arbitrary provider will be used.
|
* If multiple providers are registered for a language an arbitrary provider will be used.
|
||||||
*
|
*
|
||||||
|
|||||||
55
src/vs/vscode.proposed.d.ts
vendored
55
src/vs/vscode.proposed.d.ts
vendored
@@ -20,7 +20,7 @@ declare module 'vscode' {
|
|||||||
|
|
||||||
export interface AuthenticationSession {
|
export interface AuthenticationSession {
|
||||||
id: string;
|
id: string;
|
||||||
accessToken(): Promise<string>;
|
getAccessToken(): Thenable<string>;
|
||||||
accountName: string;
|
accountName: string;
|
||||||
scopes: string[]
|
scopes: string[]
|
||||||
}
|
}
|
||||||
@@ -58,13 +58,13 @@ declare module 'vscode' {
|
|||||||
/**
|
/**
|
||||||
* Returns an array of current sessions.
|
* Returns an array of current sessions.
|
||||||
*/
|
*/
|
||||||
getSessions(): Promise<ReadonlyArray<AuthenticationSession>>;
|
getSessions(): Thenable<ReadonlyArray<AuthenticationSession>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prompts a user to login.
|
* Prompts a user to login.
|
||||||
*/
|
*/
|
||||||
login(scopes: string[]): Promise<AuthenticationSession>;
|
login(scopes: string[]): Thenable<AuthenticationSession>;
|
||||||
logout(sessionId: string): Promise<void>;
|
logout(sessionId: string): Thenable<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace authentication {
|
export namespace authentication {
|
||||||
@@ -1273,14 +1273,14 @@ declare module 'vscode' {
|
|||||||
* in an operation that takes time to complete, your extension may decide to finish the ongoing backup rather
|
* in an operation that takes time to complete, your extension may decide to finish the ongoing backup rather
|
||||||
* than cancelling it to ensure that VS Code has some valid backup.
|
* than cancelling it to ensure that VS Code has some valid backup.
|
||||||
*/
|
*/
|
||||||
backup(cancellation: CancellationToken): Thenable<boolean>;
|
backup(cancellation: CancellationToken): Thenable<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a custom document for a custom webview editor.
|
* Represents a custom document for a custom webview editor.
|
||||||
*
|
*
|
||||||
* Custom documents are only used within a given `WebviewCustomEditorProvider`. The lifecycle of a
|
* Custom documents are only used within a given `CustomEditorProvider`. The lifecycle of a
|
||||||
* `WebviewEditorCustomDocument` is managed by VS Code. When more more references remain to a given `WebviewEditorCustomDocument`
|
* `CustomDocument` is managed by VS Code. When more more references remain to a given `CustomDocument`
|
||||||
* then it is disposed of.
|
* then it is disposed of.
|
||||||
*
|
*
|
||||||
* @param UserDataType Type of custom object that extensions can store on the document.
|
* @param UserDataType Type of custom object that extensions can store on the document.
|
||||||
@@ -1297,7 +1297,7 @@ declare module 'vscode' {
|
|||||||
readonly uri: Uri;
|
readonly uri: Uri;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event fired when there are no more references to the `WebviewEditorCustomDocument`.
|
* Event fired when there are no more references to the `CustomDocument`.
|
||||||
*/
|
*/
|
||||||
readonly onDidDispose: Event<void>;
|
readonly onDidDispose: Event<void>;
|
||||||
|
|
||||||
@@ -1313,7 +1313,7 @@ declare module 'vscode' {
|
|||||||
/**
|
/**
|
||||||
* Provider for webview editors that use a custom data model.
|
* Provider for webview editors that use a custom data model.
|
||||||
*
|
*
|
||||||
* Custom webview editors use [`WebviewEditorCustomDocument`](#WebviewEditorCustomDocument) as their data model.
|
* Custom webview editors use [`CustomDocument`](#CustomDocument) as their data model.
|
||||||
* This gives extensions full control over actions such as edit, save, and backup.
|
* This gives extensions full control over actions such as edit, save, and backup.
|
||||||
*
|
*
|
||||||
* You should use custom text based editors when dealing with binary files or more complex scenarios. For simple text
|
* You should use custom text based editors when dealing with binary files or more complex scenarios. For simple text
|
||||||
@@ -1321,24 +1321,26 @@ declare module 'vscode' {
|
|||||||
*/
|
*/
|
||||||
export interface CustomEditorProvider {
|
export interface CustomEditorProvider {
|
||||||
/**
|
/**
|
||||||
* Create the model for a given
|
* Resolve the model for a given resource.
|
||||||
*
|
*
|
||||||
* @param document Resource being resolved.
|
* @param document Document to resolve.
|
||||||
|
*
|
||||||
|
* @return The capabilities of the resolved document.
|
||||||
*/
|
*/
|
||||||
resolveCustomDocument(document: CustomDocument): Thenable<CustomEditorCapabilities>;
|
resolveCustomDocument(document: CustomDocument): Thenable<CustomEditorCapabilities>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a webview editor for a given resource.
|
* Resolve a webview editor for a given resource.
|
||||||
*
|
*
|
||||||
* To resolve a webview editor, a provider must fill in its initial html content and hook up all
|
* To resolve a webview editor, the provider must fill in its initial html content and hook up all
|
||||||
* the event listeners it is interested it. The provider should also take ownership of the passed in `WebviewPanel`.
|
* the event listeners it is interested it. The provider should also take ownership of the passed in `WebviewPanel`.
|
||||||
*
|
*
|
||||||
* @param document Document for resource being resolved.
|
* @param document Document for the resource being resolved.
|
||||||
* @param webview Webview being resolved. The provider should take ownership of this webview.
|
* @param webviewPanel Webview to resolve. The provider should take ownership of this webview.
|
||||||
*
|
*
|
||||||
* @return Thenable indicating that the webview editor has been resolved.
|
* @return Thenable indicating that the webview editor has been resolved.
|
||||||
*/
|
*/
|
||||||
resolveCustomEditor(document: CustomDocument, webview: WebviewPanel): Thenable<void>;
|
resolveCustomEditor(document: CustomDocument, webviewPanel: WebviewPanel): Thenable<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1349,7 +1351,7 @@ declare module 'vscode' {
|
|||||||
* undo and backup. The provider is responsible for synchronizing text changes between the webview and the `TextDocument`.
|
* undo and backup. The provider is responsible for synchronizing text changes between the webview and the `TextDocument`.
|
||||||
*
|
*
|
||||||
* You should use text based webview editors when dealing with text based file formats, such as `xml` or `json`.
|
* You should use text based webview editors when dealing with text based file formats, such as `xml` or `json`.
|
||||||
* For binary files or more specialized use cases, see [WebviewCustomEditorProvider](#WebviewCustomEditorProvider).
|
* For binary files or more specialized use cases, see [CustomEditorProvider](#CustomEditorProvider).
|
||||||
*/
|
*/
|
||||||
export interface CustomTextEditorProvider {
|
export interface CustomTextEditorProvider {
|
||||||
/**
|
/**
|
||||||
@@ -1359,11 +1361,11 @@ declare module 'vscode' {
|
|||||||
* the event listeners it is interested it. The provider should also take ownership of the passed in `WebviewPanel`.
|
* the event listeners it is interested it. The provider should also take ownership of the passed in `WebviewPanel`.
|
||||||
*
|
*
|
||||||
* @param document Resource being resolved.
|
* @param document Resource being resolved.
|
||||||
* @param webview Webview being resolved. The provider should take ownership of this webview.
|
* @param webviewPanel Webview to resolve. The provider should take ownership of this webview.
|
||||||
*
|
*
|
||||||
* @return Thenable indicating that the webview editor has been resolved.
|
* @return Thenable indicating that the webview editor has been resolved.
|
||||||
*/
|
*/
|
||||||
resolveCustomTextEditor(document: TextDocument, webview: WebviewPanel): Thenable<void>;
|
resolveCustomTextEditor(document: TextDocument, webviewPanel: WebviewPanel): Thenable<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace window {
|
namespace window {
|
||||||
@@ -1680,9 +1682,10 @@ declare module 'vscode' {
|
|||||||
*
|
*
|
||||||
* The documentation is shown in the code actions menu if either:
|
* The documentation is shown in the code actions menu if either:
|
||||||
*
|
*
|
||||||
* - Code actions of `kind` are requested by VS Code. Note that in this case, we always pick the most specific
|
* - Code actions of `kind` are requested by VS Code. In this case, VS Code will show the documentation that
|
||||||
* documentation. For example, if documentation for both `Refactor` and `RefactorExtract` is provided, and we
|
* most closely matches the requested code action kind. For example, if a provider has documentation for
|
||||||
* request code actions for `RefactorExtract`, we prefer the more specific documentation for `RefactorExtract`.
|
* both `Refactor` and `RefactorExtract`, when the user requests code actions for `RefactorExtract`,
|
||||||
|
* VS Code will use the documentation for `RefactorExtract` intead of the documentation for `Refactor`.
|
||||||
*
|
*
|
||||||
* - Any code actions of `kind` are returned by the provider.
|
* - Any code actions of `kind` are returned by the provider.
|
||||||
*/
|
*/
|
||||||
@@ -1703,7 +1706,10 @@ declare module 'vscode' {
|
|||||||
*/
|
*/
|
||||||
export interface OpenDialogOptions {
|
export interface OpenDialogOptions {
|
||||||
/**
|
/**
|
||||||
* Dialog title
|
* Dialog title.
|
||||||
|
*
|
||||||
|
* Depending on the underlying operating system this parameter might be ignored, since some
|
||||||
|
* systems do not present title on open dialogs.
|
||||||
*/
|
*/
|
||||||
title?: string;
|
title?: string;
|
||||||
}
|
}
|
||||||
@@ -1713,7 +1719,10 @@ declare module 'vscode' {
|
|||||||
*/
|
*/
|
||||||
export interface SaveDialogOptions {
|
export interface SaveDialogOptions {
|
||||||
/**
|
/**
|
||||||
* Dialog title
|
* Dialog title.
|
||||||
|
*
|
||||||
|
* Depending on the underlying operating system this parameter might be ignored, since some
|
||||||
|
* systems do not present title on save dialogs.
|
||||||
*/
|
*/
|
||||||
title?: string;
|
title?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export class MainThreadAuthenticationProvider {
|
|||||||
return {
|
return {
|
||||||
id: session.id,
|
id: session.id,
|
||||||
accountName: session.accountName,
|
accountName: session.accountName,
|
||||||
accessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id)
|
getAccessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ export class MainThreadAuthenticationProvider {
|
|||||||
return {
|
return {
|
||||||
id: session.id,
|
id: session.id,
|
||||||
accountName: session.accountName,
|
accountName: session.accountName,
|
||||||
accessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id)
|
getAccessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -75,48 +75,52 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
|
|||||||
async $getSessionsPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean> {
|
async $getSessionsPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean> {
|
||||||
const alwaysAllow = this.storageService.get(`${extensionId}-${providerId}`, StorageScope.GLOBAL);
|
const alwaysAllow = this.storageService.get(`${extensionId}-${providerId}`, StorageScope.GLOBAL);
|
||||||
if (alwaysAllow) {
|
if (alwaysAllow) {
|
||||||
return true;
|
return alwaysAllow === 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
const { choice } = await this.dialogService.show(
|
const { choice, checkboxChecked } = await this.dialogService.show(
|
||||||
Severity.Info,
|
Severity.Info,
|
||||||
nls.localize('confirmAuthenticationAccess', "The extension '{0}' is trying to access authentication information from {1}.", extensionName, providerName),
|
nls.localize('confirmAuthenticationAccess', "The extension '{0}' is trying to access authentication information from {1}.", extensionName, providerName),
|
||||||
[nls.localize('cancel', "Cancel"), nls.localize('allow', "Allow"), nls.localize('alwaysAllow', "Always Allow"),],
|
[nls.localize('cancel', "Cancel"), nls.localize('allow', "Allow")],
|
||||||
{ cancelId: 0 }
|
{
|
||||||
|
cancelId: 0,
|
||||||
|
checkbox: {
|
||||||
|
label: nls.localize('neverAgain', "Don't Show Again")
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
switch (choice) {
|
const allow = choice === 1;
|
||||||
case 1/** Allow */:
|
if (checkboxChecked) {
|
||||||
return true;
|
this.storageService.store(`${extensionId}-${providerId}`, allow ? 'true' : 'false', StorageScope.GLOBAL);
|
||||||
case 2 /** Always Allow */:
|
|
||||||
this.storageService.store(`${extensionId}-${providerId}`, 'true', StorageScope.GLOBAL);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return allow;
|
||||||
}
|
}
|
||||||
|
|
||||||
async $loginPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean> {
|
async $loginPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise<boolean> {
|
||||||
const alwaysAllow = this.storageService.get(`${extensionId}-${providerId}`, StorageScope.GLOBAL);
|
const alwaysAllow = this.storageService.get(`${extensionId}-${providerId}`, StorageScope.GLOBAL);
|
||||||
if (alwaysAllow) {
|
if (alwaysAllow) {
|
||||||
return true;
|
return alwaysAllow === 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
const { choice } = await this.dialogService.show(
|
const { choice, checkboxChecked } = await this.dialogService.show(
|
||||||
Severity.Info,
|
Severity.Info,
|
||||||
nls.localize('confirmLogin', "The extension '{0}' wants to sign in using {1}.", extensionName, providerName),
|
nls.localize('confirmLogin', "The extension '{0}' wants to sign in using {1}.", extensionName, providerName),
|
||||||
[nls.localize('cancel', "Cancel"), nls.localize('continue', "Continue"), nls.localize('neverAgain', "Don't Show Again")],
|
[nls.localize('cancel', "Cancel"), nls.localize('continue', "Continue")],
|
||||||
{ cancelId: 0 }
|
{
|
||||||
|
cancelId: 0,
|
||||||
|
checkbox: {
|
||||||
|
label: nls.localize('neverAgain', "Don't Show Again")
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
switch (choice) {
|
const allow = choice === 1;
|
||||||
case 1/** Allow */:
|
if (checkboxChecked) {
|
||||||
return true;
|
this.storageService.store(`${extensionId}-${providerId}`, allow ? 'true' : 'false', StorageScope.GLOBAL);
|
||||||
case 2 /** Always Allow */:
|
|
||||||
this.storageService.store(`${extensionId}-${providerId}`, 'true', StorageScope.GLOBAL);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return allow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
|||||||
this._register(_webviewWorkbenchService.registerResolver({
|
this._register(_webviewWorkbenchService.registerResolver({
|
||||||
canResolve: (webview: WebviewInput) => {
|
canResolve: (webview: WebviewInput) => {
|
||||||
if (webview instanceof CustomEditorInput) {
|
if (webview instanceof CustomEditorInput) {
|
||||||
extensionService.activateByEvent(`onWebviewEditor:${webview.viewType}`);
|
extensionService.activateByEvent(`onCustomEditor:${webview.viewType}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -624,7 +624,7 @@ export interface ExtHostWebviewsShape {
|
|||||||
$onSave(resource: UriComponents, viewType: string): Promise<void>;
|
$onSave(resource: UriComponents, viewType: string): Promise<void>;
|
||||||
$onSaveAs(resource: UriComponents, viewType: string, targetResource: UriComponents): Promise<void>;
|
$onSaveAs(resource: UriComponents, viewType: string, targetResource: UriComponents): Promise<void>;
|
||||||
|
|
||||||
$backup(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<boolean>;
|
$backup(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MainThreadUrlsShape extends IDisposable {
|
export interface MainThreadUrlsShape extends IDisposable {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export class AuthenticationProviderWrapper implements vscode.AuthenticationProvi
|
|||||||
id: session.id,
|
id: session.id,
|
||||||
accountName: session.accountName,
|
accountName: session.accountName,
|
||||||
scopes: session.scopes,
|
scopes: session.scopes,
|
||||||
accessToken: async () => {
|
getAccessToken: async () => {
|
||||||
const isAllowed = await this._proxy.$getSessionsPrompt(
|
const isAllowed = await this._proxy.$getSessionsPrompt(
|
||||||
this._provider.id,
|
this._provider.id,
|
||||||
this.displayName,
|
this.displayName,
|
||||||
@@ -45,7 +45,7 @@ export class AuthenticationProviderWrapper implements vscode.AuthenticationProvi
|
|||||||
throw new Error('User did not consent to token access.');
|
throw new Error('User did not consent to token access.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return session.accessToken();
|
return session.getAccessToken();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -60,7 +60,7 @@ export class AuthenticationProviderWrapper implements vscode.AuthenticationProvi
|
|||||||
return this._provider.login(scopes);
|
return this._provider.login(scopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
logout(sessionId: string): Promise<void> {
|
logout(sessionId: string): Thenable<void> {
|
||||||
return this._provider.logout(sessionId);
|
return this._provider.logout(sessionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
|
|||||||
const sessions = await authProvider.getSessions();
|
const sessions = await authProvider.getSessions();
|
||||||
const session = sessions.find(session => session.id === sessionId);
|
const session = sessions.find(session => session.id === sessionId);
|
||||||
if (session) {
|
if (session) {
|
||||||
return session.accessToken();
|
return session.getAccessToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`Unable to find session with id: ${sessionId}`);
|
throw new Error(`Unable to find session with id: ${sessionId}`);
|
||||||
|
|||||||
@@ -71,11 +71,17 @@ export class ExtHostTimeline implements IExtHostTimeline {
|
|||||||
scheme: scheme,
|
scheme: scheme,
|
||||||
onDidChange: undefined,
|
onDidChange: undefined,
|
||||||
async provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: { cacheResults?: boolean }) {
|
async provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: { cacheResults?: boolean }) {
|
||||||
timelineDisposables.clear();
|
|
||||||
|
|
||||||
// For now, only allow the caching of a single Uri
|
// For now, only allow the caching of a single Uri
|
||||||
if (internalOptions?.cacheResults && !itemsBySourceByUriMap.has(getUriKey(uri))) {
|
if (internalOptions?.cacheResults) {
|
||||||
itemsBySourceByUriMap.clear();
|
if (options.cursor === undefined) {
|
||||||
|
timelineDisposables.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!itemsBySourceByUriMap.has(getUriKey(uri))) {
|
||||||
|
itemsBySourceByUriMap.clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timelineDisposables.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await provider.provideTimeline(uri, options, token);
|
const result = await provider.provideTimeline(uri, options, token);
|
||||||
|
|||||||
@@ -247,143 +247,160 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa
|
|||||||
|
|
||||||
type EditType = unknown;
|
type EditType = unknown;
|
||||||
|
|
||||||
class WebviewEditorCustomDocument extends Disposable implements vscode.CustomDocument {
|
class CustomDocument extends Disposable implements vscode.CustomDocument {
|
||||||
private _currentEditIndex: number = -1;
|
|
||||||
private _savePoint: number = -1;
|
|
||||||
private readonly _edits: Array<EditType> = [];
|
|
||||||
|
|
||||||
public userData: unknown;
|
public static create(proxy: MainThreadWebviewsShape, viewType: string, uri: vscode.Uri) {
|
||||||
|
return Object.seal(new CustomDocument(proxy, viewType, uri));
|
||||||
public _capabilities?: vscode.CustomEditorCapabilities = undefined;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private readonly _proxy: MainThreadWebviewsShape,
|
|
||||||
public readonly viewType: string,
|
|
||||||
public readonly uri: vscode.Uri,
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_setCapabilities(capabilities: vscode.CustomEditorCapabilities) {
|
// Explicitly initialize all properties as we seal the object after creation!
|
||||||
if (this._capabilities) {
|
|
||||||
throw new Error('Capabilities already provided');
|
|
||||||
}
|
|
||||||
|
|
||||||
this._capabilities = capabilities;
|
#currentEditIndex: number = -1;
|
||||||
capabilities.editing?.onDidEdit(edit => {
|
#savePoint: number = -1;
|
||||||
this.pushEdit(edit, this);
|
readonly #edits: Array<EditType> = [];
|
||||||
});
|
|
||||||
|
readonly #proxy: MainThreadWebviewsShape;
|
||||||
|
readonly #viewType: string;
|
||||||
|
readonly #uri: vscode.Uri;
|
||||||
|
|
||||||
|
#capabilities: vscode.CustomEditorCapabilities | undefined = undefined;
|
||||||
|
|
||||||
|
private constructor(proxy: MainThreadWebviewsShape, viewType: string, uri: vscode.Uri) {
|
||||||
|
super();
|
||||||
|
this.#proxy = proxy;
|
||||||
|
this.#viewType = viewType;
|
||||||
|
this.#uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.#onDidDispose.fire();
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region Public API
|
//#region Public API
|
||||||
|
|
||||||
#_onDidDispose = this._register(new Emitter<void>());
|
public get viewType(): string { return this.#viewType; }
|
||||||
public readonly onDidDispose = this.#_onDidDispose.event;
|
|
||||||
|
public get uri(): vscode.Uri { return this.#uri; }
|
||||||
|
|
||||||
|
#onDidDispose = this._register(new Emitter<void>());
|
||||||
|
public readonly onDidDispose = this.#onDidDispose.event;
|
||||||
|
|
||||||
|
public userData: unknown = undefined;
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
dispose() {
|
//#region Internal
|
||||||
this.#_onDidDispose.fire();
|
|
||||||
super.dispose();
|
/** @internal*/ _setCapabilities(capabilities: vscode.CustomEditorCapabilities) {
|
||||||
|
if (this.#capabilities) {
|
||||||
|
throw new Error('Capabilities already provided');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#capabilities = capabilities;
|
||||||
|
capabilities.editing?.onDidEdit(edit => {
|
||||||
|
this.pushEdit(edit);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private pushEdit(edit: EditType, trigger: any) {
|
/** @internal*/ _revert() {
|
||||||
this.spliceEdits(edit);
|
|
||||||
|
|
||||||
this._currentEditIndex = this._edits.length - 1;
|
|
||||||
this.updateState();
|
|
||||||
// this._onApplyEdit.fire({ edits: [edit], trigger });
|
|
||||||
}
|
|
||||||
|
|
||||||
private updateState() {
|
|
||||||
const dirty = this._edits.length > 0 && this._savePoint !== this._currentEditIndex;
|
|
||||||
this._proxy.$onDidChangeCustomDocumentState(this.uri, this.viewType, { dirty });
|
|
||||||
}
|
|
||||||
|
|
||||||
private spliceEdits(editToInsert?: EditType) {
|
|
||||||
const start = this._currentEditIndex + 1;
|
|
||||||
const toRemove = this._edits.length - this._currentEditIndex;
|
|
||||||
|
|
||||||
editToInsert
|
|
||||||
? this._edits.splice(start, toRemove, editToInsert)
|
|
||||||
: this._edits.splice(start, toRemove);
|
|
||||||
}
|
|
||||||
|
|
||||||
revert() {
|
|
||||||
const editing = this.getEditingCapability();
|
const editing = this.getEditingCapability();
|
||||||
if (this._currentEditIndex === this._savePoint) {
|
if (this.#currentEditIndex === this.#savePoint) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._currentEditIndex >= this._savePoint) {
|
if (this.#currentEditIndex >= this.#savePoint) {
|
||||||
const editsToUndo = this._edits.slice(this._savePoint, this._currentEditIndex);
|
const editsToUndo = this.#edits.slice(this.#savePoint, this.#currentEditIndex);
|
||||||
editing.undoEdits(editsToUndo.reverse());
|
editing.undoEdits(editsToUndo.reverse());
|
||||||
} else if (this._currentEditIndex < this._savePoint) {
|
} else if (this.#currentEditIndex < this.#savePoint) {
|
||||||
const editsToRedo = this._edits.slice(this._currentEditIndex, this._savePoint);
|
const editsToRedo = this.#edits.slice(this.#currentEditIndex, this.#savePoint);
|
||||||
editing.applyEdits(editsToRedo);
|
editing.applyEdits(editsToRedo);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._currentEditIndex = this._savePoint;
|
this.#currentEditIndex = this.#savePoint;
|
||||||
this.spliceEdits();
|
this.spliceEdits();
|
||||||
|
|
||||||
this.updateState();
|
this.updateState();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
undo() {
|
/** @internal*/ _undo() {
|
||||||
const editing = this.getEditingCapability();
|
const editing = this.getEditingCapability();
|
||||||
if (this._currentEditIndex < 0) {
|
if (this.#currentEditIndex < 0) {
|
||||||
// nothing to undo
|
// nothing to undo
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const undoneEdit = this._edits[this._currentEditIndex];
|
const undoneEdit = this.#edits[this.#currentEditIndex];
|
||||||
--this._currentEditIndex;
|
--this.#currentEditIndex;
|
||||||
editing.undoEdits([undoneEdit]);
|
editing.undoEdits([undoneEdit]);
|
||||||
this.updateState();
|
this.updateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
redo() {
|
/** @internal*/ _redo() {
|
||||||
const editing = this.getEditingCapability();
|
const editing = this.getEditingCapability();
|
||||||
if (this._currentEditIndex >= this._edits.length - 1) {
|
if (this.#currentEditIndex >= this.#edits.length - 1) {
|
||||||
// nothing to redo
|
// nothing to redo
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
++this._currentEditIndex;
|
++this.#currentEditIndex;
|
||||||
const redoneEdit = this._edits[this._currentEditIndex];
|
const redoneEdit = this.#edits[this.#currentEditIndex];
|
||||||
editing.applyEdits([redoneEdit]);
|
editing.applyEdits([redoneEdit]);
|
||||||
this.updateState();
|
this.updateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
/** @internal*/ _save() {
|
||||||
return this.getEditingCapability().save();
|
return this.getEditingCapability().save();
|
||||||
}
|
}
|
||||||
|
|
||||||
saveAs(target: vscode.Uri) {
|
/** @internal*/ _saveAs(target: vscode.Uri) {
|
||||||
return this.getEditingCapability().saveAs(target);
|
return this.getEditingCapability().saveAs(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
backup(cancellation: CancellationToken) {
|
/** @internal*/ _backup(cancellation: CancellationToken) {
|
||||||
return this.getEditingCapability().backup(cancellation);
|
return this.getEditingCapability().backup(cancellation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
private pushEdit(edit: EditType) {
|
||||||
|
this.spliceEdits(edit);
|
||||||
|
|
||||||
|
this.#currentEditIndex = this.#edits.length - 1;
|
||||||
|
this.updateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateState() {
|
||||||
|
const dirty = this.#edits.length > 0 && this.#savePoint !== this.#currentEditIndex;
|
||||||
|
this.#proxy.$onDidChangeCustomDocumentState(this.uri, this.viewType, { dirty });
|
||||||
|
}
|
||||||
|
|
||||||
|
private spliceEdits(editToInsert?: EditType) {
|
||||||
|
const start = this.#currentEditIndex + 1;
|
||||||
|
const toRemove = this.#edits.length - this.#currentEditIndex;
|
||||||
|
|
||||||
|
editToInsert
|
||||||
|
? this.#edits.splice(start, toRemove, editToInsert)
|
||||||
|
: this.#edits.splice(start, toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
private getEditingCapability(): vscode.CustomEditorEditingCapability {
|
private getEditingCapability(): vscode.CustomEditorEditingCapability {
|
||||||
if (!this._capabilities?.editing) {
|
if (!this.#capabilities?.editing) {
|
||||||
throw new Error('Document is not editable');
|
throw new Error('Document is not editable');
|
||||||
}
|
}
|
||||||
return this._capabilities.editing;
|
return this.#capabilities.editing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WebviewDocumentStore {
|
class WebviewDocumentStore {
|
||||||
private readonly _documents = new Map<string, WebviewEditorCustomDocument>();
|
private readonly _documents = new Map<string, CustomDocument>();
|
||||||
|
|
||||||
public get(viewType: string, resource: vscode.Uri): WebviewEditorCustomDocument | undefined {
|
public get(viewType: string, resource: vscode.Uri): CustomDocument | undefined {
|
||||||
return this._documents.get(this.key(viewType, resource));
|
return this._documents.get(this.key(viewType, resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
public add(document: WebviewEditorCustomDocument) {
|
public add(document: CustomDocument) {
|
||||||
const key = this.key(document.viewType, document.uri);
|
const key = this.key(document.viewType, document.uri);
|
||||||
if (this._documents.has(key)) {
|
if (this._documents.has(key)) {
|
||||||
throw new Error(`Document already exists for viewType:${document.viewType} resource:${document.uri}`);
|
throw new Error(`Document already exists for viewType:${document.viewType} resource:${document.uri}`);
|
||||||
@@ -391,7 +408,7 @@ class WebviewDocumentStore {
|
|||||||
this._documents.set(key, document);
|
this._documents.set(key, document);
|
||||||
}
|
}
|
||||||
|
|
||||||
public delete(document: WebviewEditorCustomDocument) {
|
public delete(document: CustomDocument) {
|
||||||
const key = this.key(document.viewType, document.uri);
|
const key = this.key(document.viewType, document.uri);
|
||||||
this._documents.delete(key);
|
this._documents.delete(key);
|
||||||
}
|
}
|
||||||
@@ -622,7 +639,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const revivedResource = URI.revive(resource);
|
const revivedResource = URI.revive(resource);
|
||||||
const document = Object.seal(new WebviewEditorCustomDocument(this._proxy, viewType, revivedResource));
|
const document = CustomDocument.create(this._proxy, viewType, revivedResource);
|
||||||
const capabilities = await entry.provider.resolveCustomDocument(document);
|
const capabilities = await entry.provider.resolveCustomDocument(document);
|
||||||
document._setCapabilities(capabilities);
|
document._setCapabilities(capabilities);
|
||||||
this._documents.add(document);
|
this._documents.add(document);
|
||||||
@@ -687,39 +704,39 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
|||||||
|
|
||||||
async $undo(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
async $undo(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
||||||
const document = this.getDocument(viewType, resourceComponents);
|
const document = this.getDocument(viewType, resourceComponents);
|
||||||
document.undo();
|
document._undo();
|
||||||
}
|
}
|
||||||
|
|
||||||
async $redo(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
async $redo(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
||||||
const document = this.getDocument(viewType, resourceComponents);
|
const document = this.getDocument(viewType, resourceComponents);
|
||||||
document.redo();
|
document._redo();
|
||||||
}
|
}
|
||||||
|
|
||||||
async $revert(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
async $revert(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
||||||
const document = this.getDocument(viewType, resourceComponents);
|
const document = this.getDocument(viewType, resourceComponents);
|
||||||
document.revert();
|
document._revert();
|
||||||
}
|
}
|
||||||
|
|
||||||
async $onSave(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
async $onSave(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
||||||
const document = this.getDocument(viewType, resourceComponents);
|
const document = this.getDocument(viewType, resourceComponents);
|
||||||
document.save();
|
document._save();
|
||||||
}
|
}
|
||||||
|
|
||||||
async $onSaveAs(resourceComponents: UriComponents, viewType: string, targetResource: UriComponents): Promise<void> {
|
async $onSaveAs(resourceComponents: UriComponents, viewType: string, targetResource: UriComponents): Promise<void> {
|
||||||
const document = this.getDocument(viewType, resourceComponents);
|
const document = this.getDocument(viewType, resourceComponents);
|
||||||
return document.saveAs(URI.revive(targetResource));
|
return document._saveAs(URI.revive(targetResource));
|
||||||
}
|
}
|
||||||
|
|
||||||
async $backup(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise<boolean> {
|
async $backup(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise<void> {
|
||||||
const document = this.getDocument(viewType, resourceComponents);
|
const document = this.getDocument(viewType, resourceComponents);
|
||||||
return document.backup(cancellation);
|
return document._backup(cancellation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewEditor | undefined {
|
private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewEditor | undefined {
|
||||||
return this._webviewPanels.get(handle);
|
return this._webviewPanels.get(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDocument(viewType: string, resource: UriComponents): WebviewEditorCustomDocument {
|
private getDocument(viewType: string, resource: UriComponents): CustomDocument {
|
||||||
const document = this._documents.get(viewType, URI.revive(resource));
|
const document = this._documents.get(viewType, URI.revive(resource));
|
||||||
if (!document) {
|
if (!document) {
|
||||||
throw new Error('No webview editor custom document found');
|
throw new Error('No webview editor custom document found');
|
||||||
|
|||||||
@@ -25,9 +25,10 @@ import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/commo
|
|||||||
import { SideBarVisibleContext } from 'vs/workbench/common/viewlet';
|
import { SideBarVisibleContext } from 'vs/workbench/common/viewlet';
|
||||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
import { IViewDescriptorService, IViewContainersRegistry, Extensions as ViewContainerExtensions, IViewsService, FocusedViewContext, ViewContainerLocation } from 'vs/workbench/common/views';
|
import { IViewDescriptorService, IViewContainersRegistry, Extensions as ViewContainerExtensions, IViewsService, FocusedViewContext, ViewContainerLocation } from 'vs/workbench/common/views';
|
||||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||||
|
import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService';
|
||||||
|
|
||||||
const registry = Registry.as<IWorkbenchActionRegistry>(WorkbenchExtensions.WorkbenchActions);
|
const registry = Registry.as<IWorkbenchActionRegistry>(WorkbenchExtensions.WorkbenchActions);
|
||||||
const viewCategory = nls.localize('view', "View");
|
const viewCategory = nls.localize('view', "View");
|
||||||
@@ -534,6 +535,7 @@ export class MoveFocusedViewAction extends Action {
|
|||||||
@IQuickInputService private quickInputService: IQuickInputService,
|
@IQuickInputService private quickInputService: IQuickInputService,
|
||||||
@IContextKeyService private contextKeyService: IContextKeyService,
|
@IContextKeyService private contextKeyService: IContextKeyService,
|
||||||
@INotificationService private notificationService: INotificationService,
|
@INotificationService private notificationService: INotificationService,
|
||||||
|
@IActivityBarService private activityBarService: IActivityBarService,
|
||||||
@IViewletService private viewletService: IViewletService
|
@IViewletService private viewletService: IViewletService
|
||||||
) {
|
) {
|
||||||
super(id, label);
|
super(id, label);
|
||||||
@@ -542,58 +544,64 @@ export class MoveFocusedViewAction extends Action {
|
|||||||
run(): Promise<void> {
|
run(): Promise<void> {
|
||||||
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
||||||
|
|
||||||
const focusedView = FocusedViewContext.getValue(this.contextKeyService);
|
const focusedViewId = FocusedViewContext.getValue(this.contextKeyService);
|
||||||
|
|
||||||
if (focusedView === undefined || focusedView.trim() === '') {
|
if (focusedViewId === undefined || focusedViewId.trim() === '') {
|
||||||
this.notificationService.error(nls.localize('moveFocusedView.error.noFocusedView', "There is no view currently focused."));
|
this.notificationService.error(nls.localize('moveFocusedView.error.noFocusedView', "There is no view currently focused."));
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptor(focusedView);
|
const viewDescriptor = this.viewDescriptorService.getViewDescriptor(focusedViewId);
|
||||||
if (!viewDescriptor || !viewDescriptor.canMoveView) {
|
if (!viewDescriptor || !viewDescriptor.canMoveView) {
|
||||||
this.notificationService.error(nls.localize('moveFocusedView.error.nonMovableView', "The currently focused view is not movable {0}.", focusedView));
|
this.notificationService.error(nls.localize('moveFocusedView.error.nonMovableView', "The currently focused view is not movable."));
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const quickPick = this.quickInputService.createQuickPick();
|
const quickPick = this.quickInputService.createQuickPick();
|
||||||
quickPick.placeholder = nls.localize('moveFocusedView.selectDestination', "Select a destination area for the view...");
|
quickPick.placeholder = nls.localize('moveFocusedView.selectDestination', "Select a Destination for the View");
|
||||||
quickPick.autoFocusOnList = true;
|
|
||||||
|
|
||||||
quickPick.items = [
|
const pinnedViewlets = this.activityBarService.getPinnedViewletIds();
|
||||||
{
|
const items: Array<IQuickPickItem | IQuickPickSeparator> = this.viewletService.getViewlets()
|
||||||
id: 'sidebar',
|
.filter(viewlet => {
|
||||||
label: nls.localize('sidebar', "Sidebar")
|
if (viewlet.id === this.viewDescriptorService.getViewContainer(focusedViewId)!.id) {
|
||||||
},
|
return false;
|
||||||
{
|
}
|
||||||
id: 'panel',
|
|
||||||
|
return !viewContainerRegistry.get(viewlet.id)!.rejectAddedViews && pinnedViewlets.indexOf(viewlet.id) !== -1;
|
||||||
|
})
|
||||||
|
.map(viewlet => {
|
||||||
|
return {
|
||||||
|
id: viewlet.id,
|
||||||
|
label: viewlet.name,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.viewDescriptorService.getViewLocation(focusedViewId) !== ViewContainerLocation.Panel) {
|
||||||
|
items.unshift({
|
||||||
|
type: 'separator',
|
||||||
|
label: nls.localize('sidebar', "Side Bar")
|
||||||
|
});
|
||||||
|
items.push({
|
||||||
|
type: 'separator',
|
||||||
label: nls.localize('panel', "Panel")
|
label: nls.localize('panel', "Panel")
|
||||||
}
|
});
|
||||||
];
|
items.push({
|
||||||
|
id: '_.panel.newcontainer',
|
||||||
|
label: nls.localize('moveFocusedView.newContainerInPanel', "New Container in Panel"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
quickPick.items = items;
|
||||||
|
|
||||||
quickPick.onDidAccept(() => {
|
quickPick.onDidAccept(() => {
|
||||||
const destination = quickPick.selectedItems[0];
|
const destination = quickPick.selectedItems[0];
|
||||||
|
|
||||||
if (destination.id === 'panel') {
|
if (destination.id === '_.panel.newcontainer') {
|
||||||
quickPick.hide();
|
|
||||||
this.viewDescriptorService.moveViewToLocation(viewDescriptor!, ViewContainerLocation.Panel);
|
this.viewDescriptorService.moveViewToLocation(viewDescriptor!, ViewContainerLocation.Panel);
|
||||||
this.viewsService.openView(focusedView, true);
|
this.viewsService.openView(focusedViewId, true);
|
||||||
|
|
||||||
return;
|
|
||||||
} else if (destination.id === 'sidebar') {
|
|
||||||
quickPick.placeholder = nls.localize('moveFocusedView.selectDestinationContainer', "Select a destination view group...");
|
|
||||||
quickPick.items = this.viewletService.getViewlets().map(viewlet => {
|
|
||||||
return {
|
|
||||||
id: viewlet.id,
|
|
||||||
label: viewlet.name
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
} else if (destination.id) {
|
} else if (destination.id) {
|
||||||
quickPick.hide();
|
|
||||||
this.viewDescriptorService.moveViewsToContainer([viewDescriptor], viewContainerRegistry.get(destination.id)!);
|
this.viewDescriptorService.moveViewsToContainer([viewDescriptor], viewContainerRegistry.get(destination.id)!);
|
||||||
this.viewsService.openView(focusedView, true);
|
this.viewsService.openView(focusedViewId, true);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quickPick.hide();
|
quickPick.hide();
|
||||||
@@ -605,7 +613,7 @@ export class MoveFocusedViewAction extends Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveFocusedViewAction, MoveFocusedViewAction.ID, MoveFocusedViewAction.LABEL), 'View: Move Focused View', viewCategory);
|
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveFocusedViewAction, MoveFocusedViewAction.ID, MoveFocusedViewAction.LABEL), 'View: Move Focused View', viewCategory, FocusedViewContext.notEqualsTo(''));
|
||||||
|
|
||||||
|
|
||||||
// --- Resize View
|
// --- Resize View
|
||||||
|
|||||||
@@ -27,6 +27,10 @@
|
|||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.monaco-workbench .activitybar > .content > .composite-bar-excess {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.monaco-workbench .activitybar .menubar {
|
.monaco-workbench .activitybar .menubar {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
|||||||
@@ -17,13 +17,14 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
|||||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||||
import { Widget } from 'vs/base/browser/ui/widget';
|
import { Widget } from 'vs/base/browser/ui/widget';
|
||||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||||
import { LocalSelectionTransfer } from 'vs/workbench/browser/dnd';
|
import { LocalSelectionTransfer, DragAndDropObserver } from 'vs/workbench/browser/dnd';
|
||||||
import { ITheme } from 'vs/platform/theme/common/themeService';
|
import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
import { Emitter } from 'vs/base/common/event';
|
import { Emitter } from 'vs/base/common/event';
|
||||||
import { DraggedViewIdentifier } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
import { DraggedViewIdentifier } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||||
import { Registry } from 'vs/platform/registry/common/platform';
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
|
import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
|
||||||
import { ICompositeDragAndDrop, CompositeDragAndDropData } from 'vs/base/parts/composite/browser/compositeDnd';
|
import { ICompositeDragAndDrop, CompositeDragAndDropData } from 'vs/base/parts/composite/browser/compositeDnd';
|
||||||
|
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
|
||||||
|
|
||||||
export interface ICompositeBarItem {
|
export interface ICompositeBarItem {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -38,7 +39,7 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
|||||||
constructor(
|
constructor(
|
||||||
private viewDescriptorService: IViewDescriptorService,
|
private viewDescriptorService: IViewDescriptorService,
|
||||||
private targetContainerLocation: ViewContainerLocation,
|
private targetContainerLocation: ViewContainerLocation,
|
||||||
private openComposite: (id: string, focus?: boolean) => void,
|
private openComposite: (id: string, focus?: boolean) => Promise<IPaneComposite | undefined>,
|
||||||
private moveComposite: (from: string, to: string) => void,
|
private moveComposite: (from: string, to: string) => void,
|
||||||
private getVisibleCompositeIds: () => string[]
|
private getVisibleCompositeIds: () => string[]
|
||||||
) { }
|
) { }
|
||||||
@@ -52,9 +53,14 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
|||||||
if (targetCompositeId) {
|
if (targetCompositeId) {
|
||||||
if (currentLocation !== this.targetContainerLocation && this.targetContainerLocation !== ViewContainerLocation.Panel) {
|
if (currentLocation !== this.targetContainerLocation && this.targetContainerLocation !== ViewContainerLocation.Panel) {
|
||||||
const destinationContainer = viewContainerRegistry.get(targetCompositeId);
|
const destinationContainer = viewContainerRegistry.get(targetCompositeId);
|
||||||
if (destinationContainer) {
|
if (destinationContainer && !destinationContainer.rejectAddedViews) {
|
||||||
this.viewDescriptorService.moveViewsToContainer(this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors.filter(vd => vd.canMoveView), destinationContainer);
|
const viewsToMove = this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors.filter(vd => vd.canMoveView);
|
||||||
this.openComposite(targetCompositeId, true);
|
this.viewDescriptorService.moveViewsToContainer(viewsToMove, destinationContainer);
|
||||||
|
this.openComposite(targetCompositeId, true).then(composite => {
|
||||||
|
if (composite && viewsToMove.length === 1) {
|
||||||
|
composite.openView(viewsToMove[0].id, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.moveComposite(dragData.id, targetCompositeId);
|
this.moveComposite(dragData.id, targetCompositeId);
|
||||||
@@ -73,10 +79,14 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
|||||||
if (viewDescriptor && viewDescriptor.canMoveView) {
|
if (viewDescriptor && viewDescriptor.canMoveView) {
|
||||||
if (targetCompositeId) {
|
if (targetCompositeId) {
|
||||||
const destinationContainer = viewContainerRegistry.get(targetCompositeId);
|
const destinationContainer = viewContainerRegistry.get(targetCompositeId);
|
||||||
if (destinationContainer) {
|
if (destinationContainer && !destinationContainer.rejectAddedViews) {
|
||||||
if (this.targetContainerLocation === ViewContainerLocation.Sidebar) {
|
if (this.targetContainerLocation === ViewContainerLocation.Sidebar) {
|
||||||
this.viewDescriptorService.moveViewsToContainer([viewDescriptor], destinationContainer);
|
this.viewDescriptorService.moveViewsToContainer([viewDescriptor], destinationContainer);
|
||||||
this.openComposite(targetCompositeId, true);
|
this.openComposite(targetCompositeId, true).then(composite => {
|
||||||
|
if (composite) {
|
||||||
|
composite.openView(viewDescriptor.id, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.viewDescriptorService.moveViewToLocation(viewDescriptor, this.targetContainerLocation);
|
this.viewDescriptorService.moveViewToLocation(viewDescriptor, this.targetContainerLocation);
|
||||||
this.moveComposite(this.viewDescriptorService.getViewContainer(viewDescriptor.id)!.id, targetCompositeId);
|
this.moveComposite(this.viewDescriptorService.getViewContainer(viewDescriptor.id)!.id, targetCompositeId);
|
||||||
@@ -91,13 +101,25 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
|||||||
this.moveComposite(newCompositeId, targetId);
|
this.moveComposite(newCompositeId, targetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.openComposite(newCompositeId, true);
|
this.openComposite(newCompositeId, true).then(composite => {
|
||||||
|
if (composite) {
|
||||||
|
composite.openView(viewDescriptor.id, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDragEnter(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent): boolean {
|
||||||
|
return this.canDrop(data, targetCompositeId);
|
||||||
|
}
|
||||||
|
|
||||||
onDragOver(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent): boolean {
|
onDragOver(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent): boolean {
|
||||||
|
return this.canDrop(data, targetCompositeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private canDrop(data: CompositeDragAndDropData, targetCompositeId: string | undefined): boolean {
|
||||||
const dragData = data.getData();
|
const dragData = data.getData();
|
||||||
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
||||||
|
|
||||||
@@ -134,6 +156,7 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
|||||||
if (this.targetContainerLocation === ViewContainerLocation.Sidebar) {
|
if (this.targetContainerLocation === ViewContainerLocation.Sidebar) {
|
||||||
const destinationContainer = viewContainerRegistry.get(targetCompositeId);
|
const destinationContainer = viewContainerRegistry.get(targetCompositeId);
|
||||||
return !!destinationContainer &&
|
return !!destinationContainer &&
|
||||||
|
!destinationContainer.rejectAddedViews &&
|
||||||
this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors.some(vd => vd.canMoveView);
|
this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors.some(vd => vd.canMoveView);
|
||||||
}
|
}
|
||||||
// ... from sidebar to the panel
|
// ... from sidebar to the panel
|
||||||
@@ -155,10 +178,9 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ... into a destination
|
// ... into a destination
|
||||||
return true;
|
const destinationContainer = viewContainerRegistry.get(targetCompositeId);
|
||||||
|
return !!destinationContainer && !destinationContainer.rejectAddedViews;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +222,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
|||||||
constructor(
|
constructor(
|
||||||
items: ICompositeBarItem[],
|
items: ICompositeBarItem[],
|
||||||
private options: ICompositeBarOptions,
|
private options: ICompositeBarOptions,
|
||||||
|
@IThemeService private readonly themeService: IThemeService,
|
||||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||||
@IContextMenuService private readonly contextMenuService: IContextMenuService
|
@IContextMenuService private readonly contextMenuService: IContextMenuService
|
||||||
) {
|
) {
|
||||||
@@ -228,6 +251,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
|||||||
|
|
||||||
create(parent: HTMLElement): HTMLElement {
|
create(parent: HTMLElement): HTMLElement {
|
||||||
const actionBarDiv = parent.appendChild($('.composite-bar'));
|
const actionBarDiv = parent.appendChild($('.composite-bar'));
|
||||||
|
const excessDiv = parent.appendChild($('.composite-bar-excess'));
|
||||||
|
|
||||||
this.compositeSwitcherBar = this._register(new ActionBar(actionBarDiv, {
|
this.compositeSwitcherBar = this._register(new ActionBar(actionBarDiv, {
|
||||||
actionViewItemProvider: (action: IAction) => {
|
actionViewItemProvider: (action: IAction) => {
|
||||||
@@ -254,58 +278,99 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
|||||||
this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, e => this.showContextMenu(e)));
|
this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, e => this.showContextMenu(e)));
|
||||||
|
|
||||||
// Allow to drop at the end to move composites to the end
|
// Allow to drop at the end to move composites to the end
|
||||||
this._register(addDisposableListener(parent, EventType.DROP, (e: DragEvent) => {
|
this._register(new DragAndDropObserver(excessDiv, {
|
||||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
onDragOver: (e: DragEvent) => {
|
||||||
EventHelper.stop(e, true);
|
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
||||||
|
EventHelper.stop(e, true);
|
||||||
|
|
||||||
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
const draggedCompositeId = data[0].id;
|
const draggedCompositeId = data[0].id;
|
||||||
this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype);
|
|
||||||
|
|
||||||
this.options.dndHandler.drop(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e);
|
// Check if drop is allowed
|
||||||
}
|
if (e.dataTransfer && !this.options.dndHandler.onDragOver(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e)) {
|
||||||
}
|
e.dataTransfer.dropEffect = 'none';
|
||||||
|
}
|
||||||
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
|
||||||
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
const draggedViewId = data[0].id;
|
|
||||||
this.compositeTransfer.clearData(DraggedViewIdentifier.prototype);
|
|
||||||
|
|
||||||
this.options.dndHandler.drop(new CompositeDragAndDropData('view', draggedViewId), undefined, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._register(addDisposableListener(parent, EventType.DRAG_OVER, (e: DragEvent) => {
|
|
||||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
|
||||||
EventHelper.stop(e, true);
|
|
||||||
|
|
||||||
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
const draggedCompositeId = data[0].id;
|
|
||||||
|
|
||||||
// Check if drop is allowed
|
|
||||||
if (e.dataTransfer && !this.options.dndHandler.onDragOver(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e)) {
|
|
||||||
e.dataTransfer.dropEffect = 'none';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||||
EventHelper.stop(e, true);
|
EventHelper.stop(e, true);
|
||||||
|
|
||||||
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
const draggedViewId = data[0].id;
|
const draggedViewId = data[0].id;
|
||||||
|
|
||||||
// Check if drop is allowed
|
// Check if drop is allowed
|
||||||
if (e.dataTransfer && !this.options.dndHandler.onDragOver(new CompositeDragAndDropData('view', draggedViewId), undefined, e)) {
|
if (e.dataTransfer && !this.options.dndHandler.onDragOver(new CompositeDragAndDropData('view', draggedViewId), undefined, e)) {
|
||||||
e.dataTransfer.dropEffect = 'none';
|
e.dataTransfer.dropEffect = 'none';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
onDragEnter: (e: DragEvent) => {
|
||||||
|
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
||||||
|
EventHelper.stop(e, true);
|
||||||
|
|
||||||
|
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
const draggedCompositeId = data[0].id;
|
||||||
|
|
||||||
|
// Check if drop is allowed
|
||||||
|
const validDropTarget = this.options.dndHandler.onDragEnter(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e);
|
||||||
|
this.updateFromDragging(excessDiv, validDropTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||||
|
EventHelper.stop(e, true);
|
||||||
|
|
||||||
|
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
const draggedViewId = data[0].id;
|
||||||
|
|
||||||
|
// Check if drop is allowed
|
||||||
|
const validDropTarget = this.options.dndHandler.onDragEnter(new CompositeDragAndDropData('view', draggedViewId), undefined, e);
|
||||||
|
this.updateFromDragging(excessDiv, validDropTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onDragLeave: (e: DragEvent) => {
|
||||||
|
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype) ||
|
||||||
|
this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||||
|
this.updateFromDragging(excessDiv, false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDragEnd: (e: DragEvent) => {
|
||||||
|
// no-op, will not be called
|
||||||
|
},
|
||||||
|
onDrop: (e: DragEvent) => {
|
||||||
|
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
||||||
|
EventHelper.stop(e, true);
|
||||||
|
|
||||||
|
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
const draggedCompositeId = data[0].id;
|
||||||
|
this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype);
|
||||||
|
|
||||||
|
this.options.dndHandler.drop(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e);
|
||||||
|
this.updateFromDragging(excessDiv, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||||
|
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
const draggedViewId = data[0].id;
|
||||||
|
this.compositeTransfer.clearData(DraggedViewIdentifier.prototype);
|
||||||
|
|
||||||
|
this.options.dndHandler.drop(new CompositeDragAndDropData('view', draggedViewId), undefined, e);
|
||||||
|
this.updateFromDragging(excessDiv, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return actionBarDiv;
|
return actionBarDiv;
|
||||||
@@ -410,6 +475,13 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateFromDragging(element: HTMLElement, isDragging: boolean): void {
|
||||||
|
const theme = this.themeService.getTheme();
|
||||||
|
const dragBackground = this.options.colors(theme).dragAndDropBackground;
|
||||||
|
|
||||||
|
element.style.backgroundColor = isDragging && dragBackground ? dragBackground.toString() : '';
|
||||||
|
}
|
||||||
|
|
||||||
private resetActiveComposite(compositeId: string) {
|
private resetActiveComposite(compositeId: string) {
|
||||||
const defaultCompositeId = this.options.getDefaultCompositeId();
|
const defaultCompositeId = this.options.getDefaultCompositeId();
|
||||||
|
|
||||||
|
|||||||
@@ -544,14 +544,16 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
|
|||||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
||||||
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
||||||
if (Array.isArray(data) && data[0].id !== this.activity.id) {
|
if (Array.isArray(data) && data[0].id !== this.activity.id) {
|
||||||
this.updateFromDragging(container, true);
|
const validDropTarget = this.dndHandler.onDragEnter(new CompositeDragAndDropData('composite', data[0].id), this.activity.id, e);
|
||||||
|
this.updateFromDragging(container, validDropTarget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||||
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
||||||
if (Array.isArray(data) && data[0].id !== this.activity.id) {
|
if (Array.isArray(data) && data[0].id !== this.activity.id) {
|
||||||
this.updateFromDragging(container, true);
|
const validDropTarget = this.dndHandler.onDragEnter(new CompositeDragAndDropData('view', data[0].id), this.activity.id, e);
|
||||||
|
this.updateFromDragging(container, validDropTarget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -616,6 +618,8 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
|
|||||||
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
const draggedViewId = data[0].id;
|
const draggedViewId = data[0].id;
|
||||||
|
this.updateFromDragging(container, false);
|
||||||
|
this.compositeTransfer.clearData(DraggedViewIdentifier.prototype);
|
||||||
|
|
||||||
this.dndHandler.drop(new CompositeDragAndDropData('view', draggedViewId), this.activity.id, e);
|
this.dndHandler.drop(new CompositeDragAndDropData('view', draggedViewId), this.activity.id, e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ class StateChange {
|
|||||||
encoding: boolean = false;
|
encoding: boolean = false;
|
||||||
EOL: boolean = false;
|
EOL: boolean = false;
|
||||||
tabFocusMode: boolean = false;
|
tabFocusMode: boolean = false;
|
||||||
|
columnSelectionMode: boolean = false;
|
||||||
screenReaderMode: boolean = false;
|
screenReaderMode: boolean = false;
|
||||||
metadata: boolean = false;
|
metadata: boolean = false;
|
||||||
|
|
||||||
@@ -157,6 +158,7 @@ class StateChange {
|
|||||||
this.encoding = this.encoding || other.encoding;
|
this.encoding = this.encoding || other.encoding;
|
||||||
this.EOL = this.EOL || other.EOL;
|
this.EOL = this.EOL || other.EOL;
|
||||||
this.tabFocusMode = this.tabFocusMode || other.tabFocusMode;
|
this.tabFocusMode = this.tabFocusMode || other.tabFocusMode;
|
||||||
|
this.columnSelectionMode = this.columnSelectionMode || other.columnSelectionMode;
|
||||||
this.screenReaderMode = this.screenReaderMode || other.screenReaderMode;
|
this.screenReaderMode = this.screenReaderMode || other.screenReaderMode;
|
||||||
this.metadata = this.metadata || other.metadata;
|
this.metadata = this.metadata || other.metadata;
|
||||||
}
|
}
|
||||||
@@ -168,21 +170,23 @@ class StateChange {
|
|||||||
|| this.encoding
|
|| this.encoding
|
||||||
|| this.EOL
|
|| this.EOL
|
||||||
|| this.tabFocusMode
|
|| this.tabFocusMode
|
||||||
|
|| this.columnSelectionMode
|
||||||
|| this.screenReaderMode
|
|| this.screenReaderMode
|
||||||
|| this.metadata;
|
|| this.metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StateDelta {
|
type StateDelta = (
|
||||||
selectionStatus?: string;
|
{ type: 'selectionStatus'; selectionStatus: string | undefined; }
|
||||||
mode?: string;
|
| { type: 'mode'; mode: string | undefined; }
|
||||||
encoding?: string;
|
| { type: 'encoding'; encoding: string | undefined; }
|
||||||
EOL?: string;
|
| { type: 'EOL'; EOL: string | undefined; }
|
||||||
indentation?: string;
|
| { type: 'indentation'; indentation: string | undefined; }
|
||||||
tabFocusMode?: boolean;
|
| { type: 'tabFocusMode'; tabFocusMode: boolean; }
|
||||||
screenReaderMode?: boolean;
|
| { type: 'columnSelectionMode'; columnSelectionMode: boolean; }
|
||||||
metadata?: string | undefined;
|
| { type: 'screenReaderMode'; screenReaderMode: boolean; }
|
||||||
}
|
| { type: 'metadata'; metadata: string | undefined; }
|
||||||
|
);
|
||||||
|
|
||||||
class State {
|
class State {
|
||||||
|
|
||||||
@@ -204,6 +208,9 @@ class State {
|
|||||||
private _tabFocusMode: boolean | undefined;
|
private _tabFocusMode: boolean | undefined;
|
||||||
get tabFocusMode(): boolean | undefined { return this._tabFocusMode; }
|
get tabFocusMode(): boolean | undefined { return this._tabFocusMode; }
|
||||||
|
|
||||||
|
private _columnSelectionMode: boolean | undefined;
|
||||||
|
get columnSelectionMode(): boolean | undefined { return this._columnSelectionMode; }
|
||||||
|
|
||||||
private _screenReaderMode: boolean | undefined;
|
private _screenReaderMode: boolean | undefined;
|
||||||
get screenReaderMode(): boolean | undefined { return this._screenReaderMode; }
|
get screenReaderMode(): boolean | undefined { return this._screenReaderMode; }
|
||||||
|
|
||||||
@@ -213,56 +220,63 @@ class State {
|
|||||||
update(update: StateDelta): StateChange {
|
update(update: StateDelta): StateChange {
|
||||||
const change = new StateChange();
|
const change = new StateChange();
|
||||||
|
|
||||||
if ('selectionStatus' in update) {
|
if (update.type === 'selectionStatus') {
|
||||||
if (this._selectionStatus !== update.selectionStatus) {
|
if (this._selectionStatus !== update.selectionStatus) {
|
||||||
this._selectionStatus = update.selectionStatus;
|
this._selectionStatus = update.selectionStatus;
|
||||||
change.selectionStatus = true;
|
change.selectionStatus = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('indentation' in update) {
|
if (update.type === 'indentation') {
|
||||||
if (this._indentation !== update.indentation) {
|
if (this._indentation !== update.indentation) {
|
||||||
this._indentation = update.indentation;
|
this._indentation = update.indentation;
|
||||||
change.indentation = true;
|
change.indentation = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('mode' in update) {
|
if (update.type === 'mode') {
|
||||||
if (this._mode !== update.mode) {
|
if (this._mode !== update.mode) {
|
||||||
this._mode = update.mode;
|
this._mode = update.mode;
|
||||||
change.mode = true;
|
change.mode = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('encoding' in update) {
|
if (update.type === 'encoding') {
|
||||||
if (this._encoding !== update.encoding) {
|
if (this._encoding !== update.encoding) {
|
||||||
this._encoding = update.encoding;
|
this._encoding = update.encoding;
|
||||||
change.encoding = true;
|
change.encoding = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('EOL' in update) {
|
if (update.type === 'EOL') {
|
||||||
if (this._EOL !== update.EOL) {
|
if (this._EOL !== update.EOL) {
|
||||||
this._EOL = update.EOL;
|
this._EOL = update.EOL;
|
||||||
change.EOL = true;
|
change.EOL = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('tabFocusMode' in update) {
|
if (update.type === 'tabFocusMode') {
|
||||||
if (this._tabFocusMode !== update.tabFocusMode) {
|
if (this._tabFocusMode !== update.tabFocusMode) {
|
||||||
this._tabFocusMode = update.tabFocusMode;
|
this._tabFocusMode = update.tabFocusMode;
|
||||||
change.tabFocusMode = true;
|
change.tabFocusMode = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('screenReaderMode' in update) {
|
if (update.type === 'columnSelectionMode') {
|
||||||
|
if (this._columnSelectionMode !== update.columnSelectionMode) {
|
||||||
|
this._columnSelectionMode = update.columnSelectionMode;
|
||||||
|
change.columnSelectionMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update.type === 'screenReaderMode') {
|
||||||
if (this._screenReaderMode !== update.screenReaderMode) {
|
if (this._screenReaderMode !== update.screenReaderMode) {
|
||||||
this._screenReaderMode = update.screenReaderMode;
|
this._screenReaderMode = update.screenReaderMode;
|
||||||
change.screenReaderMode = true;
|
change.screenReaderMode = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('metadata' in update) {
|
if (update.type === 'metadata') {
|
||||||
if (this._metadata !== update.metadata) {
|
if (this._metadata !== update.metadata) {
|
||||||
this._metadata = update.metadata;
|
this._metadata = update.metadata;
|
||||||
change.metadata = true;
|
change.metadata = true;
|
||||||
@@ -282,6 +296,7 @@ const nlsEOLCRLF = nls.localize('endOfLineCarriageReturnLineFeed', "CRLF");
|
|||||||
|
|
||||||
export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
||||||
private readonly tabFocusModeElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
private readonly tabFocusModeElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
||||||
|
private readonly columnSelectionModeElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
||||||
private readonly screenRedearModeElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
private readonly screenRedearModeElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
||||||
private readonly indentationElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
private readonly indentationElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
||||||
private readonly selectionElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
private readonly selectionElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
|
||||||
@@ -402,6 +417,22 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateColumnSelectionModeElement(visible: boolean): void {
|
||||||
|
if (visible) {
|
||||||
|
if (!this.columnSelectionModeElement.value) {
|
||||||
|
this.columnSelectionModeElement.value = this.statusbarService.addEntry({
|
||||||
|
text: nls.localize('columnSelectionModeEnabled', "Column Selection"),
|
||||||
|
tooltip: nls.localize('disableColumnSelectionMode', "Disable Column Selection Mode"),
|
||||||
|
command: 'editor.action.toggleColumnSelection',
|
||||||
|
backgroundColor: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_BACKGROUND),
|
||||||
|
color: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_FOREGROUND)
|
||||||
|
}, 'status.editor.columnSelectionMode', nls.localize('status.editor.columnSelectionMode', "Column Selection Mode"), StatusbarAlignment.RIGHT, 100.8);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.columnSelectionModeElement.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private updateScreenReaderModeElement(visible: boolean): void {
|
private updateScreenReaderModeElement(visible: boolean): void {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
if (!this.screenRedearModeElement.value) {
|
if (!this.screenRedearModeElement.value) {
|
||||||
@@ -544,6 +575,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
|
|
||||||
private doRenderNow(changed: StateChange): void {
|
private doRenderNow(changed: StateChange): void {
|
||||||
this.updateTabFocusModeElement(!!this.state.tabFocusMode);
|
this.updateTabFocusModeElement(!!this.state.tabFocusMode);
|
||||||
|
this.updateColumnSelectionModeElement(!!this.state.columnSelectionMode);
|
||||||
this.updateScreenReaderModeElement(!!this.state.screenReaderMode);
|
this.updateScreenReaderModeElement(!!this.state.screenReaderMode);
|
||||||
this.updateIndentationElement(this.state.indentation);
|
this.updateIndentationElement(this.state.indentation);
|
||||||
this.updateSelectionElement(this.state.selectionStatus && !this.state.screenReaderMode ? this.state.selectionStatus : undefined);
|
this.updateSelectionElement(this.state.selectionStatus && !this.state.screenReaderMode ? this.state.selectionStatus : undefined);
|
||||||
@@ -583,6 +615,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
const activeCodeEditor = activeControl ? withNullAsUndefined(getCodeEditor(activeControl.getControl())) : undefined;
|
const activeCodeEditor = activeControl ? withNullAsUndefined(getCodeEditor(activeControl.getControl())) : undefined;
|
||||||
|
|
||||||
// Update all states
|
// Update all states
|
||||||
|
this.onColumnSelectionModeChange(activeCodeEditor);
|
||||||
this.onScreenReaderModeChange(activeCodeEditor);
|
this.onScreenReaderModeChange(activeCodeEditor);
|
||||||
this.onSelectionChange(activeCodeEditor);
|
this.onSelectionChange(activeCodeEditor);
|
||||||
this.onModeChange(activeCodeEditor, activeInput);
|
this.onModeChange(activeCodeEditor, activeInput);
|
||||||
@@ -600,6 +633,9 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
|
|
||||||
// Hook Listener for Configuration changes
|
// Hook Listener for Configuration changes
|
||||||
this.activeEditorListeners.add(activeCodeEditor.onDidChangeConfiguration((event: ConfigurationChangedEvent) => {
|
this.activeEditorListeners.add(activeCodeEditor.onDidChangeConfiguration((event: ConfigurationChangedEvent) => {
|
||||||
|
if (event.hasChanged(EditorOption.columnSelection)) {
|
||||||
|
this.onColumnSelectionModeChange(activeCodeEditor);
|
||||||
|
}
|
||||||
if (event.hasChanged(EditorOption.accessibilitySupport)) {
|
if (event.hasChanged(EditorOption.accessibilitySupport)) {
|
||||||
this.onScreenReaderModeChange(activeCodeEditor);
|
this.onScreenReaderModeChange(activeCodeEditor);
|
||||||
}
|
}
|
||||||
@@ -668,14 +704,14 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onModeChange(editorWidget: ICodeEditor | undefined, editorInput: IEditorInput | undefined): void {
|
private onModeChange(editorWidget: ICodeEditor | undefined, editorInput: IEditorInput | undefined): void {
|
||||||
let info: StateDelta = { mode: undefined };
|
let info: StateDelta = { type: 'mode', mode: undefined };
|
||||||
|
|
||||||
// We only support text based editors
|
// We only support text based editors
|
||||||
if (editorWidget && editorInput && toEditorWithModeSupport(editorInput)) {
|
if (editorWidget && editorInput && toEditorWithModeSupport(editorInput)) {
|
||||||
const textModel = editorWidget.getModel();
|
const textModel = editorWidget.getModel();
|
||||||
if (textModel) {
|
if (textModel) {
|
||||||
const modeId = textModel.getLanguageIdentifier().language;
|
const modeId = textModel.getLanguageIdentifier().language;
|
||||||
info = { mode: withNullAsUndefined(this.modeService.getLanguageName(modeId)) };
|
info.mode = withNullAsUndefined(this.modeService.getLanguageName(modeId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,7 +719,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onIndentationChange(editorWidget: ICodeEditor | undefined): void {
|
private onIndentationChange(editorWidget: ICodeEditor | undefined): void {
|
||||||
const update: StateDelta = { indentation: undefined };
|
const update: StateDelta = { type: 'indentation', indentation: undefined };
|
||||||
|
|
||||||
if (editorWidget) {
|
if (editorWidget) {
|
||||||
const model = editorWidget.getModel();
|
const model = editorWidget.getModel();
|
||||||
@@ -701,7 +737,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onMetadataChange(editor: IBaseEditor | undefined): void {
|
private onMetadataChange(editor: IBaseEditor | undefined): void {
|
||||||
const update: StateDelta = { metadata: undefined };
|
const update: StateDelta = { type: 'metadata', metadata: undefined };
|
||||||
|
|
||||||
if (editor instanceof BaseBinaryResourceEditor || editor instanceof BinaryResourceDiffEditor) {
|
if (editor instanceof BaseBinaryResourceEditor || editor instanceof BinaryResourceDiffEditor) {
|
||||||
update.metadata = editor.getMetadata();
|
update.metadata = editor.getMetadata();
|
||||||
@@ -710,6 +746,16 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
this.updateState(update);
|
this.updateState(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onColumnSelectionModeChange(editorWidget: ICodeEditor | undefined): void {
|
||||||
|
const info: StateDelta = { type: 'columnSelectionMode', columnSelectionMode: false };
|
||||||
|
|
||||||
|
if (editorWidget && editorWidget.getOption(EditorOption.columnSelection)) {
|
||||||
|
info.columnSelectionMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateState(info);
|
||||||
|
}
|
||||||
|
|
||||||
private onScreenReaderModeChange(editorWidget: ICodeEditor | undefined): void {
|
private onScreenReaderModeChange(editorWidget: ICodeEditor | undefined): void {
|
||||||
let screenReaderMode = false;
|
let screenReaderMode = false;
|
||||||
|
|
||||||
@@ -733,7 +779,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
this.screenReaderNotification.close();
|
this.screenReaderNotification.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateState({ screenReaderMode: screenReaderMode });
|
this.updateState({ type: 'screenReaderMode', screenReaderMode: screenReaderMode });
|
||||||
}
|
}
|
||||||
|
|
||||||
private onSelectionChange(editorWidget: ICodeEditor | undefined): void {
|
private onSelectionChange(editorWidget: ICodeEditor | undefined): void {
|
||||||
@@ -773,11 +819,11 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateState({ selectionStatus: this.getSelectionLabel(info) });
|
this.updateState({ type: 'selectionStatus', selectionStatus: this.getSelectionLabel(info) });
|
||||||
}
|
}
|
||||||
|
|
||||||
private onEOLChange(editorWidget: ICodeEditor | undefined): void {
|
private onEOLChange(editorWidget: ICodeEditor | undefined): void {
|
||||||
const info: StateDelta = { EOL: undefined };
|
const info: StateDelta = { type: 'EOL', EOL: undefined };
|
||||||
|
|
||||||
if (editorWidget && !editorWidget.getOption(EditorOption.readOnly)) {
|
if (editorWidget && !editorWidget.getOption(EditorOption.readOnly)) {
|
||||||
const codeEditorModel = editorWidget.getModel();
|
const codeEditorModel = editorWidget.getModel();
|
||||||
@@ -794,7 +840,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const info: StateDelta = { encoding: undefined };
|
const info: StateDelta = { type: 'encoding', encoding: undefined };
|
||||||
|
|
||||||
// We only support text based editors that have a model associated
|
// We only support text based editors that have a model associated
|
||||||
// This ensures we do not show the encoding picker while an editor
|
// This ensures we do not show the encoding picker while an editor
|
||||||
@@ -828,7 +874,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onTabFocusModeChange(): void {
|
private onTabFocusModeChange(): void {
|
||||||
const info: StateDelta = { tabFocusMode: TabFocus.getTabFocusMode() };
|
const info: StateDelta = { type: 'tabFocusMode', tabFocusMode: TabFocus.getTabFocusMode() };
|
||||||
|
|
||||||
this.updateState(info);
|
this.updateState(info);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,10 +26,8 @@ export class ClearNotificationAction extends Action {
|
|||||||
super(id, label, 'codicon-close');
|
super(id, label, 'codicon-close');
|
||||||
}
|
}
|
||||||
|
|
||||||
run(notification: INotificationViewItem): Promise<any> {
|
async run(notification: INotificationViewItem): Promise<any> {
|
||||||
this.commandService.executeCommand(CLEAR_NOTIFICATION, notification);
|
this.commandService.executeCommand(CLEAR_NOTIFICATION, notification);
|
||||||
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,10 +44,8 @@ export class ClearAllNotificationsAction extends Action {
|
|||||||
super(id, label, 'codicon-clear-all');
|
super(id, label, 'codicon-clear-all');
|
||||||
}
|
}
|
||||||
|
|
||||||
run(notification: INotificationViewItem): Promise<any> {
|
async run(notification: INotificationViewItem): Promise<any> {
|
||||||
this.commandService.executeCommand(CLEAR_ALL_NOTIFICATIONS);
|
this.commandService.executeCommand(CLEAR_ALL_NOTIFICATIONS);
|
||||||
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,13 +59,11 @@ export class HideNotificationsCenterAction extends Action {
|
|||||||
label: string,
|
label: string,
|
||||||
@ICommandService private readonly commandService: ICommandService
|
@ICommandService private readonly commandService: ICommandService
|
||||||
) {
|
) {
|
||||||
super(id, label, 'codicon-close');
|
super(id, label, 'codicon-chevron-down');
|
||||||
}
|
}
|
||||||
|
|
||||||
run(notification: INotificationViewItem): Promise<any> {
|
async run(notification: INotificationViewItem): Promise<any> {
|
||||||
this.commandService.executeCommand(HIDE_NOTIFICATIONS_CENTER);
|
this.commandService.executeCommand(HIDE_NOTIFICATIONS_CENTER);
|
||||||
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,10 +80,8 @@ export class ExpandNotificationAction extends Action {
|
|||||||
super(id, label, 'codicon-chevron-up');
|
super(id, label, 'codicon-chevron-up');
|
||||||
}
|
}
|
||||||
|
|
||||||
run(notification: INotificationViewItem): Promise<any> {
|
async run(notification: INotificationViewItem): Promise<any> {
|
||||||
this.commandService.executeCommand(EXPAND_NOTIFICATION, notification);
|
this.commandService.executeCommand(EXPAND_NOTIFICATION, notification);
|
||||||
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,10 +98,8 @@ export class CollapseNotificationAction extends Action {
|
|||||||
super(id, label, 'codicon-chevron-down');
|
super(id, label, 'codicon-chevron-down');
|
||||||
}
|
}
|
||||||
|
|
||||||
run(notification: INotificationViewItem): Promise<any> {
|
async run(notification: INotificationViewItem): Promise<any> {
|
||||||
this.commandService.executeCommand(COLLAPSE_NOTIFICATION, notification);
|
this.commandService.executeCommand(COLLAPSE_NOTIFICATION, notification);
|
||||||
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,9 @@ export class NotificationsCenter extends Themable implements INotificationsCente
|
|||||||
// Theming
|
// Theming
|
||||||
this.updateStyles();
|
this.updateStyles();
|
||||||
|
|
||||||
|
// Mark as visible
|
||||||
|
this.model.notifications.forEach(notification => notification.updateVisibility(true));
|
||||||
|
|
||||||
// Context Key
|
// Context Key
|
||||||
this.notificationsCenterVisibleContextKey.set(true);
|
this.notificationsCenterVisibleContextKey.set(true);
|
||||||
|
|
||||||
@@ -115,7 +118,7 @@ export class NotificationsCenter extends Themable implements INotificationsCente
|
|||||||
clearAllAction.enabled = false;
|
clearAllAction.enabled = false;
|
||||||
} else {
|
} else {
|
||||||
notificationsCenterTitle.textContent = localize('notifications', "Notifications");
|
notificationsCenterTitle.textContent = localize('notifications', "Notifications");
|
||||||
clearAllAction.enabled = true;
|
clearAllAction.enabled = this.model.notifications.some(notification => !notification.hasProgress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,20 +175,22 @@ export class NotificationsCenter extends Themable implements INotificationsCente
|
|||||||
return; // only if visible
|
return; // only if visible
|
||||||
}
|
}
|
||||||
|
|
||||||
let focusGroup = false;
|
let focusEditor = false;
|
||||||
|
|
||||||
// Update notifications list based on event
|
// Update notifications list based on event
|
||||||
const [notificationsList, notificationsCenterContainer] = assertAllDefined(this.notificationsList, this.notificationsCenterContainer);
|
const [notificationsList, notificationsCenterContainer] = assertAllDefined(this.notificationsList, this.notificationsCenterContainer);
|
||||||
switch (e.kind) {
|
switch (e.kind) {
|
||||||
case NotificationChangeType.ADD:
|
case NotificationChangeType.ADD:
|
||||||
notificationsList.updateNotificationsList(e.index, 0, [e.item]);
|
notificationsList.updateNotificationsList(e.index, 0, [e.item]);
|
||||||
|
e.item.updateVisibility(true);
|
||||||
break;
|
break;
|
||||||
case NotificationChangeType.CHANGE:
|
case NotificationChangeType.CHANGE:
|
||||||
notificationsList.updateNotificationsList(e.index, 1, [e.item]);
|
notificationsList.updateNotificationsList(e.index, 1, [e.item]);
|
||||||
break;
|
break;
|
||||||
case NotificationChangeType.REMOVE:
|
case NotificationChangeType.REMOVE:
|
||||||
focusGroup = isAncestor(document.activeElement, notificationsCenterContainer);
|
focusEditor = isAncestor(document.activeElement, notificationsCenterContainer);
|
||||||
notificationsList.updateNotificationsList(e.index, 1);
|
notificationsList.updateNotificationsList(e.index, 1);
|
||||||
|
e.item.updateVisibility(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +202,7 @@ export class NotificationsCenter extends Themable implements INotificationsCente
|
|||||||
this.hide();
|
this.hide();
|
||||||
|
|
||||||
// Restore focus to editor group if we had focus
|
// Restore focus to editor group if we had focus
|
||||||
if (focusGroup) {
|
if (focusEditor) {
|
||||||
this.editorGroupService.activeGroup.focus();
|
this.editorGroupService.activeGroup.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,13 +213,16 @@ export class NotificationsCenter extends Themable implements INotificationsCente
|
|||||||
return; // already hidden
|
return; // already hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
const focusGroup = isAncestor(document.activeElement, this.notificationsCenterContainer);
|
const focusEditor = isAncestor(document.activeElement, this.notificationsCenterContainer);
|
||||||
|
|
||||||
// Hide
|
// Hide
|
||||||
this._isVisible = false;
|
this._isVisible = false;
|
||||||
removeClass(this.notificationsCenterContainer, 'visible');
|
removeClass(this.notificationsCenterContainer, 'visible');
|
||||||
this.notificationsList.hide();
|
this.notificationsList.hide();
|
||||||
|
|
||||||
|
// Mark as hidden
|
||||||
|
this.model.notifications.forEach(notification => notification.updateVisibility(false));
|
||||||
|
|
||||||
// Context Key
|
// Context Key
|
||||||
this.notificationsCenterVisibleContextKey.set(false);
|
this.notificationsCenterVisibleContextKey.set(false);
|
||||||
|
|
||||||
@@ -222,7 +230,7 @@ export class NotificationsCenter extends Themable implements INotificationsCente
|
|||||||
this._onDidChangeVisibility.fire();
|
this._onDidChangeVisibility.fire();
|
||||||
|
|
||||||
// Restore focus to editor group if we had focus
|
// Restore focus to editor group if we had focus
|
||||||
if (focusGroup) {
|
if (focusEditor) {
|
||||||
this.editorGroupService.activeGroup.focus();
|
this.editorGroupService.activeGroup.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ export function registerNotificationCommands(center: INotificationsCenterControl
|
|||||||
|
|
||||||
// Show Notifications Cneter
|
// Show Notifications Cneter
|
||||||
CommandsRegistry.registerCommand(SHOW_NOTIFICATIONS_CENTER, () => {
|
CommandsRegistry.registerCommand(SHOW_NOTIFICATIONS_CENTER, () => {
|
||||||
|
toasts.hide();
|
||||||
center.show();
|
center.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -92,6 +93,7 @@ export function registerNotificationCommands(center: INotificationsCenterControl
|
|||||||
if (center.isVisible) {
|
if (center.isVisible) {
|
||||||
center.hide();
|
center.hide();
|
||||||
} else {
|
} else {
|
||||||
|
toasts.hide();
|
||||||
center.show();
|
center.show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export class NotificationsStatus extends Disposable {
|
|||||||
if (!this.isNotificationsCenterVisible) {
|
if (!this.isNotificationsCenterVisible) {
|
||||||
if (e.kind === NotificationChangeType.ADD) {
|
if (e.kind === NotificationChangeType.ADD) {
|
||||||
this.newNotificationsCount++;
|
this.newNotificationsCount++;
|
||||||
} else if (e.kind === NotificationChangeType.REMOVE) {
|
} else if (e.kind === NotificationChangeType.REMOVE && this.newNotificationsCount > 0) {
|
||||||
this.newNotificationsCount--;
|
this.newNotificationsCount--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,8 +69,9 @@ export class NotificationsStatus extends Disposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show the bell with a dot if there are unread or in-progress notifications
|
||||||
const statusProperties: IStatusbarEntry = {
|
const statusProperties: IStatusbarEntry = {
|
||||||
text: `${this.newNotificationsCount === 0 ? '$(bell)' : '$(bell-dot)'}${notificationsInProgress > 0 ? ' $(sync~spin)' : ''}`,
|
text: `${notificationsInProgress > 0 || this.newNotificationsCount > 0 ? '$(bell-dot)' : '$(bell)'}`,
|
||||||
command: this.isNotificationsCenterVisible ? HIDE_NOTIFICATIONS_CENTER : SHOW_NOTIFICATIONS_CENTER,
|
command: this.isNotificationsCenterVisible ? HIDE_NOTIFICATIONS_CENTER : SHOW_NOTIFICATIONS_CENTER,
|
||||||
tooltip: this.getTooltip(notificationsInProgress),
|
tooltip: this.getTooltip(notificationsInProgress),
|
||||||
showBeak: this.isNotificationsCenterVisible
|
showBeak: this.isNotificationsCenterVisible
|
||||||
|
|||||||
@@ -179,11 +179,8 @@ export class NotificationsToasts extends Themable implements INotificationsToast
|
|||||||
const toast: INotificationToast = { item, list: notificationList, container: notificationToastContainer, toast: notificationToast, toDispose: itemDisposables };
|
const toast: INotificationToast = { item, list: notificationList, container: notificationToastContainer, toast: notificationToast, toDispose: itemDisposables };
|
||||||
this.mapNotificationToToast.set(item, toast);
|
this.mapNotificationToToast.set(item, toast);
|
||||||
|
|
||||||
itemDisposables.add(toDisposable(() => {
|
// When disposed, remove as visible
|
||||||
if (this.isToastVisible(toast) && notificationsToastsContainer) {
|
itemDisposables.add(toDisposable(() => this.updateToastVisibility(toast, false)));
|
||||||
notificationsToastsContainer.removeChild(toast.container);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Make visible
|
// Make visible
|
||||||
notificationList.show();
|
notificationList.show();
|
||||||
@@ -236,6 +233,9 @@ export class NotificationsToasts extends Themable implements INotificationsToast
|
|||||||
addClass(notificationToast, 'notification-fade-in-done');
|
addClass(notificationToast, 'notification-fade-in-done');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Mark as visible
|
||||||
|
item.updateVisibility(true);
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
if (!this._isVisible) {
|
if (!this._isVisible) {
|
||||||
this._isVisible = true;
|
this._isVisible = true;
|
||||||
@@ -292,12 +292,13 @@ export class NotificationsToasts extends Themable implements INotificationsToast
|
|||||||
}
|
}
|
||||||
|
|
||||||
private removeToast(item: INotificationViewItem): void {
|
private removeToast(item: INotificationViewItem): void {
|
||||||
|
let focusEditor = false;
|
||||||
|
|
||||||
const notificationToast = this.mapNotificationToToast.get(item);
|
const notificationToast = this.mapNotificationToToast.get(item);
|
||||||
let focusGroup = false;
|
|
||||||
if (notificationToast) {
|
if (notificationToast) {
|
||||||
const toastHasDOMFocus = isAncestor(document.activeElement, notificationToast.container);
|
const toastHasDOMFocus = isAncestor(document.activeElement, notificationToast.container);
|
||||||
if (toastHasDOMFocus) {
|
if (toastHasDOMFocus) {
|
||||||
focusGroup = !(this.focusNext() || this.focusPrevious()); // focus next if any, otherwise focus editor
|
focusEditor = !(this.focusNext() || this.focusPrevious()); // focus next if any, otherwise focus editor
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listeners
|
// Listeners
|
||||||
@@ -317,7 +318,7 @@ export class NotificationsToasts extends Themable implements INotificationsToast
|
|||||||
this.doHide();
|
this.doHide();
|
||||||
|
|
||||||
// Move focus back to editor group as needed
|
// Move focus back to editor group as needed
|
||||||
if (focusGroup) {
|
if (focusEditor) {
|
||||||
this.editorGroupService.activeGroup.focus();
|
this.editorGroupService.activeGroup.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,11 +347,11 @@ export class NotificationsToasts extends Themable implements INotificationsToast
|
|||||||
}
|
}
|
||||||
|
|
||||||
hide(): void {
|
hide(): void {
|
||||||
const focusGroup = this.notificationsToastsContainer ? isAncestor(document.activeElement, this.notificationsToastsContainer) : false;
|
const focusEditor = this.notificationsToastsContainer ? isAncestor(document.activeElement, this.notificationsToastsContainer) : false;
|
||||||
|
|
||||||
this.removeToasts();
|
this.removeToasts();
|
||||||
|
|
||||||
if (focusGroup) {
|
if (focusEditor) {
|
||||||
this.editorGroupService.activeGroup.focus();
|
this.editorGroupService.activeGroup.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -459,12 +460,12 @@ export class NotificationsToasts extends Themable implements INotificationsToast
|
|||||||
notificationToasts.push(toast);
|
notificationToasts.push(toast);
|
||||||
break;
|
break;
|
||||||
case ToastVisibility.HIDDEN:
|
case ToastVisibility.HIDDEN:
|
||||||
if (!this.isToastVisible(toast)) {
|
if (!this.isToastInDOM(toast)) {
|
||||||
notificationToasts.push(toast);
|
notificationToasts.push(toast);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ToastVisibility.VISIBLE:
|
case ToastVisibility.VISIBLE:
|
||||||
if (this.isToastVisible(toast)) {
|
if (this.isToastInDOM(toast)) {
|
||||||
notificationToasts.push(toast);
|
notificationToasts.push(toast);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -530,7 +531,7 @@ export class NotificationsToasts extends Themable implements INotificationsToast
|
|||||||
|
|
||||||
// In order to measure the client height, the element cannot have display: none
|
// In order to measure the client height, the element cannot have display: none
|
||||||
toast.container.style.opacity = '0';
|
toast.container.style.opacity = '0';
|
||||||
this.setVisibility(toast, true);
|
this.updateToastVisibility(toast, true);
|
||||||
|
|
||||||
heightToGive -= toast.container.offsetHeight;
|
heightToGive -= toast.container.offsetHeight;
|
||||||
|
|
||||||
@@ -542,7 +543,7 @@ export class NotificationsToasts extends Themable implements INotificationsToast
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hide or show toast based on context
|
// Hide or show toast based on context
|
||||||
this.setVisibility(toast, makeVisible);
|
this.updateToastVisibility(toast, makeVisible);
|
||||||
toast.container.style.opacity = '';
|
toast.container.style.opacity = '';
|
||||||
|
|
||||||
if (makeVisible) {
|
if (makeVisible) {
|
||||||
@@ -551,20 +552,24 @@ export class NotificationsToasts extends Themable implements INotificationsToast
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setVisibility(toast: INotificationToast, visible: boolean): void {
|
private updateToastVisibility(toast: INotificationToast, visible: boolean): void {
|
||||||
if (this.isToastVisible(toast) === visible) {
|
if (this.isToastInDOM(toast) === visible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update visibility in DOM
|
||||||
const notificationsToastsContainer = assertIsDefined(this.notificationsToastsContainer);
|
const notificationsToastsContainer = assertIsDefined(this.notificationsToastsContainer);
|
||||||
if (visible) {
|
if (visible) {
|
||||||
notificationsToastsContainer.appendChild(toast.container);
|
notificationsToastsContainer.appendChild(toast.container);
|
||||||
} else {
|
} else {
|
||||||
notificationsToastsContainer.removeChild(toast.container);
|
notificationsToastsContainer.removeChild(toast.container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update visibility in model
|
||||||
|
toast.item.updateVisibility(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
private isToastVisible(toast: INotificationToast): boolean {
|
private isToastInDOM(toast: INotificationToast): boolean {
|
||||||
return !!toast.container.parentElement;
|
return !!toast.container.parentElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,10 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.monaco-workbench .part.panel > .composite.title > .composite-bar-excess {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar {
|
.monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar {
|
||||||
line-height: 27px; /* matches panel titles in settings */
|
line-height: 27px; /* matches panel titles in settings */
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
|
|||||||
import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExtensions, IViewDescriptorService, IViewDescriptorCollection, ViewContainerLocation } from 'vs/workbench/common/views';
|
import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExtensions, IViewDescriptorService, IViewDescriptorCollection, ViewContainerLocation } from 'vs/workbench/common/views';
|
||||||
import { MenuId } from 'vs/platform/actions/common/actions';
|
import { MenuId } from 'vs/platform/actions/common/actions';
|
||||||
import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions';
|
import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions';
|
||||||
|
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
|
||||||
|
|
||||||
interface ICachedPanel {
|
interface ICachedPanel {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -143,7 +144,7 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
|||||||
getDefaultCompositeId: () => this.panelRegistry.getDefaultPanelId(),
|
getDefaultCompositeId: () => this.panelRegistry.getDefaultPanelId(),
|
||||||
hidePart: () => this.layoutService.setPanelHidden(true),
|
hidePart: () => this.layoutService.setPanelHidden(true),
|
||||||
dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Panel,
|
dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Panel,
|
||||||
(id: string, focus?: boolean) => this.openPanel(id, focus),
|
(id: string, focus?: boolean) => (<unknown>this.openPanel(id, focus)) as Promise<IPaneComposite | undefined>, // {{SQL CARBON EDIT}} strict-null-check
|
||||||
(from: string, to: string) => this.compositeBar.move(from, to),
|
(from: string, to: string) => this.compositeBar.move(from, to),
|
||||||
() => this.getPinnedPanels().map(p => p.id)
|
() => this.getPinnedPanels().map(p => p.id)
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -255,7 +255,10 @@ export abstract class ViewPane extends Pane implements IView {
|
|||||||
this._onDidFocus.fire();
|
this._onDidFocus.fire();
|
||||||
}));
|
}));
|
||||||
this._register(focusTracker.onDidBlur(() => {
|
this._register(focusTracker.onDidBlur(() => {
|
||||||
this.focusedViewContextKey.reset();
|
if (this.focusedViewContextKey.get() === this.id) {
|
||||||
|
this.focusedViewContextKey.reset();
|
||||||
|
}
|
||||||
|
|
||||||
this._onDidBlur.fire();
|
this._onDidBlur.fire();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -1006,7 +1009,8 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
|||||||
}
|
}
|
||||||
if (!this.areExtensionsReady) {
|
if (!this.areExtensionsReady) {
|
||||||
if (this.visibleViewsCountFromCache === undefined) {
|
if (this.visibleViewsCountFromCache === undefined) {
|
||||||
return true;
|
// TODO @sbatten fix hack for #91367
|
||||||
|
return this.viewDescriptorService.getViewContainerLocation(this.viewContainer) === ViewContainerLocation.Panel;
|
||||||
}
|
}
|
||||||
// Check in cache so that view do not jump. See #29609
|
// Check in cache so that view do not jump. See #29609
|
||||||
return this.visibleViewsCountFromCache === 1;
|
return this.visibleViewsCountFromCache === 1;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification';
|
import { INotification, INotificationHandle, INotificationActions, INotificationProgress, NoOpNotification, Severity, NotificationMessage, IPromptChoice, IStatusMessageOptions, NotificationsFilter, INotificationProgressProperties } from 'vs/platform/notification/common/notification';
|
||||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||||
@@ -92,6 +92,9 @@ export class NotificationHandle extends Disposable implements INotificationHandl
|
|||||||
private readonly _onDidClose = this._register(new Emitter<void>());
|
private readonly _onDidClose = this._register(new Emitter<void>());
|
||||||
readonly onDidClose = this._onDidClose.event;
|
readonly onDidClose = this._onDidClose.event;
|
||||||
|
|
||||||
|
private readonly _onDidChangeVisibility = this._register(new Emitter<boolean>());
|
||||||
|
readonly onDidChangeVisibility = this._onDidChangeVisibility.event;
|
||||||
|
|
||||||
constructor(private readonly item: INotificationViewItem, private readonly onClose: (item: INotificationViewItem) => void) {
|
constructor(private readonly item: INotificationViewItem, private readonly onClose: (item: INotificationViewItem) => void) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -99,6 +102,11 @@ export class NotificationHandle extends Disposable implements INotificationHandl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private registerListeners(): void {
|
private registerListeners(): void {
|
||||||
|
|
||||||
|
// Visibility
|
||||||
|
this._register(this.item.onDidChangeVisibility(visible => this._onDidChangeVisibility.fire(visible)));
|
||||||
|
|
||||||
|
// Closing
|
||||||
Event.once(this.item.onDidClose)(() => {
|
Event.once(this.item.onDidClose)(() => {
|
||||||
this._onDidClose.fire();
|
this._onDidClose.fire();
|
||||||
|
|
||||||
@@ -265,6 +273,7 @@ export interface INotificationViewItem {
|
|||||||
|
|
||||||
readonly onDidChangeExpansion: Event<void>;
|
readonly onDidChangeExpansion: Event<void>;
|
||||||
readonly onDidClose: Event<void>;
|
readonly onDidClose: Event<void>;
|
||||||
|
readonly onDidChangeVisibility: Event<boolean>;
|
||||||
readonly onDidChangeLabel: Event<INotificationViewItemLabelChangeEvent>;
|
readonly onDidChangeLabel: Event<INotificationViewItemLabelChangeEvent>;
|
||||||
|
|
||||||
expand(): void;
|
expand(): void;
|
||||||
@@ -275,6 +284,8 @@ export interface INotificationViewItem {
|
|||||||
updateMessage(message: NotificationMessage): void;
|
updateMessage(message: NotificationMessage): void;
|
||||||
updateActions(actions?: INotificationActions): void;
|
updateActions(actions?: INotificationActions): void;
|
||||||
|
|
||||||
|
updateVisibility(visible: boolean): void;
|
||||||
|
|
||||||
close(): void;
|
close(): void;
|
||||||
|
|
||||||
equals(item: INotificationViewItem): boolean;
|
equals(item: INotificationViewItem): boolean;
|
||||||
@@ -398,6 +409,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie
|
|||||||
private static readonly MAX_MESSAGE_LENGTH = 1000;
|
private static readonly MAX_MESSAGE_LENGTH = 1000;
|
||||||
|
|
||||||
private _expanded: boolean | undefined;
|
private _expanded: boolean | undefined;
|
||||||
|
private _visible: boolean = false;
|
||||||
|
|
||||||
private _actions: INotificationActions | undefined;
|
private _actions: INotificationActions | undefined;
|
||||||
private _progress: NotificationViewItemProgress | undefined;
|
private _progress: NotificationViewItemProgress | undefined;
|
||||||
@@ -411,6 +423,9 @@ export class NotificationViewItem extends Disposable implements INotificationVie
|
|||||||
private readonly _onDidChangeLabel = this._register(new Emitter<INotificationViewItemLabelChangeEvent>());
|
private readonly _onDidChangeLabel = this._register(new Emitter<INotificationViewItemLabelChangeEvent>());
|
||||||
readonly onDidChangeLabel = this._onDidChangeLabel.event;
|
readonly onDidChangeLabel = this._onDidChangeLabel.event;
|
||||||
|
|
||||||
|
private readonly _onDidChangeVisibility = this._register(new Emitter<boolean>());
|
||||||
|
readonly onDidChangeVisibility = this._onDidChangeVisibility.event;
|
||||||
|
|
||||||
static create(notification: INotification, filter: NotificationsFilter = NotificationsFilter.OFF): INotificationViewItem | undefined {
|
static create(notification: INotification, filter: NotificationsFilter = NotificationsFilter.OFF): INotificationViewItem | undefined {
|
||||||
if (!notification || !notification.message || isPromiseCanceledError(notification.message)) {
|
if (!notification || !notification.message || isPromiseCanceledError(notification.message)) {
|
||||||
return undefined; // we need a message to show
|
return undefined; // we need a message to show
|
||||||
@@ -435,7 +450,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie
|
|||||||
actions = { primary: notification.message.actions };
|
actions = { primary: notification.message.actions };
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NotificationViewItem(severity, notification.sticky, notification.silent || filter === NotificationsFilter.SILENT || (filter === NotificationsFilter.ERROR && notification.severity !== Severity.Error), message, notification.source, actions);
|
return new NotificationViewItem(severity, notification.sticky, notification.silent || filter === NotificationsFilter.SILENT || (filter === NotificationsFilter.ERROR && notification.severity !== Severity.Error), message, notification.source, notification.progress, actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static parseNotificationMessage(input: NotificationMessage): INotificationMessage | undefined {
|
private static parseNotificationMessage(input: NotificationMessage): INotificationMessage | undefined {
|
||||||
@@ -472,13 +487,30 @@ export class NotificationViewItem extends Disposable implements INotificationVie
|
|||||||
private _silent: boolean | undefined,
|
private _silent: boolean | undefined,
|
||||||
private _message: INotificationMessage,
|
private _message: INotificationMessage,
|
||||||
private _source: string | undefined,
|
private _source: string | undefined,
|
||||||
|
progress: INotificationProgressProperties | undefined,
|
||||||
actions?: INotificationActions
|
actions?: INotificationActions
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
if (progress) {
|
||||||
|
this.setProgress(progress);
|
||||||
|
}
|
||||||
|
|
||||||
this.setActions(actions);
|
this.setActions(actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setProgress(progress: INotificationProgressProperties): void {
|
||||||
|
if (progress.infinite) {
|
||||||
|
this.progress.infinite();
|
||||||
|
} else if (progress.total) {
|
||||||
|
this.progress.total(progress.total);
|
||||||
|
|
||||||
|
if (progress.worked) {
|
||||||
|
this.progress.worked(progress.worked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private setActions(actions: INotificationActions = { primary: [], secondary: [] }): void {
|
private setActions(actions: INotificationActions = { primary: [], secondary: [] }): void {
|
||||||
if (!Array.isArray(actions.primary)) {
|
if (!Array.isArray(actions.primary)) {
|
||||||
actions.primary = [];
|
actions.primary = [];
|
||||||
@@ -583,6 +615,14 @@ export class NotificationViewItem extends Disposable implements INotificationVie
|
|||||||
this._onDidChangeLabel.fire({ kind: NotificationViewItemLabelKind.ACTIONS });
|
this._onDidChangeLabel.fire({ kind: NotificationViewItemLabelKind.ACTIONS });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateVisibility(visible: boolean): void {
|
||||||
|
if (this._visible !== visible) {
|
||||||
|
this._visible = visible;
|
||||||
|
|
||||||
|
this._onDidChangeVisibility.fire(visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
expand(): void {
|
expand(): void {
|
||||||
if (this._expanded || !this.canCollapse) {
|
if (this._expanded || !this.canCollapse) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
|||||||
import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||||
import { IAction, IActionViewItem } from 'vs/base/common/actions';
|
import { IAction, IActionViewItem } from 'vs/base/common/actions';
|
||||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||||
import { flatten } from 'vs/base/common/arrays';
|
import { flatten, mergeSort } from 'vs/base/common/arrays';
|
||||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||||
import { SetMap } from 'vs/base/common/collections';
|
import { SetMap } from 'vs/base/common/collections';
|
||||||
|
|
||||||
@@ -53,6 +53,7 @@ export interface IViewContainerDescriptor {
|
|||||||
|
|
||||||
readonly extensionId?: ExtensionIdentifier;
|
readonly extensionId?: ExtensionIdentifier;
|
||||||
|
|
||||||
|
readonly rejectAddedViews?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IViewContainersRegistry {
|
export interface IViewContainersRegistry {
|
||||||
@@ -211,9 +212,16 @@ export interface IViewDescriptorCollection extends IDisposable {
|
|||||||
readonly allViewDescriptors: IViewDescriptor[];
|
readonly allViewDescriptors: IViewDescriptor[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ViewContentPriority {
|
||||||
|
Normal = 0,
|
||||||
|
Low = 1,
|
||||||
|
Lowest = 2
|
||||||
|
}
|
||||||
|
|
||||||
export interface IViewContentDescriptor {
|
export interface IViewContentDescriptor {
|
||||||
readonly content: string;
|
readonly content: string;
|
||||||
readonly when?: ContextKeyExpr | 'default';
|
readonly when?: ContextKeyExpr | 'default';
|
||||||
|
readonly priority?: ViewContentPriority;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ordered preconditions for each button in the content
|
* ordered preconditions for each button in the content
|
||||||
@@ -247,6 +255,13 @@ export interface IViewsRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function compareViewContentDescriptors(a: IViewContentDescriptor, b: IViewContentDescriptor): number {
|
function compareViewContentDescriptors(a: IViewContentDescriptor, b: IViewContentDescriptor): number {
|
||||||
|
const aPriority = a.priority ?? ViewContentPriority.Normal;
|
||||||
|
const bPriority = b.priority ?? ViewContentPriority.Normal;
|
||||||
|
|
||||||
|
if (aPriority !== bPriority) {
|
||||||
|
return aPriority - bPriority;
|
||||||
|
}
|
||||||
|
|
||||||
return a.content < b.content ? -1 : 1;
|
return a.content < b.content ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,8 +343,8 @@ class ViewsRegistry extends Disposable implements IViewsRegistry {
|
|||||||
|
|
||||||
getViewWelcomeContent(id: string): IViewContentDescriptor[] {
|
getViewWelcomeContent(id: string): IViewContentDescriptor[] {
|
||||||
const result: IViewContentDescriptor[] = [];
|
const result: IViewContentDescriptor[] = [];
|
||||||
result.sort(compareViewContentDescriptors);
|
|
||||||
this._viewWelcomeContents.forEach(id, descriptor => result.push(descriptor));
|
this._viewWelcomeContents.forEach(id, descriptor => result.push(descriptor));
|
||||||
|
mergeSort(result, compareViewContentDescriptors);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ class BulkEditPreviewContribution {
|
|||||||
private async _previewEdit(edit: WorkspaceEdit) {
|
private async _previewEdit(edit: WorkspaceEdit) {
|
||||||
this._ctxEnabled.set(true);
|
this._ctxEnabled.set(true);
|
||||||
|
|
||||||
|
const uxState = this._activeSession?.uxState ?? new UXState(this._panelService, this._editorGroupsService);
|
||||||
const view = await getBulkEditPane(this._viewsService);
|
const view = await getBulkEditPane(this._viewsService);
|
||||||
if (!view) {
|
if (!view) {
|
||||||
this._ctxEnabled.set(false);
|
this._ctxEnabled.set(false);
|
||||||
@@ -136,9 +137,9 @@ class BulkEditPreviewContribution {
|
|||||||
let session: PreviewSession;
|
let session: PreviewSession;
|
||||||
if (this._activeSession) {
|
if (this._activeSession) {
|
||||||
this._activeSession.cts.dispose(true);
|
this._activeSession.cts.dispose(true);
|
||||||
session = new PreviewSession(this._activeSession.uxState);
|
session = new PreviewSession(uxState);
|
||||||
} else {
|
} else {
|
||||||
session = new PreviewSession(new UXState(this._panelService, this._editorGroupsService));
|
session = new PreviewSession(uxState);
|
||||||
}
|
}
|
||||||
this._activeSession = session;
|
this._activeSession = session;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configur
|
|||||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||||
import { Registry } from 'vs/platform/registry/common/platform';
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
|
import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
|
||||||
|
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||||
|
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||||
|
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||||
|
import { CoreNavigationCommands } from 'vs/editor/browser/controller/coreCommands';
|
||||||
|
import { Position } from 'vs/editor/common/core/position';
|
||||||
|
import { Selection } from 'vs/editor/common/core/selection';
|
||||||
|
import { CursorColumns } from 'vs/editor/common/controller/cursorCommon';
|
||||||
|
|
||||||
export class ToggleColumnSelectionAction extends Action {
|
export class ToggleColumnSelectionAction extends Action {
|
||||||
public static readonly ID = 'editor.action.toggleColumnSelection';
|
public static readonly ID = 'editor.action.toggleColumnSelection';
|
||||||
@@ -18,26 +25,68 @@ export class ToggleColumnSelectionAction extends Action {
|
|||||||
constructor(
|
constructor(
|
||||||
id: string,
|
id: string,
|
||||||
label: string,
|
label: string,
|
||||||
@IConfigurationService private readonly _configurationService: IConfigurationService
|
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||||
|
@ICodeEditorService private readonly _codeEditorService: ICodeEditorService
|
||||||
) {
|
) {
|
||||||
super(id, label);
|
super(id, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(): Promise<any> {
|
private _getCodeEditor(): ICodeEditor | null {
|
||||||
const newValue = !this._configurationService.getValue<boolean>('editor.columnSelection');
|
const codeEditor = this._codeEditorService.getFocusedCodeEditor();
|
||||||
return this._configurationService.updateValue('editor.columnSelection', newValue, ConfigurationTarget.USER);
|
if (codeEditor) {
|
||||||
|
return codeEditor;
|
||||||
|
}
|
||||||
|
return this._codeEditorService.getActiveCodeEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(): Promise<any> {
|
||||||
|
const oldValue = this._configurationService.getValue<boolean>('editor.columnSelection');
|
||||||
|
const codeEditor = this._getCodeEditor();
|
||||||
|
await this._configurationService.updateValue('editor.columnSelection', !oldValue, ConfigurationTarget.USER);
|
||||||
|
const newValue = this._configurationService.getValue<boolean>('editor.columnSelection');
|
||||||
|
if (!codeEditor || codeEditor !== this._getCodeEditor() || oldValue === newValue || !codeEditor.hasModel()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const cursors = codeEditor._getCursors();
|
||||||
|
if (codeEditor.getOption(EditorOption.columnSelection)) {
|
||||||
|
const selection = codeEditor.getSelection();
|
||||||
|
const modelSelectionStart = new Position(selection.selectionStartLineNumber, selection.selectionStartColumn);
|
||||||
|
const viewSelectionStart = cursors.context.convertModelPositionToViewPosition(modelSelectionStart);
|
||||||
|
const modelPosition = new Position(selection.positionLineNumber, selection.positionColumn);
|
||||||
|
const viewPosition = cursors.context.convertModelPositionToViewPosition(modelPosition);
|
||||||
|
|
||||||
|
CoreNavigationCommands.MoveTo.runCoreEditorCommand(cursors, {
|
||||||
|
position: modelSelectionStart,
|
||||||
|
viewPosition: viewSelectionStart
|
||||||
|
});
|
||||||
|
const visibleColumn = CursorColumns.visibleColumnFromColumn2(cursors.context.config, cursors.context.viewModel, viewPosition);
|
||||||
|
CoreNavigationCommands.ColumnSelect.runCoreEditorCommand(cursors, {
|
||||||
|
position: modelPosition,
|
||||||
|
viewPosition: viewPosition,
|
||||||
|
doColumnSelect: true,
|
||||||
|
mouseColumn: visibleColumn + 1
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const columnSelectData = cursors.getColumnSelectData();
|
||||||
|
const fromViewColumn = CursorColumns.columnFromVisibleColumn2(cursors.context.config, cursors.context.viewModel, columnSelectData.fromViewLineNumber, columnSelectData.fromViewVisualColumn);
|
||||||
|
const fromPosition = cursors.context.convertViewPositionToModelPosition(columnSelectData.fromViewLineNumber, fromViewColumn);
|
||||||
|
const toViewColumn = CursorColumns.columnFromVisibleColumn2(cursors.context.config, cursors.context.viewModel, columnSelectData.toViewLineNumber, columnSelectData.toViewVisualColumn);
|
||||||
|
const toPosition = cursors.context.convertViewPositionToModelPosition(columnSelectData.toViewLineNumber, toViewColumn);
|
||||||
|
|
||||||
|
codeEditor.setSelection(new Selection(fromPosition.lineNumber, fromPosition.column, toPosition.lineNumber, toPosition.column));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleColumnSelectionAction, ToggleColumnSelectionAction.ID, ToggleColumnSelectionAction.LABEL), 'View: Toggle Column Selection Mode', nls.localize('view', "View"));
|
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleColumnSelectionAction, ToggleColumnSelectionAction.ID, ToggleColumnSelectionAction.LABEL), 'Toggle Column Selection Mode');
|
||||||
|
|
||||||
MenuRegistry.appendMenuItem(MenuId.MenubarSelectionMenu, {
|
MenuRegistry.appendMenuItem(MenuId.MenubarSelectionMenu, {
|
||||||
group: '3_multi',
|
group: '4_config',
|
||||||
command: {
|
command: {
|
||||||
id: ToggleColumnSelectionAction.ID,
|
id: ToggleColumnSelectionAction.ID,
|
||||||
title: nls.localize({ key: 'miColumnSelection', comment: ['&& denotes a mnemonic'] }, "Column &&Selection Mode"),
|
title: nls.localize({ key: 'miColumnSelection', comment: ['&& denotes a mnemonic'] }, "Column &&Selection Mode"),
|
||||||
toggled: ContextKeyExpr.equals('config.editor.columnSelection', true)
|
toggled: ContextKeyExpr.equals('config.editor.columnSelection', true)
|
||||||
},
|
},
|
||||||
order: 1.5
|
order: 2
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
|
|||||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleMultiCursorModifierAction, ToggleMultiCursorModifierAction.ID, ToggleMultiCursorModifierAction.LABEL), 'Toggle Multi-Cursor Modifier');
|
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleMultiCursorModifierAction, ToggleMultiCursorModifierAction.ID, ToggleMultiCursorModifierAction.LABEL), 'Toggle Multi-Cursor Modifier');
|
||||||
MenuRegistry.appendMenuItem(MenuId.MenubarSelectionMenu, {
|
MenuRegistry.appendMenuItem(MenuId.MenubarSelectionMenu, {
|
||||||
group: '3_multi',
|
group: '4_config',
|
||||||
command: {
|
command: {
|
||||||
id: ToggleMultiCursorModifierAction.ID,
|
id: ToggleMultiCursorModifierAction.ID,
|
||||||
title: nls.localize('miMultiCursorAlt', "Switch to Alt+Click for Multi-Cursor")
|
title: nls.localize('miMultiCursorAlt', "Switch to Alt+Click for Multi-Cursor")
|
||||||
@@ -79,7 +79,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarSelectionMenu, {
|
|||||||
order: 1
|
order: 1
|
||||||
});
|
});
|
||||||
MenuRegistry.appendMenuItem(MenuId.MenubarSelectionMenu, {
|
MenuRegistry.appendMenuItem(MenuId.MenubarSelectionMenu, {
|
||||||
group: '3_multi',
|
group: '4_config',
|
||||||
command: {
|
command: {
|
||||||
id: ToggleMultiCursorModifierAction.ID,
|
id: ToggleMultiCursorModifierAction.ID,
|
||||||
title: (
|
title: (
|
||||||
|
|||||||
@@ -20,10 +20,7 @@ import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
|||||||
import { Registry } from 'vs/platform/registry/common/platform';
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
|
import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
|
||||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
|
||||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
|
||||||
|
|
||||||
export class SelectionClipboard extends Disposable implements IEditorContribution {
|
export class SelectionClipboard extends Disposable implements IEditorContribution {
|
||||||
private static readonly SELECTION_LENGTH_LIMIT = 65536;
|
private static readonly SELECTION_LENGTH_LIMIT = 65536;
|
||||||
@@ -119,15 +116,7 @@ class PasteSelectionClipboardAction extends EditorAction {
|
|||||||
id: 'editor.action.selectionClipboardPaste',
|
id: 'editor.action.selectionClipboardPaste',
|
||||||
label: nls.localize('actions.pasteSelectionClipboard', "Paste Selection Clipboard"),
|
label: nls.localize('actions.pasteSelectionClipboard', "Paste Selection Clipboard"),
|
||||||
alias: 'Paste Selection Clipboard',
|
alias: 'Paste Selection Clipboard',
|
||||||
precondition: EditorContextKeys.writable,
|
precondition: EditorContextKeys.writable
|
||||||
kbOpts: {
|
|
||||||
kbExpr: ContextKeyExpr.and(
|
|
||||||
EditorContextKeys.editorTextFocus,
|
|
||||||
ContextKeyExpr.has('config.editor.selectionClipboard')
|
|
||||||
),
|
|
||||||
primary: KeyMod.Shift | KeyCode.Insert,
|
|
||||||
weight: KeybindingWeight.EditorContrib
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -333,11 +333,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
const editorInfo = this._editorInfoStore.get(editor.viewType);
|
const editorInfo = this._editorInfoStore.get(editor.viewType);
|
||||||
if (!editorInfo) {
|
if (!editorInfo?.matches(newResource)) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!editorInfo.matches(newResource)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export interface ICustomEditorModel extends IWorkingCopy {
|
|||||||
readonly onWillSave: Event<CustomEditorSaveEvent>;
|
readonly onWillSave: Event<CustomEditorSaveEvent>;
|
||||||
readonly onWillSaveAs: Event<CustomEditorSaveAsEvent>;
|
readonly onWillSaveAs: Event<CustomEditorSaveAsEvent>;
|
||||||
|
|
||||||
onBackup(f: () => CancelablePromise<boolean>): void;
|
onBackup(f: () => CancelablePromise<void>): void;
|
||||||
|
|
||||||
setDirty(dirty: boolean): void;
|
setDirty(dirty: boolean): void;
|
||||||
undo(): void;
|
undo(): void;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace HotExitState {
|
|||||||
readonly type = Type.Pending;
|
readonly type = Type.Pending;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly operation: CancelablePromise<boolean>,
|
public readonly operation: CancelablePromise<void>,
|
||||||
) { }
|
) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,9 +90,9 @@ export class CustomEditorModel extends Disposable implements ICustomEditorModel
|
|||||||
private readonly _onWillSaveAs = this._register(new Emitter<CustomEditorSaveAsEvent>());
|
private readonly _onWillSaveAs = this._register(new Emitter<CustomEditorSaveAsEvent>());
|
||||||
public readonly onWillSaveAs = this._onWillSaveAs.event;
|
public readonly onWillSaveAs = this._onWillSaveAs.event;
|
||||||
|
|
||||||
private _onBackup: undefined | (() => CancelablePromise<boolean>);
|
private _onBackup: undefined | (() => CancelablePromise<void>);
|
||||||
|
|
||||||
public onBackup(f: () => CancelablePromise<boolean>) {
|
public onBackup(f: () => CancelablePromise<void>) {
|
||||||
if (this._onBackup) {
|
if (this._onBackup) {
|
||||||
throw new Error('Backup already implemented');
|
throw new Error('Backup already implemented');
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,11 @@ export class CustomEditorModel extends Disposable implements ICustomEditorModel
|
|||||||
this._hotExitState = pendingState;
|
this._hotExitState = pendingState;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this._hotExitState = await pendingState.operation ? HotExitState.Allowed : HotExitState.NotAllowed;
|
await pendingState.operation;
|
||||||
|
// Make sure state has not changed in the meantime
|
||||||
|
if (this._hotExitState === pendingState) {
|
||||||
|
this._hotExitState = HotExitState.Allowed;
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Make sure state has not changed in the meantime
|
// Make sure state has not changed in the meantime
|
||||||
if (this._hotExitState === pendingState) {
|
if (this._hotExitState === pendingState) {
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ configurationRegistry.registerConfiguration({
|
|||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
'debug.onTaskErrors': {
|
'debug.onTaskErrors': {
|
||||||
enum: ['debugAnyway', 'showErrors', 'prompt', 'cancel'],
|
enum: ['debugAnyway', 'showErrors', 'prompt', 'abort'],
|
||||||
enumDescriptions: [nls.localize('debugAnyway', "Ignore task errors and start debugging."), nls.localize('showErrors', "Show the Problems view and do not start debugging."), nls.localize('prompt', "Prompt user."), nls.localize('cancel', "Cancel debugging.")],
|
enumDescriptions: [nls.localize('debugAnyway', "Ignore task errors and start debugging."), nls.localize('showErrors', "Show the Problems view and do not start debugging."), nls.localize('prompt', "Prompt user."), nls.localize('cancel', "Cancel debugging.")],
|
||||||
description: nls.localize('debug.onTaskErrors', "Controls what to do when errors are encountered after running a preLaunchTask."),
|
description: nls.localize('debug.onTaskErrors', "Controls what to do when errors are encountered after running a preLaunchTask."),
|
||||||
default: 'prompt'
|
default: 'prompt'
|
||||||
|
|||||||
@@ -519,18 +519,17 @@ abstract class AbstractLaunch {
|
|||||||
if (!config || (!Array.isArray(config.configurations) && !Array.isArray(config.compounds))) {
|
if (!config || (!Array.isArray(config.configurations) && !Array.isArray(config.compounds))) {
|
||||||
return [];
|
return [];
|
||||||
} else {
|
} else {
|
||||||
const names: string[] = [];
|
const configurations: (IConfig | ICompound)[] = [];
|
||||||
if (config.configurations) {
|
if (config.configurations) {
|
||||||
names.push(...config.configurations.filter(cfg => cfg && typeof cfg.name === 'string').map(cfg => cfg.name));
|
configurations.push(...config.configurations.filter(cfg => cfg && typeof cfg.name === 'string'));
|
||||||
}
|
}
|
||||||
if (includeCompounds && config.compounds) {
|
if (includeCompounds && config.compounds) {
|
||||||
if (config.compounds) {
|
if (config.compounds) {
|
||||||
names.push(...config.compounds.filter(compound => typeof compound.name === 'string' && compound.configurations && compound.configurations.length)
|
configurations.push(...config.compounds.filter(compound => typeof compound.name === 'string' && compound.configurations && compound.configurations.length));
|
||||||
.map(compound => compound.name));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return names;
|
return getVisibleAndSorted(configurations).map(c => c.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ export class DebugHoverWidget implements IContentWidget {
|
|||||||
|
|
||||||
if (!matchingExpression) {
|
if (!matchingExpression) {
|
||||||
const lineContent = model.getLineContent(pos.lineNumber);
|
const lineContent = model.getLineContent(pos.lineNumber);
|
||||||
matchingExpression = lineContent.substring(rng.startColumn - 1, rng.endColumn);
|
matchingExpression = lineContent.substring(rng.startColumn - 1, rng.endColumn - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { RawDebugSession } from 'vs/workbench/contrib/debug/browser/rawDebugSess
|
|||||||
import { IProductService } from 'vs/platform/product/common/productService';
|
import { IProductService } from 'vs/platform/product/common/productService';
|
||||||
import { IWorkspaceFolder, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
import { IWorkspaceFolder, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
import { RunOnceScheduler, Queue } from 'vs/base/common/async';
|
||||||
import { generateUuid } from 'vs/base/common/uuid';
|
import { generateUuid } from 'vs/base/common/uuid';
|
||||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||||
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
|
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
|
||||||
@@ -807,62 +807,58 @@ export class DebugSession implements IDebugSession {
|
|||||||
this._onDidChangeState.fire();
|
this._onDidChangeState.fire();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let outpuPromises: Promise<void>[] = [];
|
const outputQueue = new Queue<void>();
|
||||||
this.rawListeners.push(this.raw.onDidOutput(async event => {
|
this.rawListeners.push(this.raw.onDidOutput(async event => {
|
||||||
if (!event.body || !this.raw) {
|
outputQueue.queue(async () => {
|
||||||
return;
|
if (!event.body || !this.raw) {
|
||||||
}
|
|
||||||
|
|
||||||
const outputSeverity = event.body.category === 'stderr' ? severity.Error : event.body.category === 'console' ? severity.Warning : severity.Info;
|
|
||||||
if (event.body.category === 'telemetry') {
|
|
||||||
// only log telemetry events from debug adapter if the debug extension provided the telemetry key
|
|
||||||
// and the user opted in telemetry
|
|
||||||
if (this.raw.customTelemetryService && this.telemetryService.isOptedIn) {
|
|
||||||
// __GDPR__TODO__ We're sending events in the name of the debug extension and we can not ensure that those are declared correctly.
|
|
||||||
this.raw.customTelemetryService.publicLog(event.body.output, event.body.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure to append output in the correct order by properly waiting on preivous promises #33822
|
|
||||||
const waitFor = outpuPromises.slice();
|
|
||||||
const source = event.body.source && event.body.line ? {
|
|
||||||
lineNumber: event.body.line,
|
|
||||||
column: event.body.column ? event.body.column : 1,
|
|
||||||
source: this.getSource(event.body.source)
|
|
||||||
} : undefined;
|
|
||||||
|
|
||||||
if (event.body.group === 'start' || event.body.group === 'startCollapsed') {
|
|
||||||
const expanded = event.body.group === 'start';
|
|
||||||
this.repl.startGroup(event.body.output || '', expanded, source);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (event.body.group === 'end') {
|
|
||||||
this.repl.endGroup();
|
|
||||||
if (!event.body.output) {
|
|
||||||
// Only return if the end event does not have additional output in it
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (event.body.variablesReference) {
|
const outputSeverity = event.body.category === 'stderr' ? severity.Error : event.body.category === 'console' ? severity.Warning : severity.Info;
|
||||||
const container = new ExpressionContainer(this, undefined, event.body.variablesReference, generateUuid());
|
if (event.body.category === 'telemetry') {
|
||||||
outpuPromises.push(container.getChildren().then(async children => {
|
// only log telemetry events from debug adapter if the debug extension provided the telemetry key
|
||||||
await Promise.all(waitFor);
|
// and the user opted in telemetry
|
||||||
children.forEach(child => {
|
if (this.raw.customTelemetryService && this.telemetryService.isOptedIn) {
|
||||||
// Since we can not display multiple trees in a row, we are displaying these variables one after the other (ignoring their names)
|
// __GDPR__TODO__ We're sending events in the name of the debug extension and we can not ensure that those are declared correctly.
|
||||||
(<any>child).name = null;
|
this.raw.customTelemetryService.publicLog(event.body.output, event.body.data);
|
||||||
this.appendToRepl(child, outputSeverity, source);
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure to append output in the correct order by properly waiting on preivous promises #33822
|
||||||
|
const source = event.body.source && event.body.line ? {
|
||||||
|
lineNumber: event.body.line,
|
||||||
|
column: event.body.column ? event.body.column : 1,
|
||||||
|
source: this.getSource(event.body.source)
|
||||||
|
} : undefined;
|
||||||
|
|
||||||
|
if (event.body.group === 'start' || event.body.group === 'startCollapsed') {
|
||||||
|
const expanded = event.body.group === 'start';
|
||||||
|
this.repl.startGroup(event.body.output || '', expanded, source);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event.body.group === 'end') {
|
||||||
|
this.repl.endGroup();
|
||||||
|
if (!event.body.output) {
|
||||||
|
// Only return if the end event does not have additional output in it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.body.variablesReference) {
|
||||||
|
const container = new ExpressionContainer(this, undefined, event.body.variablesReference, generateUuid());
|
||||||
|
await container.getChildren().then(children => {
|
||||||
|
children.forEach(child => {
|
||||||
|
// Since we can not display multiple trees in a row, we are displaying these variables one after the other (ignoring their names)
|
||||||
|
(<any>child).name = null;
|
||||||
|
this.appendToRepl(child, outputSeverity, source);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}));
|
} else if (typeof event.body.output === 'string') {
|
||||||
} else if (typeof event.body.output === 'string') {
|
this.appendToRepl(event.body.output, outputSeverity, source);
|
||||||
await Promise.all(waitFor);
|
}
|
||||||
this.appendToRepl(event.body.output, outputSeverity, source);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(outpuPromises);
|
|
||||||
outpuPromises = [];
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.rawListeners.push(this.raw.onDidBreakpoint(event => {
|
this.rawListeners.push(this.raw.onDidBreakpoint(event => {
|
||||||
|
|||||||
@@ -75,35 +75,35 @@ export class StartView extends ViewPane {
|
|||||||
};
|
};
|
||||||
this._register(editorService.onDidActiveEditorChange(setContextKey));
|
this._register(editorService.onDidActiveEditorChange(setContextKey));
|
||||||
this._register(this.debugService.getConfigurationManager().onDidRegisterDebugger(setContextKey));
|
this._register(this.debugService.getConfigurationManager().onDidRegisterDebugger(setContextKey));
|
||||||
this.registerViews();
|
setContextKey();
|
||||||
|
|
||||||
|
const debugKeybinding = this.keybindingService.lookupKeybinding(StartAction.ID);
|
||||||
|
debugKeybindingLabel = debugKeybinding ? ` (${debugKeybinding.getLabel()})` : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldShowWelcome(): boolean {
|
shouldShowWelcome(): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerViews(): void {
|
|
||||||
const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
|
|
||||||
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
|
||||||
content: localize('openAFileWhichCanBeDebugged', "[Open a file](command:{0}) which can be debugged or run.", isMacintosh ? OpenFileFolderAction.ID : OpenFileAction.ID),
|
|
||||||
when: CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR.toNegated()
|
|
||||||
});
|
|
||||||
|
|
||||||
const debugKeybinding = this.keybindingService.lookupKeybinding(StartAction.ID);
|
|
||||||
const debugKeybindingLabel = debugKeybinding ? ` (${debugKeybinding.getLabel()})` : '';
|
|
||||||
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
|
||||||
content: localize('runAndDebugAction', "[Run and Debug{0}](command:{1})", debugKeybindingLabel, StartAction.ID),
|
|
||||||
preconditions: [CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR]
|
|
||||||
});
|
|
||||||
|
|
||||||
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
|
||||||
content: localize('customizeRunAndDebug', "To customize Run and Debug [create a launch.json file](command:{0}).", ConfigureAction.ID),
|
|
||||||
when: WorkbenchStateContext.notEqualsTo('empty')
|
|
||||||
});
|
|
||||||
|
|
||||||
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
|
||||||
content: localize('customizeRunAndDebugOpenFolder', "To customize Run and Debug, [open a folder](command:{0}) and create a launch.json file.", isMacintosh ? OpenFileFolderAction.ID : OpenFolderAction.ID),
|
|
||||||
when: WorkbenchStateContext.isEqualTo('empty')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
|
||||||
|
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
||||||
|
content: localize('openAFileWhichCanBeDebugged', "[Open a file](command:{0}) which can be debugged or run.", isMacintosh ? OpenFileFolderAction.ID : OpenFileAction.ID),
|
||||||
|
when: CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR.toNegated()
|
||||||
|
});
|
||||||
|
|
||||||
|
let debugKeybindingLabel = '';
|
||||||
|
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
||||||
|
content: localize('runAndDebugAction', "[Run and Debug{0}](command:{1})", debugKeybindingLabel, StartAction.ID),
|
||||||
|
preconditions: [CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR]
|
||||||
|
});
|
||||||
|
|
||||||
|
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
||||||
|
content: localize('customizeRunAndDebug', "To customize Run and Debug [create a launch.json file](command:{0}).", ConfigureAction.ID),
|
||||||
|
when: WorkbenchStateContext.notEqualsTo('empty')
|
||||||
|
});
|
||||||
|
|
||||||
|
viewsRegistry.registerViewWelcomeContent(StartView.ID, {
|
||||||
|
content: localize('customizeRunAndDebugOpenFolder', "To customize Run and Debug, [open a folder](command:{0}) and create a launch.json file.", isMacintosh ? OpenFileFolderAction.ID : OpenFolderAction.ID),
|
||||||
|
when: WorkbenchStateContext.isEqualTo('empty')
|
||||||
|
});
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegis
|
|||||||
name: localize('extensions', "Extensions"),
|
name: localize('extensions', "Extensions"),
|
||||||
ctorDescriptor: new SyncDescriptor(ExtensionsViewPaneContainer),
|
ctorDescriptor: new SyncDescriptor(ExtensionsViewPaneContainer),
|
||||||
icon: 'codicon-extensions',
|
icon: 'codicon-extensions',
|
||||||
order: 14 // {{SQL CARBON EDIT}}
|
order: 14, // {{SQL CARBON EDIT}}
|
||||||
|
rejectAddedViews: true,
|
||||||
}, ViewContainerLocation.Sidebar);
|
}, ViewContainerLocation.Sidebar);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2690,7 +2690,7 @@ export class SystemDisabledWarningAction extends ExtensionAction {
|
|||||||
if (server) {
|
if (server) {
|
||||||
this.tooltip = localize('Install in other server to enable', "Install the extension on '{0}' to enable.", server.label);
|
this.tooltip = localize('Install in other server to enable', "Install the extension on '{0}' to enable.", server.label);
|
||||||
} else {
|
} else {
|
||||||
this.tooltip = localize('disabled because of extension kind', "This extension cannot be enabled in the remote server.");
|
this.tooltip = localize('disabled because of extension kind', "This extension has defined that it cannot run on the remote server");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,21 +65,21 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor
|
|||||||
private registerViews(): void {
|
private registerViews(): void {
|
||||||
const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
|
const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
|
||||||
|
|
||||||
viewsRegistry.registerViewWelcomeContent(EmptyView.ID, {
|
this._register(viewsRegistry.registerViewWelcomeContent(EmptyView.ID, {
|
||||||
content: localize('noWorkspaceHelp', "You have not yet added a folder to the workspace.\n[Add Folder](command:{0})", AddRootFolderAction.ID),
|
content: localize('noWorkspaceHelp', "You have not yet added a folder to the workspace.\n[Add Folder](command:{0})", AddRootFolderAction.ID),
|
||||||
when: WorkbenchStateContext.isEqualTo('workspace')
|
when: WorkbenchStateContext.isEqualTo('workspace')
|
||||||
});
|
}));
|
||||||
|
|
||||||
const commandId = isMacintosh ? OpenFileFolderAction.ID : OpenFolderAction.ID;
|
const commandId = isMacintosh ? OpenFileFolderAction.ID : OpenFolderAction.ID;
|
||||||
viewsRegistry.registerViewWelcomeContent(EmptyView.ID, {
|
this._register(viewsRegistry.registerViewWelcomeContent(EmptyView.ID, {
|
||||||
content: localize('remoteNoFolderHelp', "Connected to remote.\n[Open Folder](command:{0})", commandId),
|
content: localize('remoteNoFolderHelp', "Connected to remote.\n[Open Folder](command:{0})", commandId),
|
||||||
when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), RemoteNameContext.notEqualsTo(''), IsWebContext.toNegated())
|
when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), RemoteNameContext.notEqualsTo(''), IsWebContext.toNegated())
|
||||||
});
|
}));
|
||||||
|
|
||||||
viewsRegistry.registerViewWelcomeContent(EmptyView.ID, {
|
this._register(viewsRegistry.registerViewWelcomeContent(EmptyView.ID, {
|
||||||
content: localize('noFolderHelp', "You have not yet opened a folder.\n[Open Folder](command:{0})", commandId),
|
content: localize('noFolderHelp', "You have not yet opened a folder.\n[Open Folder](command:{0})", commandId),
|
||||||
when: ContextKeyExpr.or(ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), RemoteNameContext.isEqualTo('')), ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), IsWebContext))
|
when: ContextKeyExpr.or(ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), RemoteNameContext.isEqualTo('')), ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), IsWebContext))
|
||||||
});
|
}));
|
||||||
|
|
||||||
const viewDescriptors = viewsRegistry.getViews(VIEW_CONTAINER);
|
const viewDescriptors = viewsRegistry.getViews(VIEW_CONTAINER);
|
||||||
|
|
||||||
|
|||||||
@@ -55,11 +55,11 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.explorer-viewlet .pane-header .monaco-count-badge.hidden {
|
.pane-header .dirty-count.monaco-count-badge.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.explorer-viewlet .monaco-count-badge {
|
.dirty-count.monaco-count-badge {
|
||||||
padding: 1px 6px 2px;
|
padding: 1px 6px 2px;
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user