1- import type { Disposable , QuickInputButton } from 'vscode' ;
1+ import type { Disposable , QuickInputButton , QuickPickItem } from 'vscode' ;
22import { env , ThemeIcon , Uri , window } from 'vscode' ;
33import type { OpenOnRemoteCommandArgs } from '../commands/openOnRemote' ;
44import { SetRemoteAsDefaultQuickInputButton } from '../commands/quickCommand.buttons' ;
55import type { Keys } from '../constants' ;
66import { GlyphChars } from '../constants' ;
77import { GlCommand } from '../constants.commands' ;
8+ import type { IntegrationId } from '../constants.integrations' ;
9+ import type { Sources } from '../constants.telemetry' ;
810import { Container } from '../container' ;
11+ import { RequiresIntegrationError } from '../errors' ;
912import type { GitRemote } from '../git/models/remote' ;
1013import type { RemoteResource } from '../git/models/remoteResource' ;
1114import { RemoteResourceType } from '../git/models/remoteResource' ;
@@ -14,10 +17,12 @@ import { getDefaultBranchName } from '../git/utils/-webview/branch.utils';
1417import { getBranchNameWithoutRemote , getRemoteNameFromBranchName } from '../git/utils/branch.utils' ;
1518import { getHighlanderProviders } from '../git/utils/remote.utils' ;
1619import { getNameFromRemoteResource } from '../git/utils/remoteResource.utils' ;
20+ import { remoteProviderIdToIntegrationId } from '../plus/integrations/integrationService' ;
21+ import { providersMetadata } from '../plus/integrations/providers/models' ;
1722import { getQuickPickIgnoreFocusOut } from '../system/-webview/vscode' ;
18- import { filterMap } from '../system/array' ;
1923import { getSettledValue } from '../system/promise' ;
20- import { CommandQuickPickItem } from './items/common' ;
24+ import { CommandQuickPickItem , createQuickPickItemOfT } from './items/common' ;
25+ import { createDirectiveQuickPickItem , Directive } from './items/directive' ;
2126
2227export class ConfigureCustomRemoteProviderCommandQuickPickItem extends CommandQuickPickItem {
2328 constructor ( ) {
@@ -69,6 +74,20 @@ export class CopyOrOpenRemoteCommandQuickPickItem extends CommandQuickPickItem {
6974 ...resource ,
7075 base : { branch : branch , remote : { path : this . remote . path , url : this . remote . url } } ,
7176 } ;
77+
78+ if (
79+ resource . base . remote . url !== resource . compare . remote . url &&
80+ ! ( await this . remote . provider . isReadyForForCrossForkPullRequestUrls ( ) )
81+ ) {
82+ const integrationId = remoteProviderIdToIntegrationId ( this . remote . provider . id ) ;
83+ const connected =
84+ integrationId && ( await this . showIntegrationConnectionPicker ( integrationId , 'view' ) ) ;
85+ if ( ! connected ) {
86+ throw new RequiresIntegrationError (
87+ 'Cross-fork pull request URLs are not supported by this provider' ,
88+ ) ;
89+ }
90+ }
7291 } else if (
7392 resource . type === RemoteResourceType . File &&
7493 resource . branchOrTag != null &&
@@ -97,11 +116,68 @@ export class CopyOrOpenRemoteCommandQuickPickItem extends CommandQuickPickItem {
97116 } ) ,
98117 ) ;
99118
100- const resources = filterMap ( resourcesResults , r => getSettledValue ( r ) ) ;
119+ const resources = resourcesResults
120+ . map ( r => {
121+ if ( r . status === 'fulfilled' ) {
122+ return r . value ;
123+ }
124+ if ( r . reason instanceof RequiresIntegrationError ) {
125+ throw r . reason ;
126+ }
127+ return undefined ;
128+ } )
129+ . filter ( ( r ) : r is RemoteResource => r !== undefined ) ;
101130
102131 void ( await ( this . clipboard ? this . remote . provider . copy ( resources ) : this . remote . provider . open ( resources ) ) ) ;
103132 }
104133
134+ async showIntegrationConnectionPicker ( integrationId : IntegrationId , source : Sources ) : Promise < boolean > {
135+ const disposables : Disposable [ ] = [ ] ;
136+ const quickpick = window . createQuickPick < QuickPickItem > ( ) ;
137+ try {
138+ const integrationName = providersMetadata [ integrationId ] . name ;
139+ const connectItem = createQuickPickItemOfT (
140+ {
141+ label : `Connect a ${ integrationName } Integration...` ,
142+ detail : `Connect a ${ integrationName } integration to be able to create cross-fork pull requests` ,
143+ picked : true ,
144+ } ,
145+ true ,
146+ ) ;
147+ const cancelItem = createDirectiveQuickPickItem ( Directive . Cancel , false , { label : 'Cancel' } ) ;
148+ const quickpickPromise = new Promise < undefined | QuickPickItem > ( resolve => {
149+ disposables . push (
150+ quickpick . onDidHide ( ( ) => resolve ( undefined ) ) ,
151+ quickpick . onDidAccept ( ( ) => {
152+ if ( quickpick . activeItems . length !== 0 ) {
153+ resolve ( quickpick . activeItems [ 0 ] ) ;
154+ }
155+ } ) ,
156+ ) ;
157+ } ) ;
158+ quickpick . ignoreFocusOut = getQuickPickIgnoreFocusOut ( ) ;
159+ quickpick . title = `Connect a ${ integrationName } Integration` ;
160+ quickpick . placeholder = `Connect a ${ integrationName } integration to be able to create cross-fork pull requests` ;
161+ quickpick . matchOnDetail = true ;
162+ quickpick . items = [ connectItem , cancelItem ] ;
163+ quickpick . show ( ) ;
164+ const pick = await quickpickPromise ;
165+ if ( pick === connectItem ) {
166+ const connected = await Container . instance . integrations . connectCloudIntegrations (
167+ { integrationIds : [ integrationId ] } ,
168+ {
169+ source : source ,
170+ } ,
171+ ) ;
172+ return connected ;
173+ }
174+ } finally {
175+ quickpick . dispose ( ) ;
176+ disposables . forEach ( d => void d . dispose ( ) ) ;
177+ }
178+ return false ;
179+ }
180+
105181 setAsDefault ( ) : Promise < void > {
106182 return this . remote . setAsDefault ( true ) ;
107183 }
0 commit comments