Skip to content

Commit ba0d87d

Browse files
authored
Share menu multiple selection support (#6558)
Fixes #6542
1 parent 8eacb79 commit ba0d87d

2 files changed

Lines changed: 158 additions & 97 deletions

File tree

src/issues/issueFeatureRegistrar.ts

Lines changed: 73 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import { basename } from 'path';
67
import * as vscode from 'vscode';
78
import { Remote } from '../api/api';
89
import { GitApiImpl } from '../api/api1';
@@ -54,6 +55,7 @@ import { UserHoverProvider } from './userHoverProvider';
5455
import {
5556
createGitHubLink,
5657
createGithubPermalink,
58+
createSinglePermalink,
5759
getIssue,
5860
IssueTemplate,
5961
LinkContext,
@@ -137,116 +139,116 @@ export class IssueFeatureRegistrar extends Disposable {
137139
this._register(
138140
vscode.commands.registerCommand(
139141
'issue.copyGithubPermalink',
140-
(context: LinkContext) => {
142+
(context: LinkContext, additional: LinkContext[] | undefined) => {
141143
/* __GDPR__
142144
"issue.copyGithubPermalink" : {}
143145
*/
144146
this.telemetry.sendTelemetryEvent('issue.copyGithubPermalink');
145-
return this.copyPermalink(this.manager, context);
147+
return this.copyPermalink(this.manager, additional && additional.length > 0 ? additional : [context]);
146148
},
147149
this,
148150
),
149151
);
150152
this._register(
151153
vscode.commands.registerCommand(
152154
'issue.copyGithubHeadLink',
153-
(fileUri: any) => {
155+
(fileUri: vscode.Uri, additional: vscode.Uri[] | undefined) => {
154156
/* __GDPR__
155157
"issue.copyGithubHeadLink" : {}
156158
*/
157159
this.telemetry.sendTelemetryEvent('issue.copyGithubHeadLink');
158-
return this.copyHeadLink(fileUri);
160+
return this.copyHeadLink(additional && additional.length > 0 ? additional : [fileUri]);
159161
},
160162
this,
161163
),
162164
);
163165
this._register(
164166
vscode.commands.registerCommand(
165167
'issue.copyGithubPermalinkWithoutRange',
166-
(context: LinkContext) => {
168+
(context: LinkContext, additional: LinkContext[] | undefined) => {
167169
/* __GDPR__
168170
"issue.copyGithubPermalinkWithoutRange" : {}
169171
*/
170172
this.telemetry.sendTelemetryEvent('issue.copyGithubPermalinkWithoutRange');
171-
return this.copyPermalink(this.manager, context, false);
173+
return this.copyPermalink(this.manager, additional && additional.length > 0 ? additional : [context], false);
172174
},
173175
this,
174176
),
175177
);
176178
this._register(
177179
vscode.commands.registerCommand(
178180
'issue.copyGithubHeadLinkWithoutRange',
179-
(fileUri: any) => {
181+
(fileUri: vscode.Uri, additional: vscode.Uri[] | undefined) => {
180182
/* __GDPR__
181183
"issue.copyGithubHeadLinkWithoutRange" : {}
182184
*/
183185
this.telemetry.sendTelemetryEvent('issue.copyGithubHeadLinkWithoutRange');
184-
return this.copyHeadLink(fileUri, false);
186+
return this.copyHeadLink(additional && additional.length > 0 ? additional : [fileUri], false);
185187
},
186188
this,
187189
),
188190
);
189191
this._register(
190192
vscode.commands.registerCommand(
191193
'issue.copyGithubDevLinkWithoutRange',
192-
(context: LinkContext) => {
194+
(context: LinkContext, additional: LinkContext[] | undefined) => {
193195
/* __GDPR__
194196
"issue.copyGithubDevLinkWithoutRange" : {}
195197
*/
196198
this.telemetry.sendTelemetryEvent('issue.copyGithubDevLinkWithoutRange');
197-
return this.copyPermalink(this.manager, context, false, true, true);
199+
return this.copyPermalink(this.manager, additional && additional.length > 0 ? additional : [context], false, true, true);
198200
},
199201
this,
200202
),
201203
);
202204
this._register(
203205
vscode.commands.registerCommand(
204206
'issue.copyGithubDevLink',
205-
(context: LinkContext) => {
207+
(context: LinkContext, additional: LinkContext[] | undefined) => {
206208
/* __GDPR__
207209
"issue.copyGithubDevLink" : {}
208210
*/
209211
this.telemetry.sendTelemetryEvent('issue.copyGithubDevLink');
210-
return this.copyPermalink(this.manager, context, true, true, true);
212+
return this.copyPermalink(this.manager, additional && additional.length > 0 ? additional : [context], true, true, true);
211213
},
212214
this,
213215
),
214216
);
215217
this._register(
216218
vscode.commands.registerCommand(
217219
'issue.copyGithubDevLinkFile',
218-
(context: LinkContext) => {
220+
(context: LinkContext, additional: LinkContext[] | undefined) => {
219221
/* __GDPR__
220222
"issue.copyGithubDevLinkFile" : {}
221223
*/
222224
this.telemetry.sendTelemetryEvent('issue.copyGithubDevLinkFile');
223-
return this.copyPermalink(this.manager, context, false, true, true);
225+
return this.copyPermalink(this.manager, additional && additional.length > 0 ? additional : [context], false, true, true);
224226
},
225227
this,
226228
),
227229
);
228230
this._register(
229231
vscode.commands.registerCommand(
230232
'issue.copyMarkdownGithubPermalink',
231-
(context: LinkContext) => {
233+
(context: LinkContext, additional: LinkContext[] | undefined) => {
232234
/* __GDPR__
233235
"issue.copyMarkdownGithubPermalink" : {}
234236
*/
235237
this.telemetry.sendTelemetryEvent('issue.copyMarkdownGithubPermalink');
236-
return this.copyMarkdownPermalink(this.manager, context);
238+
return this.copyMarkdownPermalink(this.manager, additional && additional.length > 0 ? additional : [context]);
237239
},
238240
this,
239241
),
240242
);
241243
this._register(
242244
vscode.commands.registerCommand(
243245
'issue.copyMarkdownGithubPermalinkWithoutRange',
244-
(context: LinkContext) => {
246+
(context: LinkContext, additional: LinkContext[] | undefined) => {
245247
/* __GDPR__
246248
"issue.copyMarkdownGithubPermalinkWithoutRange" : {}
247249
*/
248250
this.telemetry.sendTelemetryEvent('issue.copyMarkdownGithubPermalinkWithoutRange');
249-
return this.copyMarkdownPermalink(this.manager, context, false);
251+
return this.copyMarkdownPermalink(this.manager, additional && additional.length > 0 ? additional : [context], false);
250252
},
251253
this,
252254
),
@@ -949,7 +951,7 @@ export class IssueFeatureRegistrar extends Disposable {
949951
}
950952
}
951953

952-
contents += (await createGithubPermalink(this.manager, this.gitAPI, true, true, newIssue)).permalink;
954+
contents += (await createSinglePermalink(this.manager, this.gitAPI, true, true, newIssue)).permalink;
953955
return contents;
954956
}
955957

@@ -1293,7 +1295,7 @@ ${options?.body ?? ''}\n
12931295
const body: string | undefined =
12941296
issueBody || newIssue?.document.isUntitled
12951297
? issueBody
1296-
: (await createGithubPermalink(this.manager, this.gitAPI, true, true, newIssue)).permalink;
1298+
: (await createSinglePermalink(this.manager, this.gitAPI, true, true, newIssue)).permalink;
12971299
const createParams: OctokitCommon.IssuesCreateParams = {
12981300
owner: origin.owner,
12991301
repo: origin.repo,
@@ -1343,20 +1345,24 @@ ${options?.body ?? ''}\n
13431345
});
13441346
}
13451347

1346-
private async getPermalinkWithError(repositoriesManager: RepositoriesManager, includeRange: boolean, includeFile: boolean, context?: LinkContext): Promise<PermalinkInfo> {
1347-
const link = await createGithubPermalink(repositoriesManager, this.gitAPI, includeRange, includeFile, undefined, context);
1348-
if (link.error) {
1349-
vscode.window.showWarningMessage(vscode.l10n.t('Unable to create a GitHub permalink for the selection. {0}', link.error));
1348+
private async getPermalinkWithError(repositoriesManager: RepositoriesManager, includeRange: boolean, includeFile: boolean, context?: LinkContext[]): Promise<PermalinkInfo[]> {
1349+
const links = await createGithubPermalink(repositoriesManager, this.gitAPI, includeRange, includeFile, undefined, context);
1350+
const firstError = links.find(link => link.error);
1351+
if (firstError) {
1352+
vscode.window.showWarningMessage(vscode.l10n.t('Unable to create a GitHub permalink for the selection. {0}', firstError.error!));
13501353
}
1351-
return link;
1354+
return links;
13521355
}
13531356

1354-
private async getHeadLinkWithError(context?: vscode.Uri, includeRange?: boolean): Promise<PermalinkInfo> {
1355-
const link = await createGitHubLink(this.manager, context, includeRange);
1356-
if (link.error) {
1357-
vscode.window.showWarningMessage(vscode.l10n.t('Unable to create a GitHub link for the selection. {0}', link.error));
1357+
private async getHeadLinkWithError(context?: vscode.Uri[], includeRange?: boolean): Promise<PermalinkInfo[]> {
1358+
const links = await createGitHubLink(this.manager, context, includeRange);
1359+
if (links.length > 0) {
1360+
const firstError = links.find(link => link.error);
1361+
if (firstError) {
1362+
vscode.window.showWarningMessage(vscode.l10n.t('Unable to create a GitHub link for the selection. {0}', firstError.error!));
1363+
}
13581364
}
1359-
return link;
1365+
return links;
13601366
}
13611367

13621368
private async getContextualizedLink(file: vscode.Uri, link: string): Promise<string> {
@@ -1376,19 +1382,30 @@ ${options?.body ?? ''}\n
13761382
return linkUri.with({ authority, path: linkPath }).toString();
13771383
}
13781384

1379-
async copyPermalink(repositoriesManager: RepositoriesManager, context?: LinkContext, includeRange: boolean = true, includeFile: boolean = true, contextualizeLink: boolean = false) {
1380-
const link = await this.getPermalinkWithError(repositoriesManager, includeRange, includeFile, context);
1381-
if (link.permalink) {
1382-
const contextualizedLink = contextualizeLink && link.originalFile ? await this.getContextualizedLink(link.originalFile, link.permalink) : link.permalink;
1383-
Logger.debug(`writing ${contextualizedLink} to the clipboard`, PERMALINK_COMPONENT);
1384-
return vscode.env.clipboard.writeText(contextualizedLink);
1385+
private async permalinkInfoToClipboardText(links: PermalinkInfo[], shouldContextualize: boolean = false): Promise<string | undefined> {
1386+
const withPermalinks: (PermalinkInfo & { permalink: string })[] = links.filter((link): link is PermalinkInfo & { permalink: string } => !!link.permalink);
1387+
if (withPermalinks.length !== 0) {
1388+
const contextualizedLinks = await Promise.all(withPermalinks.map(async link => (shouldContextualize && link.originalFile) ? await this.getContextualizedLink(link.originalFile, link.permalink) : link.permalink));
1389+
const clipboardText = contextualizedLinks.join('\n');
1390+
Logger.debug(`Will write ${clipboardText} to the clipboard`, PERMALINK_COMPONENT);
1391+
return clipboardText;
1392+
}
1393+
return undefined;
1394+
}
1395+
1396+
async copyPermalink(repositoriesManager: RepositoriesManager, context?: LinkContext[], includeRange: boolean = true, includeFile: boolean = true, contextualizeLink: boolean = false) {
1397+
const links = await this.getPermalinkWithError(repositoriesManager, includeRange, includeFile, context);
1398+
const clipboardText = await this.permalinkInfoToClipboardText(links, contextualizeLink);
1399+
if (clipboardText) {
1400+
return vscode.env.clipboard.writeText(clipboardText);
13851401
}
13861402
}
13871403

1388-
async copyHeadLink(fileUri?: vscode.Uri, includeRange = true) {
1404+
async copyHeadLink(fileUri?: vscode.Uri[], includeRange = true) {
13891405
const link = await this.getHeadLinkWithError(fileUri, includeRange);
1390-
if (link.permalink) {
1391-
return vscode.env.clipboard.writeText(link.permalink);
1406+
const clipboardText = await this.permalinkInfoToClipboardText(link);
1407+
if (clipboardText) {
1408+
return vscode.env.clipboard.writeText(clipboardText);
13921409
}
13931410
}
13941411

@@ -1414,18 +1431,27 @@ ${options?.body ?? ''}\n
14141431
return undefined;
14151432
}
14161433

1417-
async copyMarkdownPermalink(repositoriesManager: RepositoriesManager, context: LinkContext, includeRange: boolean = true) {
1418-
const link = await this.getPermalinkWithError(repositoriesManager, includeRange, true, context);
1419-
const selection = this.getMarkdownLinkText();
1420-
if (link.permalink && selection) {
1421-
return vscode.env.clipboard.writeText(`[${selection.trim()}](${link.permalink})`);
1434+
async copyMarkdownPermalink(repositoriesManager: RepositoriesManager, context: LinkContext[], includeRange: boolean = true) {
1435+
const links = await this.getPermalinkWithError(repositoriesManager, includeRange, true, context);
1436+
const withPermalinks: (PermalinkInfo & { permalink: string })[] = links.filter((link): link is PermalinkInfo & { permalink: string } => !!link.permalink);
1437+
1438+
if (withPermalinks.length === 1) {
1439+
const selection = this.getMarkdownLinkText();
1440+
if (selection) {
1441+
return vscode.env.clipboard.writeText(`[${selection.trim()}](${withPermalinks[0].permalink})`);
1442+
}
14221443
}
1444+
const clipboardText = withPermalinks.map(link => `[${basename(link.originalFile?.fsPath ?? '')}](${link.permalink})`).join('\n');
1445+
Logger.debug(`writing ${clipboardText} to the clipboard`, PERMALINK_COMPONENT);
1446+
return vscode.env.clipboard.writeText(clipboardText);
14231447
}
14241448

14251449
async openPermalink(repositoriesManager: RepositoriesManager) {
1426-
const link = await this.getPermalinkWithError(repositoriesManager, true, true);
1427-
if (link.permalink) {
1428-
return vscode.env.openExternal(vscode.Uri.parse(link.permalink));
1450+
const links = await this.getPermalinkWithError(repositoriesManager, true, true);
1451+
const withPermalinks: (PermalinkInfo & { permalink: string })[] = links.filter((link): link is PermalinkInfo & { permalink: string } => !!link.permalink);
1452+
1453+
if (withPermalinks.length > 0) {
1454+
return vscode.env.openExternal(vscode.Uri.parse(withPermalinks[0].permalink));
14291455
}
14301456
return undefined;
14311457
}

0 commit comments

Comments
 (0)