|
10 | 10 | let loadingHidden = false; |
11 | 11 | let blazorReady = false; |
12 | 12 | let initialRenderComplete = false; |
| 13 | + let monacoReady = false; |
13 | 14 |
|
14 | 15 | // Load required stylesheets |
15 | 16 | function loadStyles() { |
|
31 | 32 | }); |
32 | 33 | } |
33 | 34 |
|
34 | | - // Load required scripts |
35 | | - function loadScripts() { |
| 35 | + // Load Monaco Editor first with proper sequencing |
| 36 | + function loadMonacoEditor() { |
| 37 | + return new Promise((resolve, reject) => { |
| 38 | + // First load the Monaco loader |
| 39 | + const loaderScript = document.createElement('script'); |
| 40 | + loaderScript.src = '_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js'; |
| 41 | + loaderScript.onload = () => { |
| 42 | + // Configure RequireJS paths for Monaco |
| 43 | + if (typeof require !== 'undefined') { |
| 44 | + require.config({ |
| 45 | + paths: { |
| 46 | + 'vs': '_content/BlazorMonaco/lib/monaco-editor/min/vs' |
| 47 | + } |
| 48 | + }); |
| 49 | + |
| 50 | + // Load Monaco editor main |
| 51 | + require(['vs/editor/editor.main'], () => { |
| 52 | + console.log('Monaco editor loaded successfully'); |
| 53 | + monacoReady = true; |
| 54 | + resolve(); |
| 55 | + }, (error) => { |
| 56 | + console.error('Failed to load Monaco editor:', error); |
| 57 | + reject(error); |
| 58 | + }); |
| 59 | + } else { |
| 60 | + // Fallback: load editor.main.js directly |
| 61 | + const editorScript = document.createElement('script'); |
| 62 | + editorScript.src = '_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js'; |
| 63 | + editorScript.onload = () => { |
| 64 | + console.log('Monaco editor loaded (fallback method)'); |
| 65 | + monacoReady = true; |
| 66 | + resolve(); |
| 67 | + }; |
| 68 | + editorScript.onerror = reject; |
| 69 | + document.body.appendChild(editorScript); |
| 70 | + } |
| 71 | + }; |
| 72 | + loaderScript.onerror = reject; |
| 73 | + document.body.appendChild(loaderScript); |
| 74 | + }); |
| 75 | + } |
| 76 | + |
| 77 | + // Load remaining scripts after Monaco is ready |
| 78 | + function loadOtherScripts() { |
36 | 79 | const scripts = [ |
37 | 80 | '_content/BlazorMonaco/jsInterop.js', |
38 | | - '_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js', |
39 | | - '_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js', |
40 | 81 | '_content/MudBlazor/MudBlazor.min.js', |
41 | 82 | '_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js', |
42 | 83 | '_content/Radzen.Blazor/Radzen.Blazor.js', |
43 | 84 | '_framework/blazor.server.js' |
44 | 85 | ]; |
45 | 86 |
|
46 | | - scripts.forEach(src => { |
47 | | - if (!document.querySelector(`script[src="${src}"]`)) { |
| 87 | + const loadPromises = scripts.map(src => { |
| 88 | + return new Promise((resolve, reject) => { |
| 89 | + if (document.querySelector(`script[src="${src}"]`)) { |
| 90 | + resolve(); // Already loaded |
| 91 | + return; |
| 92 | + } |
| 93 | + |
48 | 94 | const script = document.createElement('script'); |
49 | 95 | script.src = src; |
| 96 | + script.onload = resolve; |
| 97 | + script.onerror = reject; |
50 | 98 | document.body.appendChild(script); |
51 | | - } |
| 99 | + }); |
52 | 100 | }); |
| 101 | + |
| 102 | + return Promise.all(loadPromises); |
| 103 | + } |
| 104 | + |
| 105 | + // Load all scripts in proper sequence |
| 106 | + async function loadScripts() { |
| 107 | + try { |
| 108 | + console.log('Loading Monaco editor...'); |
| 109 | + await loadMonacoEditor(); |
| 110 | + console.log('Loading other scripts...'); |
| 111 | + await loadOtherScripts(); |
| 112 | + console.log('All scripts loaded successfully'); |
| 113 | + } catch (error) { |
| 114 | + console.error('Script loading failed:', error); |
| 115 | + // Continue anyway - some features might still work |
| 116 | + } |
53 | 117 | } |
54 | 118 |
|
55 | 119 | // Inject loading screen HTML |
|
83 | 147 | document.head.insertAdjacentHTML('beforeend', loadingStyle); |
84 | 148 | } |
85 | 149 |
|
86 | | - // Update loading text (minimal usage) |
87 | | - function updateLoadingText(text) { |
88 | | - const loadingTextEl = document.getElementById('elsa-loading-text'); |
89 | | - if (loadingTextEl) { |
90 | | - loadingTextEl.textContent = text; |
91 | | - } |
92 | | - } |
93 | | - |
94 | 150 | // Hide loading screen when actually ready |
95 | 151 | function hideLoadingScreen() { |
96 | 152 | if (!loadingHidden) { |
|
102 | 158 |
|
103 | 159 | // Check if we should hide loading screen |
104 | 160 | function checkReadiness() { |
105 | | - if (blazorReady && initialRenderComplete && !loadingHidden) { |
| 161 | + if (blazorReady && initialRenderComplete && monacoReady && !loadingHidden) { |
106 | 162 | hideLoadingScreen(); |
107 | 163 | } |
108 | 164 | } |
109 | 165 |
|
110 | 166 | // Detect when Blazor Server connection is established |
111 | 167 | function detectBlazorConnection() { |
112 | | - // Check for Blazor global object and connection |
113 | 168 | if (typeof window.Blazor !== 'undefined') { |
114 | | - // Monitor for SignalR connection |
115 | 169 | const originalLog = console.log; |
116 | 170 | console.log = function(...args) { |
117 | 171 | const message = args.join(' '); |
|
123 | 177 | }; |
124 | 178 | } |
125 | 179 |
|
126 | | - // Check for Blazor Server specific DOM changes |
127 | 180 | const observer = new MutationObserver(function(mutations) { |
128 | 181 | mutations.forEach(function(mutation) { |
129 | 182 | if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { |
130 | 183 | for (let node of mutation.addedNodes) { |
131 | 184 | if (node.nodeType === Node.ELEMENT_NODE) { |
132 | | - // Check for Blazor component markers |
133 | 185 | if (node.hasAttribute && ( |
134 | 186 | node.hasAttribute('_bl_') || |
135 | 187 | node.querySelector && node.querySelector('[_bl_]') || |
|
152 | 204 | attributes: true |
153 | 205 | }); |
154 | 206 |
|
155 | | - // Stop observing after readiness is detected |
156 | 207 | setTimeout(() => { |
157 | 208 | if (blazorReady || loadingHidden) { |
158 | 209 | observer.disconnect(); |
|
162 | 213 |
|
163 | 214 | // Detect when initial render is complete |
164 | 215 | function detectRenderCompletion() { |
165 | | - // Check for common Blazor/MudBlazor elements |
166 | 216 | function checkForMainContent() { |
167 | 217 | const indicators = [ |
168 | 218 | '.mud-main-content', |
|
184 | 234 | return false; |
185 | 235 | } |
186 | 236 |
|
187 | | - // Use requestAnimationFrame to detect when rendering settles |
188 | 237 | let frameCount = 0; |
189 | 238 | let lastBodyHeight = 0; |
190 | 239 | let stableFrames = 0; |
|
195 | 244 |
|
196 | 245 | if (currentHeight === lastBodyHeight && currentHeight > 100) { |
197 | 246 | stableFrames++; |
198 | | - if (stableFrames >= 5) { // 5 stable frames |
| 247 | + if (stableFrames >= 5) { |
199 | 248 | if (!initialRenderComplete && checkForMainContent()) { |
200 | 249 | return; |
201 | 250 | } else if (!initialRenderComplete && frameCount > 30) { |
|
212 | 261 | if (frameCount < 100 && !initialRenderComplete) { |
213 | 262 | requestAnimationFrame(checkRenderStability); |
214 | 263 | } else if (!initialRenderComplete) { |
215 | | - // Fallback after 100 frames |
216 | 264 | initialRenderComplete = true; |
217 | 265 | checkReadiness(); |
218 | 266 | } |
219 | 267 | } |
220 | 268 |
|
221 | | - // Start checking on next frame |
222 | 269 | requestAnimationFrame(checkRenderStability); |
223 | 270 |
|
224 | | - // Also check periodically |
225 | 271 | const intervalCheck = setInterval(() => { |
226 | 272 | if (checkForMainContent()) { |
227 | 273 | clearInterval(intervalCheck); |
|
233 | 279 |
|
234 | 280 | // Enhanced Blazor Server initialization |
235 | 281 | function initializeBlazorServer(maxWaitMs) { |
236 | | - maxWaitMs = maxWaitMs || 8000; // Fallback timeout |
| 282 | + maxWaitMs = maxWaitMs || 8000; |
237 | 283 |
|
238 | | - // Start detection methods |
239 | 284 | setTimeout(() => detectBlazorConnection(), 100); |
240 | 285 | setTimeout(() => detectRenderCompletion(), 500); |
241 | 286 |
|
242 | | - // Ultimate fallback timeout |
243 | 287 | setTimeout(function() { |
244 | 288 | if (!loadingHidden) { |
245 | 289 | console.warn('Fallback timeout reached - forcing loading screen to hide'); |
246 | 290 | blazorReady = true; |
247 | 291 | initialRenderComplete = true; |
| 292 | + monacoReady = true; // Force ready on timeout |
248 | 293 | hideLoadingScreen(); |
249 | 294 | } |
250 | 295 | }, maxWaitMs); |
251 | 296 | } |
252 | 297 |
|
253 | | - // Initialize everything |
254 | | - function initialize() { |
| 298 | + // Initialize everything with proper sequencing |
| 299 | + async function initialize() { |
| 300 | + console.log('Starting Elsa Studio initialization...'); |
255 | 301 | loadStyles(); |
256 | 302 | injectLoadingScreen(); |
257 | | - loadScripts(); |
258 | | - initializeBlazorServer(8000); |
| 303 | + |
| 304 | + // Load scripts asynchronously but track completion |
| 305 | + loadScripts(); // Don't await - let it load in background |
| 306 | + |
| 307 | + initializeBlazorServer(10000); // Give more time for Monaco loading |
259 | 308 | } |
260 | 309 |
|
261 | 310 | // Run initialization |
|
265 | 314 | initialize(); |
266 | 315 | } |
267 | 316 |
|
268 | | - // Expose API for manual control if needed |
| 317 | + // Expose API |
269 | 318 | window.ElsaStudio = window.ElsaStudio || {}; |
270 | 319 | window.ElsaStudio.hideLoading = hideLoadingScreen; |
271 | | - window.ElsaStudio.updateLoadingText = updateLoadingText; |
272 | 320 | window.ElsaStudio.forceReady = function() { |
273 | 321 | blazorReady = true; |
274 | 322 | initialRenderComplete = true; |
| 323 | + monacoReady = true; |
275 | 324 | checkReadiness(); |
276 | 325 | }; |
277 | 326 |
|
|
0 commit comments