@@ -68,17 +68,13 @@ export class ConfirmationDialog {
6868 const interfaceId = this . #interfaceId;
6969
7070 const isConfirmationGranted = new Promise < boolean > ( ( resolve , reject ) => {
71- // cleanup can't be defined before the click handlers, so cannot be const
72- // eslint-disable-next-line prefer-const
73- let cleanup : ( ) => Promise < void > ;
74-
7571 const { unbind : unbindGrantButtonClick } = this . #userEventDispatcher. on ( {
7672 elementName : ConfirmationDialog . #grantButton,
7773 eventType : UserInputEventType . ButtonClickEvent ,
7874 interfaceId,
7975 handler : async ( ) => {
80- await cleanup ( ) ;
81-
76+ await this . # cleanup( ) ;
77+ this . #interfaceId = undefined ;
8278 resolve ( true ) ;
8379 } ,
8480 } ) ;
@@ -88,38 +84,18 @@ export class ConfirmationDialog {
8884 eventType : UserInputEventType . ButtonClickEvent ,
8985 interfaceId,
9086 handler : async ( ) => {
91- await cleanup ( ) ;
92-
87+ await this . # cleanup( ) ;
88+ this . #interfaceId = undefined ;
9389 resolve ( false ) ;
9490 } ,
9591 } ) ;
9692
97- cleanup = async ( ) => {
98- unbindGrantButtonClick ( ) ;
99- unbindCancelButtonClick ( ) ;
100-
101- // clear our stored unbind handler reference
102- this . #unbindHandlers = undefined ;
103-
104- try {
105- await this . #snaps. request ( {
106- method : 'snap_resolveInterface' ,
107- params : {
108- id : interfaceId ,
109- value : { } ,
110- } ,
111- } ) ;
112- } catch ( error ) {
113- const reason = error as Error ;
114- reject ( reason ) ;
115- }
116- } ;
117-
11893 // store hooks so we can close/reject programmatically on error
11994 this . #unbindHandlers = ( ) => {
12095 unbindGrantButtonClick ( ) ;
12196 unbindCancelButtonClick ( ) ;
12297 } ;
98+
12399 this . #decisionReject = reject ;
124100
125101 // we don't await this, because we only want to present the dialog, and
@@ -131,6 +107,14 @@ export class ConfirmationDialog {
131107 id : interfaceId ,
132108 } ,
133109 } )
110+ . then ( async ( result ) => {
111+ // Should resolve with false when dialog is closed.
112+ if ( result === null ) {
113+ await this . #cleanup( false ) ;
114+
115+ resolve ( false ) ;
116+ }
117+ } )
134118 . catch ( ( error ) => {
135119 const reason = error as Error ;
136120 reject ( reason ) ;
@@ -142,6 +126,33 @@ export class ConfirmationDialog {
142126 } ;
143127 }
144128
129+ /**
130+ * Clean up event handlers and optionally resolve the interface.
131+ * @param resolveInterface - Whether to resolve the interface. Defaults to true.
132+ */
133+ async #cleanup( resolveInterface = true ) : Promise < void > {
134+ // Unbind any listeners to avoid leaks
135+ if ( this . #unbindHandlers) {
136+ try {
137+ this . #unbindHandlers( ) ;
138+ } catch {
139+ // ignore
140+ } finally {
141+ this . #unbindHandlers = undefined ;
142+ }
143+ }
144+
145+ if ( resolveInterface && this . #interfaceId) {
146+ await this . #snaps. request ( {
147+ method : 'snap_resolveInterface' ,
148+ params : {
149+ id : this . #interfaceId,
150+ value : { } ,
151+ } ,
152+ } ) ;
153+ }
154+ }
155+
145156 #buildConfirmation( ) : JSX . Element {
146157 return (
147158 < Container >
@@ -203,30 +214,11 @@ export class ConfirmationDialog {
203214 return ;
204215 }
205216
206- // Unbind any listeners to avoid leaks
207- if ( this . #unbindHandlers) {
208- try {
209- this . #unbindHandlers( ) ;
210- } catch {
211- // ignore
212- } finally {
213- this . #unbindHandlers = undefined ;
214- }
215- }
217+ // Clean up handlers and resolve interface
218+ await this . #cleanup( true ) ;
216219
217- try {
218- await this . #snaps. request ( {
219- method : 'snap_resolveInterface' ,
220- params : {
221- id : this . #interfaceId,
222- value : { } ,
223- } ,
224- } ) ;
225- } catch ( error ) {
226- // If closing fails, still reject with the original reason
227- } finally {
228- this . #interfaceId = undefined ;
229- }
220+ // Clear interface ID after cleanup
221+ this . #interfaceId = undefined ;
230222
231223 if ( this . #decisionReject) {
232224 this . #decisionReject( reason ) ;
0 commit comments