Skip to content

Commit d3a0696

Browse files
authored
Add a way to get to github.com from views (#3474)
Fixes #3473
1 parent a33a46a commit d3a0696

File tree

4 files changed

+133
-28
lines changed

4 files changed

+133
-28
lines changed

package.json

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,12 @@
710710
"category": "GitHub Pull Requests",
711711
"icon": "$(edit)"
712712
},
713+
{
714+
"command": "pr.openPullsWebsite",
715+
"title": "Open on GitHub",
716+
"category": "GitHub Pull Requests",
717+
"icon": "$(globe)"
718+
},
713719
{
714720
"command": "issue.createIssueFromSelection",
715721
"title": "Create Issue From Selection",
@@ -847,6 +853,12 @@
847853
"command": "issue.goToLinkedCode",
848854
"title": "Go to Linked Code",
849855
"category": "GitHub Issues"
856+
},
857+
{
858+
"command": "issues.openIssuesWebsite",
859+
"title": "Open on GitHub",
860+
"category": "GitHub Pull Requests",
861+
"icon": "$(globe)"
850862
}
851863
],
852864
"viewsWelcome": [
@@ -1154,27 +1166,59 @@
11541166
{
11551167
"command": "pr.refreshActivePullRequest",
11561168
"when": "false"
1169+
},
1170+
{
1171+
"command": "pr.openPullsWebsite",
1172+
"when": "github:hasGitHubRemotes"
1173+
},
1174+
{
1175+
"command": "issues.openIssuesWebsite",
1176+
"when": "github:hasGitHubRemotes"
11571177
}
11581178
],
1159-
"view/title": [
1179+
"github.pullRequests.overflow": [
11601180
{
1161-
"command": "pr.create",
1162-
"when": "gitHubOpenRepositoryCount != 0 && github:initialized && view == pr:github",
1181+
"command": "pr.openPullsWebsite",
1182+
"when": "gitHubOpenRepositoryCount != 0 && github:initialized",
11631183
"group": "navigation@1"
11641184
},
11651185
{
11661186
"command": "pr.checkoutByNumber",
1167-
"when": "gitHubOpenRepositoryCount != 0 && github:initialized && view == pr:github",
1187+
"when": "gitHubOpenRepositoryCount != 0 && github:initialized",
11681188
"group": "navigation@2"
11691189
},
11701190
{
11711191
"command": "pr.configurePRViewlet",
1172-
"when": "gitHubOpenRepositoryCount != 0 && github:initialized && view =~ /(pr|issues):github/",
1173-
"group": "navigation@4"
1192+
"when": "gitHubOpenRepositoryCount != 0 && github:initialized",
1193+
"group": "navigation@3"
1194+
}
1195+
],
1196+
"github.issues.overflow": [
1197+
{
1198+
"command": "issues.openIssuesWebsite",
1199+
"when": "gitHubOpenRepositoryCount != 0 && github:initialized",
1200+
"group": "navigation@1"
1201+
},
1202+
{
1203+
"command": "pr.configurePRViewlet",
1204+
"when": "gitHubOpenRepositoryCount != 0 && github:initialized",
1205+
"group": "navigation@2"
1206+
}
1207+
],
1208+
"view/title": [
1209+
{
1210+
"command": "pr.create",
1211+
"when": "gitHubOpenRepositoryCount != 0 && github:initialized && view == pr:github",
1212+
"group": "navigation@1"
11741213
},
11751214
{
11761215
"command": "pr.refreshList",
11771216
"when": "gitHubOpenRepositoryCount != 0 && github:initialized && view == pr:github",
1217+
"group": "navigation@2"
1218+
},
1219+
{
1220+
"submenu": "github.pullRequests.overflow",
1221+
"when": "gitHubOpenRepositoryCount != 0 && github:initialized && view == pr:github",
11781222
"group": "navigation@3"
11791223
},
11801224
{
@@ -1192,15 +1236,20 @@
11921236
"when": "view == prStatus:github && !fileListLayout:flat",
11931237
"group": "navigation"
11941238
},
1239+
{
1240+
"command": "issue.createIssue",
1241+
"when": "view == issues:github && github:hasGitHubRemotes",
1242+
"group": "navigation@1"
1243+
},
11951244
{
11961245
"command": "issue.refresh",
11971246
"when": "view == issues:github",
11981247
"group": "navigation@2"
11991248
},
12001249
{
1201-
"command": "issue.createIssue",
1202-
"when": "view == issues:github && github:hasGitHubRemotes",
1203-
"group": "navigation@1"
1250+
"submenu": "github.issues.overflow",
1251+
"when": "gitHubOpenRepositoryCount != 0 && github:initialized && view == issues:github",
1252+
"group": "navigation@3"
12041253
},
12051254
{
12061255
"command": "pr.refreshActivePullRequest",
@@ -1558,6 +1607,18 @@
15581607
}
15591608
]
15601609
},
1610+
"submenus": [
1611+
{
1612+
"id": "github.pullRequests.overflow",
1613+
"label": "More actions...",
1614+
"icon": "$(ellipsis)"
1615+
},
1616+
{
1617+
"id": "github.issues.overflow",
1618+
"label": "More actions...",
1619+
"icon": "$(ellipsis)"
1620+
}
1621+
],
15611622
"colors": [
15621623
{
15631624
"id": "issues.newIssueDecoration",

src/commands.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { GHPRComment, TemporaryComment } from './github/prComment';
2323
import { PullRequestModel } from './github/pullRequestModel';
2424
import { PullRequestOverviewPanel } from './github/pullRequestOverview';
2525
import { RepositoriesManager } from './github/repositoriesManager';
26-
import { isInCodespaces } from './github/utils';
26+
import { getIssuesUrl, getPullsUrl, isInCodespaces } from './github/utils';
2727
import { PullRequestsTreeDataProvider } from './view/prsTreeDataProvider';
2828
import { ReviewManager } from './view/reviewManager';
2929
import { CategoryTreeNode } from './view/treeNodes/categoryNode';
@@ -937,4 +937,30 @@ export function registerCommands(
937937
return ReviewManager.getReviewManagerForFolderManager(reviewManagers, githubRepo.manager)?.switch(prModel);
938938
}
939939
}));
940+
941+
function chooseRepoToOpen() {
942+
const githubRepositories: GitHubRepository[] = [];
943+
reposManager.folderManagers.forEach(manager => {
944+
githubRepositories.push(...(manager.gitHubRepositories));
945+
});
946+
return chooseItem<GitHubRepository>(
947+
githubRepositories,
948+
itemValue => `${itemValue.remote.owner}/${itemValue.remote.repositoryName}`,
949+
{ placeHolder: 'Which GitHub repository do you want to open?' }
950+
);
951+
}
952+
context.subscriptions.push(
953+
vscode.commands.registerCommand('pr.openPullsWebsite', async () => {
954+
const githubRepo = await chooseRepoToOpen();
955+
if (githubRepo) {
956+
vscode.env.openExternal(getPullsUrl(githubRepo));
957+
}
958+
}));
959+
context.subscriptions.push(
960+
vscode.commands.registerCommand('issues.openIssuesWebsite', async () => {
961+
const githubRepo = await chooseRepoToOpen();
962+
if (githubRepo) {
963+
vscode.env.openExternal(getIssuesUrl(githubRepo));
964+
}
965+
}));
940966
}

