@@ -40,6 +40,18 @@ const saveRepositoryPrConfig = ({ repositoryFullName, config }) => {
4040 }
4141}
4242
43+ const clearRepositoryPrConfig = repositoryFullName => {
44+ if ( typeof repositoryFullName !== 'string' || ! repositoryFullName . trim ( ) ) {
45+ return
46+ }
47+
48+ try {
49+ localStorage . removeItem ( `${ prConfigStoragePrefix } ${ repositoryFullName } ` )
50+ } catch {
51+ /* noop */
52+ }
53+ }
54+
4355const toSafeText = value => ( typeof value === 'string' ? value . trim ( ) : '' )
4456
4557const normalizeFilePath = value =>
@@ -92,10 +104,38 @@ const sanitizeBranchPart = value => {
92104 . replace ( / ^ [ - / . ] + | [ - / . ] + $ / g, '' )
93105}
94106
107+ const toUtcBranchStamp = ( ) => {
108+ const now = new Date ( )
109+ const parts = [
110+ String ( now . getUTCFullYear ( ) ) ,
111+ String ( now . getUTCMonth ( ) + 1 ) . padStart ( 2 , '0' ) ,
112+ String ( now . getUTCDate ( ) ) . padStart ( 2 , '0' ) ,
113+ String ( now . getUTCHours ( ) ) . padStart ( 2 , '0' ) ,
114+ String ( now . getUTCMinutes ( ) ) . padStart ( 2 , '0' ) ,
115+ String ( now . getUTCSeconds ( ) ) . padStart ( 2 , '0' ) ,
116+ ]
117+
118+ return `${ parts [ 0 ] } ${ parts [ 1 ] } ${ parts [ 2 ] } -${ parts [ 3 ] } ${ parts [ 4 ] } ${ parts [ 5 ] } `
119+ }
120+
121+ const createBranchEntropySuffix = ( ) => Math . random ( ) . toString ( 36 ) . slice ( 2 , 6 )
122+
123+ const isAutoGeneratedHeadBranch = value => {
124+ const branch = sanitizeBranchPart ( value )
125+ if ( ! branch ) {
126+ return false
127+ }
128+
129+ return / ^ d e v e l o p \/ [ ^ / ] + \/ e d i t o r - s y n c - \d { 8 } (?: - \d { 6 } ) ? (?: - [ a - z 0 - 9 ] { 4 } ) ? (?: - \d + ) ? $ / . test (
130+ branch ,
131+ )
132+ }
133+
95134const createDefaultBranchName = repository => {
96135 const repoName = sanitizeBranchPart ( repository ?. name ?? '' ) || 'repo'
97- const stamp = new Date ( ) . toISOString ( ) . slice ( 0 , 10 ) . replace ( / - / g, '' )
98- return `develop/${ repoName } /editor-sync-${ stamp } `
136+ const stamp = toUtcBranchStamp ( )
137+ const entropy = createBranchEntropySuffix ( )
138+ return `develop/${ repoName } /editor-sync-${ stamp } -${ entropy } `
99139}
100140
101141const toDefaultPrTitle = repository => {
@@ -156,6 +196,7 @@ export const createGitHubPrDrawer = ({
156196 getStylesSource,
157197 getDrawerSide,
158198 confirmBeforeSubmit,
199+ onPullRequestOpened,
159200} ) => {
160201 if ( ! featureEnabled ) {
161202 toggleButton ?. setAttribute ( 'hidden' , '' )
@@ -174,6 +215,11 @@ export const createGitHubPrDrawer = ({
174215 let open = false
175216 let submitting = false
176217 let pendingAbortController = null
218+ let resetOnNextOpen = false
219+ const submitButtonDefaultLabel =
220+ submitButton instanceof HTMLButtonElement && toSafeText ( submitButton . textContent )
221+ ? toSafeText ( submitButton . textContent )
222+ : 'Open PR'
177223
178224 const setStatus = ( text , level = 'neutral' ) => {
179225 if ( ! statusNode ) {
@@ -190,6 +236,8 @@ export const createGitHubPrDrawer = ({
190236 if ( submitButton instanceof HTMLButtonElement ) {
191237 submitButton . disabled = isPending
192238 submitButton . setAttribute ( 'aria-busy' , isPending ? 'true' : 'false' )
239+ submitButton . classList . toggle ( 'render-button--loading' , isPending )
240+ submitButton . textContent = isPending ? 'Opening PR...' : submitButtonDefaultLabel
193241 }
194242
195243 for ( const input of [
@@ -266,10 +314,10 @@ export const createGitHubPrDrawer = ({
266314 repositorySelect . value = selectedFullName
267315 }
268316
269- const syncFormForRepository = ( { resetBranch = false } = { } ) => {
317+ const syncFormForRepository = ( { resetBranch = false , resetAll = false } = { } ) => {
270318 const repository = getSelectedRepositoryObject ( )
271319 const repositoryFullName = getRepositoryFullName ( repository )
272- const savedConfig = readRepositoryPrConfig ( repositoryFullName )
320+ const savedConfig = resetAll ? { } : readRepositoryPrConfig ( repositoryFullName )
273321
274322 const componentFilePath =
275323 typeof savedConfig . componentFilePath === 'string' && savedConfig . componentFilePath
@@ -298,21 +346,24 @@ export const createGitHubPrDrawer = ({
298346 }
299347
300348 if ( headBranchInput instanceof HTMLInputElement ) {
301- if ( resetBranch || ! toSafeText ( headBranchInput . value ) ) {
349+ if ( resetAll || resetBranch || ! toSafeText ( headBranchInput . value ) ) {
350+ const savedHeadBranch = sanitizeBranchPart ( savedConfig . headBranch )
302351 headBranchInput . value =
303- toSafeText ( savedConfig . headBranch ) || createDefaultBranchName ( repository )
352+ savedHeadBranch && ! isAutoGeneratedHeadBranch ( savedHeadBranch )
353+ ? savedHeadBranch
354+ : createDefaultBranchName ( repository )
304355 }
305356 }
306357
307358 if ( prTitleInput instanceof HTMLInputElement ) {
308- if ( ! toSafeText ( prTitleInput . value ) ) {
359+ if ( resetAll || ! toSafeText ( prTitleInput . value ) ) {
309360 prTitleInput . value =
310361 toSafeText ( savedConfig . prTitle ) || toDefaultPrTitle ( repository )
311362 }
312363 }
313364
314365 if ( prBodyInput instanceof HTMLTextAreaElement ) {
315- if ( ! toSafeText ( prBodyInput . value ) ) {
366+ if ( resetAll || ! toSafeText ( prBodyInput . value ) ) {
316367 prBodyInput . value =
317368 typeof savedConfig . prBody === 'string' && savedConfig . prBody
318369 ? savedConfig . prBody
@@ -335,7 +386,7 @@ export const createGitHubPrDrawer = ({
335386 componentFilePath : values . componentFilePath ,
336387 stylesFilePath : values . stylesFilePath ,
337388 baseBranch : values . baseBranch ,
338- headBranch : values . headBranch ,
389+ headBranch : isAutoGeneratedHeadBranch ( values . headBranch ) ? '' : values . headBranch ,
339390 prTitle : values . prTitle ,
340391 prBody : values . prBody ,
341392 } ,
@@ -364,7 +415,14 @@ export const createGitHubPrDrawer = ({
364415 drawer . toggleAttribute ( 'hidden' , ! open )
365416
366417 if ( open ) {
367- syncRepositories ( )
418+ const repositories = getWritableRepositories ?. ( ) ?? [ ]
419+ const selectedRepository = getSelectedRepositoryObject ( )
420+ syncRepositorySelect ( { repositories, selectedRepository } )
421+ syncFormForRepository ( {
422+ resetAll : resetOnNextOpen ,
423+ resetBranch : resetOnNextOpen ,
424+ } )
425+ resetOnNextOpen = false
368426 repositorySelect ?. focus ( )
369427 }
370428 }
@@ -455,6 +513,12 @@ export const createGitHubPrDrawer = ({
455513 url ? `Pull request opened: ${ url } ` : 'Pull request opened successfully.' ,
456514 'ok' ,
457515 )
516+ onPullRequestOpened ?. ( {
517+ url,
518+ pullRequestNumber : result . pullRequest . number ,
519+ } )
520+ clearRepositoryPrConfig ( repositoryLabel )
521+ resetOnNextOpen = true
458522 setOpen ( false )
459523 } )
460524 . catch ( error => {
@@ -465,6 +529,8 @@ export const createGitHubPrDrawer = ({
465529 const message =
466530 error instanceof Error ? error . message : 'Failed to open pull request.'
467531 setStatus ( `Open PR failed: ${ message } ` , 'error' )
532+ clearRepositoryPrConfig ( repositoryLabel )
533+ resetOnNextOpen = true
468534 } )
469535 . finally ( ( ) => {
470536 if ( pendingAbortController === abortController ) {
0 commit comments