@@ -44,6 +44,9 @@ export const WebFrameComponent = observer(
44
44
const zoomLevel = useRef ( 1 ) ;
45
45
const isConnecting = useRef ( false ) ;
46
46
const connectionRef = useRef < ReturnType < typeof connect > | null > ( null ) ;
47
+ const retryCount = useRef ( 0 ) ;
48
+ const maxRetries = 3 ;
49
+ const baseDelay = 1000 ;
47
50
const [ penpalChild , setPenpalChild ] = useState < PenpalChildMethods | null > ( null ) ;
48
51
49
52
const undebouncedReloadIframe = ( ) => {
@@ -60,75 +63,109 @@ export const WebFrameComponent = observer(
60
63
leading : true ,
61
64
} ) ;
62
65
63
- const setupPenpalConnection = ( ) => {
64
- if ( ! iframeRef . current ?. contentWindow ) {
65
- console . error ( 'No iframe found' ) ;
66
- return ;
67
- }
68
-
69
- if ( isConnecting . current ) {
70
- console . log (
71
- `${ PENPAL_PARENT_CHANNEL } (${ frame . id } ) - Connection already in progress` ,
66
+ const retrySetupPenpalConnection = ( error ?: Error ) => {
67
+ if ( retryCount . current >= maxRetries ) {
68
+ console . error (
69
+ `${ PENPAL_PARENT_CHANNEL } (${ frame . id } ) - Max retries (${ maxRetries } ) reached, reloading iframe` ,
70
+ error ,
72
71
) ;
72
+ retryCount . current = 0 ;
73
+ reloadIframe ( ) ;
73
74
return ;
74
75
}
75
- isConnecting . current = true ;
76
76
77
- // Destroy any existing connection before creating a new one
78
- if ( connectionRef . current ) {
79
- connectionRef . current . destroy ( ) ;
80
- connectionRef . current = null ;
81
- }
77
+ retryCount . current += 1 ;
78
+ const delay = baseDelay * Math . pow ( 2 , retryCount . current - 1 ) ;
79
+
80
+ console . log (
81
+ `${ PENPAL_PARENT_CHANNEL } (${ frame . id } ) - Retrying connection attempt ${ retryCount . current } /${ maxRetries } in ${ delay } ms` ,
82
+ ) ;
82
83
83
- const messenger = new WindowMessenger ( {
84
- remoteWindow : iframeRef . current . contentWindow ,
85
- allowedOrigins : [ '*' ] ,
86
- } ) ;
87
-
88
- const connection = connect ( {
89
- messenger,
90
- methods : {
91
- getFrameId : ( ) => frame . id ,
92
- onWindowMutated : ( ) => {
93
- editorEngine . frameEvent . handleWindowMutated ( ) ;
94
- } ,
95
- onWindowResized : ( ) => {
96
- editorEngine . frameEvent . handleWindowResized ( ) ;
97
- } ,
98
- onDomProcessed : ( data : { layerMap : Record < string , any > ; rootNode : any } ) => {
99
- editorEngine . frameEvent . handleDomProcessed ( frame . id , data ) ;
100
- } ,
101
- } satisfies PenpalParentMethods ,
102
- } ) ;
84
+ setTimeout ( ( ) => {
85
+ setupPenpalConnection ( ) ;
86
+ } , delay ) ;
87
+ } ;
103
88
104
- // Store the connection reference
105
- connectionRef . current = connection ;
89
+ const setupPenpalConnection = ( ) => {
90
+ try {
91
+ if ( ! iframeRef . current ?. contentWindow ) {
92
+ console . error ( 'No iframe found' ) ;
93
+ throw new Error ( 'No iframe found' ) ;
94
+ }
106
95
107
- connection . promise . then ( ( child ) => {
108
- isConnecting . current = false ;
109
- if ( ! child ) {
110
- console . error (
111
- `${ PENPAL_PARENT_CHANNEL } (${ frame . id } ) - Failed to setup penpal connection: child is null` ,
96
+ if ( isConnecting . current ) {
97
+ console . log (
98
+ `${ PENPAL_PARENT_CHANNEL } (${ frame . id } ) - Connection already in progress` ,
112
99
) ;
113
- reloadIframe ( ) ;
114
100
return ;
115
101
}
116
- const remote = child as unknown as PenpalChildMethods ;
117
- setPenpalChild ( remote ) ;
118
- remote . setFrameId ( frame . id ) ;
119
- remote . handleBodyReady ( ) ;
120
- remote . processDom ( ) ;
121
- console . log ( `${ PENPAL_PARENT_CHANNEL } (${ frame . id } ) - Penpal connection set ` ) ;
122
- } ) ;
102
+ isConnecting . current = true ;
103
+
104
+ // Destroy any existing connection before creating a new one
105
+ if ( connectionRef . current ) {
106
+ connectionRef . current . destroy ( ) ;
107
+ connectionRef . current = null ;
108
+ }
109
+
110
+ const messenger = new WindowMessenger ( {
111
+ remoteWindow : iframeRef . current . contentWindow ,
112
+ allowedOrigins : [ '*' ] ,
113
+ } ) ;
114
+
115
+ const connection = connect ( {
116
+ messenger,
117
+ methods : {
118
+ getFrameId : ( ) => frame . id ,
119
+ onWindowMutated : ( ) => {
120
+ editorEngine . frameEvent . handleWindowMutated ( ) ;
121
+ } ,
122
+ onWindowResized : ( ) => {
123
+ editorEngine . frameEvent . handleWindowResized ( ) ;
124
+ } ,
125
+ onDomProcessed : ( data : { layerMap : Record < string , any > ; rootNode : any } ) => {
126
+ editorEngine . frameEvent . handleDomProcessed ( frame . id , data ) ;
127
+ } ,
128
+ } satisfies PenpalParentMethods ,
129
+ } ) ;
123
130
124
- connection . promise . catch ( ( error ) => {
131
+ // Store the connection reference
132
+ connectionRef . current = connection ;
133
+
134
+ connection . promise
135
+ . then ( ( child ) => {
136
+ isConnecting . current = false ;
137
+ if ( ! child ) {
138
+ const error = new Error ( 'Failed to setup penpal connection: child is null' ) ;
139
+ console . error (
140
+ `${ PENPAL_PARENT_CHANNEL } (${ frame . id } ) - ${ error . message } ` ,
141
+ ) ;
142
+ retrySetupPenpalConnection ( error ) ;
143
+ return ;
144
+ }
145
+
146
+ // Reset retry count on successful connection
147
+ retryCount . current = 0 ;
148
+
149
+ const remote = child as unknown as PenpalChildMethods ;
150
+ setPenpalChild ( remote ) ;
151
+ remote . setFrameId ( frame . id ) ;
152
+ remote . handleBodyReady ( ) ;
153
+ remote . processDom ( ) ;
154
+ console . log ( `${ PENPAL_PARENT_CHANNEL } (${ frame . id } ) - Penpal connection set ` ) ;
155
+ } )
156
+ . catch ( ( error ) => {
157
+ isConnecting . current = false ;
158
+ console . error (
159
+ `${ PENPAL_PARENT_CHANNEL } (${ frame . id } ) - Failed to setup penpal connection:` ,
160
+ error ,
161
+ ) ;
162
+ retrySetupPenpalConnection ( error ) ;
163
+ } ) ;
164
+ } catch ( error ) {
125
165
isConnecting . current = false ;
126
- console . error (
127
- `${ PENPAL_PARENT_CHANNEL } (${ frame . id } ) - Failed to setup penpal connection:` ,
128
- error ,
129
- ) ;
130
- reloadIframe ( ) ;
131
- } ) ;
166
+ console . error ( 'Failed to setup penpal connection' , error ) ;
167
+ retrySetupPenpalConnection ( error as Error ) ;
168
+ }
132
169
} ;
133
170
134
171
const promisifyMethod = < T extends ( ...args : any [ ] ) => any > (
0 commit comments