src/github/utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,3 +989,11 @@ export function getAvatarWithEnterpriseFallback(avatarUrl: string, email: string
989989
return authProviderId === AuthProvider.github ? avatarUrl : (email ? generateGravatarUrl(
990990
crypto.createHash('md5').update(email?.trim()?.toLowerCase()).digest('hex')) : undefined);
991991
}
992+
993+
export function getPullsUrl(repo: GitHubRepository) {
994+
return vscode.Uri.parse(`https://${repo.remote.host}/${repo.remote.owner}/${repo.remote.repositoryName}/pulls`);
995+
}
996+
997+
export function getIssuesUrl(repo: GitHubRepository) {
998+
return vscode.Uri.parse(`https://${repo.remote.host}/${repo.remote.owner}/${repo.remote.repositoryName}/issues`);
999+
}

src/issues/util.ts

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Commit, Ref, Remote, Repository } from '../api/api';
1111
import { GitApiImpl } from '../api/api1';
1212
import { Protocol } from '../common/protocol';
1313
import { FolderRepositoryManager, PullRequestDefaults } from '../github/folderRepositoryManager';
14+
import { GitHubRepository } from '../github/githubRepository';
1415
import { GithubItemStateEnum, User } from '../github/interface';
1516
import { IssueModel } from '../github/issueModel';
1617
import { PullRequestModel } from '../github/pullRequestModel';
@@ -459,6 +460,30 @@ function getSimpleUpstream(repository: Repository) {
459460
}
460461
}
461462

463+
async function getBestPossibleUpstream(repository: Repository, commit: Commit): Promise<Remote | undefined> {
464+
const fallbackUpstream = new Promise<Remote | undefined>(resolve => {
465+
resolve(getSimpleUpstream(repository));
466+
});
467+
468+
let upstream: Remote | undefined = commit ? await Promise.race([
469+
getUpstream(repository, commit),
470+
new Promise<Remote | undefined>(resolve => {
471+
setTimeout(() => {
472+
resolve(fallbackUpstream);
473+
}, 1500);
474+
}),
475+
]) : await fallbackUpstream;
476+
477+
if (!upstream || !upstream.fetchUrl) {
478+
// Check fallback
479+
upstream = await fallbackUpstream;
480+
if (!upstream || !upstream.fetchUrl) {
481+
return undefined;
482+
}
483+
}
484+
return upstream;
485+
}
486+
462487
export async function createGithubPermalink(
463488
gitAPI: GitApiImpl,
464489
positionInfo?: NewIssue,
@@ -487,26 +512,11 @@ export async function createGithubPermalink(
487512
commitHash = repository.state.HEAD?.commit;
488513
}
489514

490-
const fallbackUpstream = new Promise<Remote | undefined>(resolve => {
491-
resolve(getSimpleUpstream(repository));
492-
});
493-
494-
let upstream: Remote | undefined = commit ? await Promise.race([
495-
getUpstream(repository, commit),
496-
new Promise<Remote | undefined>(resolve => {
497-
setTimeout(() => {
498-
resolve(fallbackUpstream);
499-
}, 1500);
500-
}),
501-
]) : await fallbackUpstream;
502-
515+
const upstream = commit ? await getBestPossibleUpstream(repository, commit) : undefined;
503516
if (!upstream || !upstream.fetchUrl) {
504-
// Check fallback
505-
upstream = await fallbackUpstream;
506-
if (!upstream || !upstream.fetchUrl) {
507-
return { permalink: undefined, error: 'The selection may not exist on any remote.', originalFile: uri };
508-
}
517+
return { permalink: undefined, error: 'The selection may not exist on any remote.', originalFile: uri };
509518
}
519+
510520
const pathSegment = uri.path.substring(repository.rootUri.path.length);
511521
const originOfFetchUrl = getUpstreamOrigin(upstream).replace(/\/$/, '');
512522
return {

0 commit comments

Comments
 (0)