@@ -23,6 +23,7 @@ import { ReviewManager } from '../view/reviewManager';
2323export class PullRequestViewProvider extends WebviewViewBase implements vscode . WebviewViewProvider {
2424 public override readonly viewType = 'github:activePullRequest' ;
2525 private _existingReviewers : ReviewState [ ] = [ ] ;
26+ private _isUpdating : boolean = false ;
2627
2728 constructor (
2829 extensionUri : vscode . Uri ,
@@ -182,132 +183,143 @@ export class PullRequestViewProvider extends WebviewViewBase implements vscode.W
182183 disposeAll ( this . _prDisposables ) ;
183184 }
184185 this . _prDisposables = [ ] ;
185- this . _prDisposables . push ( pullRequestModel . onDidChange ( ( ) => this . updatePullRequest ( pullRequestModel ) ) ) ;
186+ this . _prDisposables . push ( pullRequestModel . onDidChange ( e => {
187+ if ( ( e . state || e . comments || e . reviewers ) && ! this . _isUpdating ) {
188+ this . updatePullRequest ( pullRequestModel ) ;
189+ }
190+ } ) ) ;
186191 this . _prDisposables . push ( pullRequestModel . onDidChangePendingReviewState ( ( ) => this . updatePullRequest ( pullRequestModel ) ) ) ;
187192 }
188193
189194 private _updatePendingVisibility : vscode . Disposable | undefined = undefined ;
190195 public async updatePullRequest ( pullRequestModel : PullRequestModel ) : Promise < void > {
191- if ( this . _view && ! this . _view . visible ) {
192- this . _updatePendingVisibility ?. dispose ( ) ;
193- this . _updatePendingVisibility = this . _view . onDidChangeVisibility ( async ( ) => {
194- this . updatePullRequest ( pullRequestModel ) ;
195- this . _updatePendingVisibility ?. dispose ( ) ;
196- } ) ;
196+ if ( this . _isUpdating ) {
197+ throw new Error ( 'Already updating pull request view' ) ;
197198 }
199+ this . _isUpdating = true ;
198200
199- if ( ( this . _prDisposables === undefined ) || ( pullRequestModel . number !== this . _item . number ) ) {
200- this . registerPrSpecificListeners ( pullRequestModel ) ;
201- }
202- this . _item = pullRequestModel ;
203- return Promise . all ( [
204- this . _folderRepositoryManager . resolvePullRequest (
205- pullRequestModel . remote . owner ,
206- pullRequestModel . remote . repositoryName ,
207- pullRequestModel . number ,
208- ) ,
209- this . _folderRepositoryManager . getPullRequestRepositoryAccessAndMergeMethods ( pullRequestModel ) ,
210- pullRequestModel . getTimelineEvents ( ) ,
211- pullRequestModel . getReviewRequests ( ) ,
212- this . _folderRepositoryManager . getBranchNameForPullRequest ( pullRequestModel ) ,
213- this . _folderRepositoryManager . getPullRequestRepositoryDefaultBranch ( pullRequestModel ) ,
214- this . _folderRepositoryManager . getCurrentUser ( pullRequestModel . githubRepository ) ,
215- pullRequestModel . canEdit ( ) ,
216- pullRequestModel . validateDraftMode ( ) ,
217- ensureEmojis ( this . _folderRepositoryManager . context )
218- ] )
219- . then ( result => {
220- const [ pullRequest , repositoryAccess , timelineEvents , requestedReviewers , branchInfo , defaultBranch , currentUser , viewerCanEdit , hasReviewDraft ] = result ;
221- if ( ! pullRequest ) {
222- throw new Error (
223- `Fail to resolve Pull Request #${ pullRequestModel . number } in ${ pullRequestModel . remote . owner } /${ pullRequestModel . remote . repositoryName } ` ,
224- ) ;
225- }
201+ try {
202+ if ( this . _view && ! this . _view . visible ) {
203+ this . _updatePendingVisibility ?. dispose ( ) ;
204+ this . _updatePendingVisibility = this . _view . onDidChangeVisibility ( async ( ) => {
205+ this . updatePullRequest ( pullRequestModel ) ;
206+ this . _updatePendingVisibility ?. dispose ( ) ;
207+ } ) ;
208+ }
226209
227- this . _item = pullRequest ;
228- if ( ! this . _view ) {
229- // If the there is no PR webview, then there is nothing else to update.
230- return ;
231- }
210+ if ( ( this . _prDisposables === undefined ) || ( pullRequestModel . number !== this . _item . number ) ) {
211+ this . registerPrSpecificListeners ( pullRequestModel ) ;
212+ }
213+ this . _item = pullRequestModel ;
214+ const [ pullRequest , repositoryAccess , timelineEvents , requestedReviewers , branchInfo , defaultBranch , currentUser , viewerCanEdit , hasReviewDraft ] = await Promise . all ( [
215+ this . _folderRepositoryManager . resolvePullRequest (
216+ pullRequestModel . remote . owner ,
217+ pullRequestModel . remote . repositoryName ,
218+ pullRequestModel . number ,
219+ ) ,
220+ this . _folderRepositoryManager . getPullRequestRepositoryAccessAndMergeMethods ( pullRequestModel ) ,
221+ pullRequestModel . getTimelineEvents ( ) ,
222+ pullRequestModel . getReviewRequests ( ) ,
223+ this . _folderRepositoryManager . getBranchNameForPullRequest ( pullRequestModel ) ,
224+ this . _folderRepositoryManager . getPullRequestRepositoryDefaultBranch ( pullRequestModel ) ,
225+ this . _folderRepositoryManager . getCurrentUser ( pullRequestModel . githubRepository ) ,
226+ pullRequestModel . canEdit ( ) ,
227+ pullRequestModel . validateDraftMode ( ) ,
228+ ensureEmojis ( this . _folderRepositoryManager . context )
229+ ] ) ;
230+
231+ if ( ! pullRequest ) {
232+ throw new Error (
233+ `Fail to resolve Pull Request #${ pullRequestModel . number } in ${ pullRequestModel . remote . owner } /${ pullRequestModel . remote . repositoryName } ` ,
234+ ) ;
235+ }
232236
233- try {
234- this . _view . title = ` ${ vscode . l10n . t ( 'Review Pull Request' ) } # ${ pullRequestModel . number . toString ( ) } ` ;
235- } catch ( e ) {
236- // If we ry to set the title of the webview too early it will throw an error.
237- }
237+ this . _item = pullRequest ;
238+ if ( ! this . _view ) {
239+ // If the there is no PR webview, then there is nothing else to update.
240+ return ;
241+ }
238242
239- const isCurrentlyCheckedOut = pullRequestModel . equals ( this . _folderRepositoryManager . activePullRequest ) ;
240- const hasWritePermission = repositoryAccess ! . hasWritePermission ;
241- const mergeMethodsAvailability = repositoryAccess ! . mergeMethodsAvailability ;
242- const canEdit = hasWritePermission || viewerCanEdit ;
243- const defaultMergeMethod = getDefaultMergeMethod ( mergeMethodsAvailability ) ;
244- this . _existingReviewers = parseReviewers (
245- requestedReviewers ?? [ ] ,
246- timelineEvents ?? [ ] ,
247- pullRequest . author ,
248- ) ;
243+ try {
244+ this . _view . title = `${ vscode . l10n . t ( 'Review Pull Request' ) } #${ pullRequestModel . number . toString ( ) } ` ;
245+ } catch ( e ) {
246+ // If we ry to set the title of the webview too early it will throw an error.
247+ }
249248
250- const isCrossRepository =
251- pullRequest . base &&
252- pullRequest . head &&
253- ! pullRequest . base . repositoryCloneUrl . equals ( pullRequest . head . repositoryCloneUrl ) ;
254-
255- const continueOnGitHub = ! ! ( isCrossRepository && isInCodespaces ( ) ) ;
256- const reviewState = this . getCurrentUserReviewState ( this . _existingReviewers , currentUser ) ;
257-
258- const context : Partial < PullRequest > = {
259- number : pullRequest . number ,
260- title : pullRequest . title ,
261- url : pullRequest . html_url ,
262- createdAt : pullRequest . createdAt ,
263- body : pullRequest . body ,
264- bodyHTML : pullRequest . bodyHTML ,
265- labels : pullRequest . item . labels . map ( label => ( { ...label , displayName : emojify ( label . name ) } ) ) ,
266- author : {
267- login : pullRequest . author . login ,
268- name : pullRequest . author . name ,
269- avatarUrl : pullRequest . userAvatar ,
270- url : pullRequest . author . url ,
271- email : pullRequest . author . email ,
272- id : pullRequest . author . id ,
273- accountType : pullRequest . author . accountType ,
274- } ,
275- state : pullRequest . state ,
276- isCurrentlyCheckedOut : isCurrentlyCheckedOut ,
277- isRemoteBaseDeleted : pullRequest . isRemoteBaseDeleted ,
278- base : pullRequest . base . label ,
279- isRemoteHeadDeleted : pullRequest . isRemoteHeadDeleted ,
280- isLocalHeadDeleted : ! branchInfo ,
281- head : pullRequest . head ?. label ?? '' ,
282- canEdit : canEdit ,
283- hasWritePermission,
284- mergeable : pullRequest . item . mergeable ,
285- isDraft : pullRequest . isDraft ,
286- status : null ,
287- reviewRequirement : null ,
288- canUpdateBranch : pullRequest . item . viewerCanUpdate ,
289- events : timelineEvents ,
290- mergeMethodsAvailability,
291- defaultMergeMethod,
292- repositoryDefaultBranch : defaultBranch ,
293- isIssue : false ,
294- isAuthor : currentUser . login === pullRequest . author . login ,
295- reviewers : this . _existingReviewers ,
296- continueOnGitHub,
297- isDarkTheme : vscode . window . activeColorTheme . kind === vscode . ColorThemeKind . Dark ,
298- isEnterprise : pullRequest . githubRepository . remote . isEnterprise ,
299- hasReviewDraft,
300- currentUserReviewState : reviewState
301- } ;
302-
303- this . _postMessage ( {
304- command : 'pr.initialize' ,
305- pullrequest : context ,
306- } ) ;
307- } )
308- . catch ( e => {
309- vscode . window . showErrorMessage ( `Error updating active pull request view: ${ formatError ( e ) } ` ) ;
249+ const isCurrentlyCheckedOut = pullRequestModel . equals ( this . _folderRepositoryManager . activePullRequest ) ;
250+ const hasWritePermission = repositoryAccess ! . hasWritePermission ;
251+ const mergeMethodsAvailability = repositoryAccess ! . mergeMethodsAvailability ;
252+ const canEdit = hasWritePermission || viewerCanEdit ;
253+ const defaultMergeMethod = getDefaultMergeMethod ( mergeMethodsAvailability ) ;
254+ this . _existingReviewers = parseReviewers (
255+ requestedReviewers ?? [ ] ,
256+ timelineEvents ?? [ ] ,
257+ pullRequest . author ,
258+ ) ;
259+
260+ const isCrossRepository =
261+ pullRequest . base &&
262+ pullRequest . head &&
263+ ! pullRequest . base . repositoryCloneUrl . equals ( pullRequest . head . repositoryCloneUrl ) ;
264+
265+ const continueOnGitHub = ! ! ( isCrossRepository && isInCodespaces ( ) ) ;
266+ const reviewState = this . getCurrentUserReviewState ( this . _existingReviewers , currentUser ) ;
267+
268+ const context : Partial < PullRequest > = {
269+ number : pullRequest . number ,
270+ title : pullRequest . title ,
271+ url : pullRequest . html_url ,
272+ createdAt : pullRequest . createdAt ,
273+ body : pullRequest . body ,
274+ bodyHTML : pullRequest . bodyHTML ,
275+ labels : pullRequest . item . labels . map ( label => ( { ...label , displayName : emojify ( label . name ) } ) ) ,
276+ author : {
277+ login : pullRequest . author . login ,
278+ name : pullRequest . author . name ,
279+ avatarUrl : pullRequest . userAvatar ,
280+ url : pullRequest . author . url ,
281+ email : pullRequest . author . email ,
282+ id : pullRequest . author . id ,
283+ accountType : pullRequest . author . accountType ,
284+ } ,
285+ state : pullRequest . state ,
286+ isCurrentlyCheckedOut : isCurrentlyCheckedOut ,
287+ isRemoteBaseDeleted : pullRequest . isRemoteBaseDeleted ,
288+ base : pullRequest . base . label ,
289+ isRemoteHeadDeleted : pullRequest . isRemoteHeadDeleted ,
290+ isLocalHeadDeleted : ! branchInfo ,
291+ head : pullRequest . head ?. label ?? '' ,
292+ canEdit : canEdit ,
293+ hasWritePermission,
294+ mergeable : pullRequest . item . mergeable ,
295+ isDraft : pullRequest . isDraft ,
296+ status : null ,
297+ reviewRequirement : null ,
298+ canUpdateBranch : pullRequest . item . viewerCanUpdate ,
299+ events : timelineEvents ,
300+ mergeMethodsAvailability,
301+ defaultMergeMethod,
302+ repositoryDefaultBranch : defaultBranch ,
303+ isIssue : false ,
304+ isAuthor : currentUser . login === pullRequest . author . login ,
305+ reviewers : this . _existingReviewers ,
306+ continueOnGitHub,
307+ isDarkTheme : vscode . window . activeColorTheme . kind === vscode . ColorThemeKind . Dark ,
308+ isEnterprise : pullRequest . githubRepository . remote . isEnterprise ,
309+ hasReviewDraft,
310+ currentUserReviewState : reviewState
311+ } ;
312+
313+ this . _postMessage ( {
314+ command : 'pr.initialize' ,
315+ pullrequest : context ,
310316 } ) ;
317+
318+ } catch ( e ) {
319+ vscode . window . showErrorMessage ( `Error updating active pull request view: ${ formatError ( e ) } ` ) ;
320+ } finally {
321+ this . _isUpdating = false ;
322+ }
311323 }
312324
313325 private close ( message : IRequestMessage < string > ) : void {
0 commit comments