@theia/core 1.53.2 → 1.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/i18n/nls.cs.json +3 -0
- package/i18n/nls.de.json +3 -0
- package/i18n/nls.es.json +3 -0
- package/i18n/nls.fr.json +3 -0
- package/i18n/nls.hu.json +3 -0
- package/i18n/nls.it.json +3 -0
- package/i18n/nls.ja.json +3 -0
- package/i18n/nls.json +3 -0
- package/i18n/nls.ko.json +3 -0
- package/i18n/nls.pl.json +3 -0
- package/i18n/nls.pt-br.json +3 -0
- package/i18n/nls.ru.json +3 -0
- package/i18n/nls.tr.json +3 -0
- package/i18n/nls.zh-cn.json +3 -0
- package/i18n/nls.zh-tw.json +3 -0
- package/lib/browser/authentication-service.d.ts +15 -14
- package/lib/browser/authentication-service.d.ts.map +1 -1
- package/lib/browser/authentication-service.js +5 -5
- package/lib/browser/authentication-service.js.map +1 -1
- package/lib/browser/catalog.json +116 -12
- package/lib/browser/core-preferences.d.ts.map +1 -1
- package/lib/browser/core-preferences.js +9 -0
- package/lib/browser/core-preferences.js.map +1 -1
- package/lib/browser/open-with-service.d.ts +13 -1
- package/lib/browser/open-with-service.d.ts.map +1 -1
- package/lib/browser/open-with-service.js +48 -9
- package/lib/browser/open-with-service.js.map +1 -1
- package/lib/browser/opener-service.d.ts +3 -0
- package/lib/browser/opener-service.d.ts.map +1 -1
- package/lib/browser/opener-service.js +13 -1
- package/lib/browser/opener-service.js.map +1 -1
- package/lib/browser/widgets/extractable-widget.js +1 -1
- package/lib/browser/widgets/extractable-widget.js.map +1 -1
- package/lib/common/glob.d.ts +4 -4
- package/package.json +6 -6
- package/src/browser/authentication-service.ts +18 -19
- package/src/browser/core-preferences.ts +9 -0
- package/src/browser/open-with-service.ts +54 -7
- package/src/browser/opener-service.ts +13 -0
- package/src/browser/widgets/extractable-widget.ts +1 -1
- package/src/common/glob.ts +4 -4
|
@@ -32,6 +32,13 @@ export interface AuthenticationSessionAccountInformation {
|
|
|
32
32
|
readonly id: string;
|
|
33
33
|
readonly label: string;
|
|
34
34
|
}
|
|
35
|
+
export interface AuthenticationProviderSessionOptions {
|
|
36
|
+
/**
|
|
37
|
+
* The account that is being asked about. If this is passed in, the provider should
|
|
38
|
+
* attempt to return the sessions that are only related to this account.
|
|
39
|
+
*/
|
|
40
|
+
account?: AuthenticationSessionAccountInformation;
|
|
41
|
+
}
|
|
35
42
|
|
|
36
43
|
export interface AuthenticationSession {
|
|
37
44
|
id: string;
|
|
@@ -82,16 +89,6 @@ export interface AuthenticationProvider {
|
|
|
82
89
|
|
|
83
90
|
updateSessionItems(event: AuthenticationProviderAuthenticationSessionsChangeEvent): Promise<void>;
|
|
84
91
|
|
|
85
|
-
/**
|
|
86
|
-
* @deprecated use `createSession` instead.
|
|
87
|
-
*/
|
|
88
|
-
login(scopes: string[]): Promise<AuthenticationSession>;
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* @deprecated use `removeSession` instead.
|
|
92
|
-
*/
|
|
93
|
-
logout(sessionId: string): Promise<void>;
|
|
94
|
-
|
|
95
92
|
/**
|
|
96
93
|
* An [event](#Event) which fires when the array of sessions has changed, or data
|
|
97
94
|
* within a session has changed.
|
|
@@ -102,16 +99,18 @@ export interface AuthenticationProvider {
|
|
|
102
99
|
* Get a list of sessions.
|
|
103
100
|
* @param scopes An optional list of scopes. If provided, the sessions returned should match
|
|
104
101
|
* these permissions, otherwise all sessions should be returned.
|
|
102
|
+
* @param account The optional account that you would like to get the session for
|
|
105
103
|
* @returns A promise that resolves to an array of authentication sessions.
|
|
106
104
|
*/
|
|
107
|
-
getSessions(scopes
|
|
105
|
+
getSessions(scopes: string[] | undefined, account?: AuthenticationSessionAccountInformation): Thenable<ReadonlyArray<AuthenticationSession>>;
|
|
108
106
|
|
|
109
107
|
/**
|
|
110
108
|
* Prompts a user to login.
|
|
111
109
|
* @param scopes A list of scopes, permissions, that the new session should be created with.
|
|
110
|
+
* @param options The options for createing the session
|
|
112
111
|
* @returns A promise that resolves to an authentication session.
|
|
113
112
|
*/
|
|
114
|
-
createSession(scopes: string[]): Thenable<AuthenticationSession>;
|
|
113
|
+
createSession(scopes: string[], options: AuthenticationProviderSessionOptions): Thenable<AuthenticationSession>;
|
|
115
114
|
|
|
116
115
|
/**
|
|
117
116
|
* Removes the session corresponding to session id.
|
|
@@ -134,10 +133,10 @@ export interface AuthenticationService {
|
|
|
134
133
|
|
|
135
134
|
readonly onDidChangeSessions: Event<{ providerId: string, label: string, event: AuthenticationProviderAuthenticationSessionsChangeEvent }>;
|
|
136
135
|
readonly onDidUpdateSignInCount: Event<number>;
|
|
137
|
-
getSessions(providerId: string, scopes?: string[]): Promise<ReadonlyArray<AuthenticationSession>>;
|
|
136
|
+
getSessions(providerId: string, scopes?: string[], user?: AuthenticationSessionAccountInformation): Promise<ReadonlyArray<AuthenticationSession>>;
|
|
138
137
|
getLabel(providerId: string): string;
|
|
139
138
|
supportsMultipleAccounts(providerId: string): boolean;
|
|
140
|
-
login(providerId: string, scopes: string[]): Promise<AuthenticationSession>;
|
|
139
|
+
login(providerId: string, scopes: string[], options?: AuthenticationProviderSessionOptions): Promise<AuthenticationSession>;
|
|
141
140
|
logout(providerId: string, sessionId: string): Promise<void>;
|
|
142
141
|
|
|
143
142
|
signOutOfAccount(providerId: string, accountName: string): Promise<void>;
|
|
@@ -300,7 +299,7 @@ export class AuthenticationServiceImpl implements AuthenticationService {
|
|
|
300
299
|
}
|
|
301
300
|
|
|
302
301
|
const previousSize = this.signInRequestItems.size;
|
|
303
|
-
const sessions = await provider.getSessions();
|
|
302
|
+
const sessions = await provider.getSessions(undefined);
|
|
304
303
|
Object.keys(existingRequestsForProvider).forEach(requestedScopes => {
|
|
305
304
|
if (sessions.some(session => session.scopes.slice().sort().join('') === requestedScopes)) {
|
|
306
305
|
const sessionRequest = existingRequestsForProvider[requestedScopes];
|
|
@@ -411,19 +410,19 @@ export class AuthenticationServiceImpl implements AuthenticationService {
|
|
|
411
410
|
}
|
|
412
411
|
}
|
|
413
412
|
|
|
414
|
-
async getSessions(id: string, scopes?: string[]): Promise<ReadonlyArray<AuthenticationSession>> {
|
|
413
|
+
async getSessions(id: string, scopes?: string[], user?: AuthenticationSessionAccountInformation): Promise<ReadonlyArray<AuthenticationSession>> {
|
|
415
414
|
const authProvider = this.authenticationProviders.get(id);
|
|
416
415
|
if (authProvider) {
|
|
417
|
-
return authProvider.getSessions(scopes);
|
|
416
|
+
return authProvider.getSessions(scopes, user);
|
|
418
417
|
} else {
|
|
419
418
|
throw new Error(`No authentication provider '${id}' is currently registered.`);
|
|
420
419
|
}
|
|
421
420
|
}
|
|
422
421
|
|
|
423
|
-
async login(id: string, scopes: string[]): Promise<AuthenticationSession> {
|
|
422
|
+
async login(id: string, scopes: string[], options?: AuthenticationProviderSessionOptions): Promise<AuthenticationSession> {
|
|
424
423
|
const authProvider = this.authenticationProviders.get(id);
|
|
425
424
|
if (authProvider) {
|
|
426
|
-
return authProvider.createSession(scopes);
|
|
425
|
+
return authProvider.createSession(scopes, options || {});
|
|
427
426
|
} else {
|
|
428
427
|
throw new Error(`No authentication provider '${id}' is currently registered.`);
|
|
429
428
|
}
|
|
@@ -281,6 +281,15 @@ export const corePreferenceSchema: PreferenceSchema = {
|
|
|
281
281
|
default: 200,
|
|
282
282
|
minimum: 10,
|
|
283
283
|
description: nls.localize('theia/core/tabDefaultSize', 'Specifies the default size for tabs.')
|
|
284
|
+
},
|
|
285
|
+
'workbench.editorAssociations': {
|
|
286
|
+
type: 'object',
|
|
287
|
+
markdownDescription: nls.localizeByDefault('Configure [glob patterns](https://aka.ms/vscode-glob-patterns) to editors (for example `"*.hex": "hexEditor.hexedit"`). These have precedence over the default behavior.'),
|
|
288
|
+
patternProperties: {
|
|
289
|
+
'.*': {
|
|
290
|
+
type: 'string'
|
|
291
|
+
}
|
|
292
|
+
}
|
|
284
293
|
}
|
|
285
294
|
}
|
|
286
295
|
};
|
|
@@ -19,7 +19,9 @@ import { Disposable } from '../common/disposable';
|
|
|
19
19
|
import { nls } from '../common/nls';
|
|
20
20
|
import { MaybePromise } from '../common/types';
|
|
21
21
|
import { URI } from '../common/uri';
|
|
22
|
-
import { QuickInputService } from './quick-input';
|
|
22
|
+
import { QuickInputService, QuickPickItem, QuickPickItemOrSeparator } from './quick-input';
|
|
23
|
+
import { PreferenceScope, PreferenceService } from './preferences';
|
|
24
|
+
import { getDefaultHandler } from './opener-service';
|
|
23
25
|
|
|
24
26
|
export interface OpenWithHandler {
|
|
25
27
|
/**
|
|
@@ -46,6 +48,11 @@ export interface OpenWithHandler {
|
|
|
46
48
|
* A returned value indicating a priority of this handler.
|
|
47
49
|
*/
|
|
48
50
|
canHandle(uri: URI): number;
|
|
51
|
+
/**
|
|
52
|
+
* Test whether this handler and open the given URI
|
|
53
|
+
* and return the order of this handler in the list.
|
|
54
|
+
*/
|
|
55
|
+
getOrder?(uri: URI): number;
|
|
49
56
|
/**
|
|
50
57
|
* Open a widget for the given URI and options.
|
|
51
58
|
* Resolve to an opened widget or undefined, e.g. if a page is opened.
|
|
@@ -54,12 +61,19 @@ export interface OpenWithHandler {
|
|
|
54
61
|
open(uri: URI): MaybePromise<object | undefined>;
|
|
55
62
|
}
|
|
56
63
|
|
|
64
|
+
export interface OpenWithQuickPickItem extends QuickPickItem {
|
|
65
|
+
handler: OpenWithHandler;
|
|
66
|
+
}
|
|
67
|
+
|
|
57
68
|
@injectable()
|
|
58
69
|
export class OpenWithService {
|
|
59
70
|
|
|
60
71
|
@inject(QuickInputService)
|
|
61
72
|
protected readonly quickInputService: QuickInputService;
|
|
62
73
|
|
|
74
|
+
@inject(PreferenceService)
|
|
75
|
+
protected readonly preferenceService: PreferenceService;
|
|
76
|
+
|
|
63
77
|
protected readonly handlers: OpenWithHandler[] = [];
|
|
64
78
|
|
|
65
79
|
registerHandler(handler: OpenWithHandler): Disposable {
|
|
@@ -73,17 +87,50 @@ export class OpenWithService {
|
|
|
73
87
|
}
|
|
74
88
|
|
|
75
89
|
async openWith(uri: URI): Promise<object | undefined> {
|
|
90
|
+
// Clone the object, because all objects returned by the preferences service are frozen.
|
|
91
|
+
const associations: Record<string, unknown> = { ...this.preferenceService.get('workbench.editorAssociations') };
|
|
92
|
+
const ext = `*${uri.path.ext}`;
|
|
76
93
|
const handlers = this.getHandlers(uri);
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
94
|
+
const ordered = handlers.slice().sort((a, b) => this.getOrder(b, uri) - this.getOrder(a, uri));
|
|
95
|
+
const defaultHandler = getDefaultHandler(uri, this.preferenceService) ?? handlers[0]?.id;
|
|
96
|
+
const items = this.getQuickPickItems(ordered, defaultHandler);
|
|
97
|
+
// Only offer to select a default editor when the file has a file extension
|
|
98
|
+
const extraItems: QuickPickItemOrSeparator[] = uri.path.ext ? [{
|
|
99
|
+
type: 'separator'
|
|
100
|
+
}, {
|
|
101
|
+
label: nls.localizeByDefault("Configure default editor for '{0}'...", ext)
|
|
102
|
+
}] : [];
|
|
103
|
+
const result = await this.quickInputService.pick<OpenWithQuickPickItem | { label: string }>([...items, ...extraItems], {
|
|
82
104
|
placeHolder: nls.localizeByDefault("Select editor for '{0}'", uri.path.base)
|
|
83
105
|
});
|
|
84
106
|
if (result) {
|
|
85
|
-
|
|
107
|
+
if ('handler' in result) {
|
|
108
|
+
return result.handler.open(uri);
|
|
109
|
+
} else if (result.label) {
|
|
110
|
+
const configureResult = await this.quickInputService.pick(items, {
|
|
111
|
+
placeHolder: nls.localizeByDefault("Select new default editor for '{0}'", ext)
|
|
112
|
+
});
|
|
113
|
+
if (configureResult) {
|
|
114
|
+
associations[ext] = configureResult.handler.id;
|
|
115
|
+
this.preferenceService.set('workbench.editorAssociations', associations, PreferenceScope.User);
|
|
116
|
+
return configureResult.handler.open(uri);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
86
119
|
}
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
protected getQuickPickItems(handlers: OpenWithHandler[], defaultHandler?: string): OpenWithQuickPickItem[] {
|
|
124
|
+
return handlers.map(handler => ({
|
|
125
|
+
handler,
|
|
126
|
+
label: handler.label ?? handler.id,
|
|
127
|
+
detail: handler.providerName ?? '',
|
|
128
|
+
description: handler.id === defaultHandler ? nls.localizeByDefault('Default') : undefined
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
protected getOrder(handler: OpenWithHandler, uri: URI): number {
|
|
133
|
+
return handler.getOrder ? handler.getOrder(uri) : handler.canHandle(uri);
|
|
87
134
|
}
|
|
88
135
|
|
|
89
136
|
getHandlers(uri: URI): OpenWithHandler[] {
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
import { named, injectable, inject } from 'inversify';
|
|
18
18
|
import URI from '../common/uri';
|
|
19
19
|
import { ContributionProvider, Prioritizeable, MaybePromise, Emitter, Event, Disposable } from '../common';
|
|
20
|
+
import { PreferenceService } from './preferences';
|
|
21
|
+
import { match } from '../common/glob';
|
|
20
22
|
|
|
21
23
|
export interface OpenerOptions {
|
|
22
24
|
}
|
|
@@ -96,6 +98,17 @@ export async function open(openerService: OpenerService, uri: URI, options?: Ope
|
|
|
96
98
|
return opener.open(uri, options);
|
|
97
99
|
}
|
|
98
100
|
|
|
101
|
+
export function getDefaultHandler(uri: URI, preferenceService: PreferenceService): string | undefined {
|
|
102
|
+
const associations = preferenceService.get('workbench.editorAssociations', {});
|
|
103
|
+
const defaultHandler = Object.entries(associations).find(([key]) => match(key, uri.path.base))?.[1];
|
|
104
|
+
if (typeof defaultHandler === 'string') {
|
|
105
|
+
return defaultHandler;
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const defaultHandlerPriority = 100_000;
|
|
111
|
+
|
|
99
112
|
@injectable()
|
|
100
113
|
export class DefaultOpenerService implements OpenerService {
|
|
101
114
|
// Collection of open-handlers for custom-editor contributions.
|
|
@@ -28,6 +28,6 @@ export interface ExtractableWidget extends Widget {
|
|
|
28
28
|
|
|
29
29
|
export namespace ExtractableWidget {
|
|
30
30
|
export function is(widget: unknown): widget is ExtractableWidget {
|
|
31
|
-
return widget instanceof Widget &&
|
|
31
|
+
return widget instanceof Widget && 'isExtractable' in widget && (widget as ExtractableWidget).isExtractable === true;
|
|
32
32
|
}
|
|
33
33
|
}
|
package/src/common/glob.ts
CHANGED
|
@@ -454,10 +454,10 @@ function toRegExp(pattern: string): ParsedStringPattern {
|
|
|
454
454
|
|
|
455
455
|
/**
|
|
456
456
|
* Simplified glob matching. Supports a subset of glob patterns:
|
|
457
|
-
* -
|
|
458
|
-
* -
|
|
459
|
-
* -
|
|
460
|
-
* - simple brace expansion ({js,ts} => js or ts)
|
|
457
|
+
* - `*` matches anything inside a path segment
|
|
458
|
+
* - `?` matches 1 character inside a path segment
|
|
459
|
+
* - `**` matches anything including an empty path segment
|
|
460
|
+
* - simple brace expansion (`{js,ts}` => js or ts)
|
|
461
461
|
* - character ranges (using [...])
|
|
462
462
|
*/
|
|
463
463
|
export function match(pattern: string | IRelativePattern, path: string): boolean;
|