|
52 | 52 | <script>window.PHOENIX_APP_CACHE_VERSION="LATEST";</script> |
53 | 53 | <!-- The app cache version is set by the pipeline version update script. Do not update manually.--> |
54 | 54 | <script> |
| 55 | + if(["dev.phcode.dev", "staging.phcode.dev"].includes(location.hostname) |
| 56 | + && localStorage.getItem("devDomainsEnabled") !== "true"){ |
| 57 | + alert("Hello explorer, you have reached a development version of phcode.dev that is not for general use and could be very unstable." + |
| 58 | + `\n\nIf you know what you are doing and what to visit the dev site, please go to https://${location.hostname}/devEnable.html to enable dev site and visit again.` + |
| 59 | + "\n\nYou will now be redirected to phcode.dev."); |
| 60 | + window.location = "https://phcode.dev"; |
| 61 | + } |
55 | 62 | if(location.href.startsWith("tauri://") || location.href.startsWith('https://tauri.localhost')){ |
56 | 63 | const errorMessage = `You should use custom protocol phtauri:// instead of tauri protocol ${location.href} .`; |
57 | 64 | alert(errorMessage); |
|
335 | 342 | window.PhoenixBaseURL = baseUrl; |
336 | 343 | }()); |
337 | 344 | </script> |
| 345 | + <script src="phoenix/virtualfs.js"></script> |
338 | 346 | <script> |
339 | | - if(["dev.phcode.dev", "staging.phcode.dev"].includes(location.hostname) |
340 | | - && localStorage.getItem("devDomainsEnabled") !== "true"){ |
341 | | - alert("Hello explorer, you have reached a development version of phcode.dev that is not for general use and could be very unstable." + |
342 | | - `\n\nIf you know what you are doing and what to visit the dev site, please go to https://${location.hostname}/devEnable.html to enable dev site and visit again.` + |
343 | | - "\n\nYou will now be redirected to phcode.dev."); |
344 | | - window.location = "https://phcode.dev"; |
345 | | - } |
346 | 347 | /*Bootstrap cache check. since index.html is always loaded network first, the cache reset code will always |
347 | 348 | be guaranteed to be hit on app update. |
348 | 349 | Note that this cannot be moved to a separate file and should be in index.html due to above reason. |
349 | 350 | This is a nuke cache option. Though mostly safe, Use it wisely to prevent slow startup when resetting. |
350 | 351 | */ |
351 | | - const urlParams = new URLSearchParams(window.location.search || ""); |
352 | | - const LESS_REFRESH_SCHEDULED_KEY = "lessRefreshScheduled"; |
353 | | - const shouldRefreshLess = window.localStorage.getItem(LESS_REFRESH_SCHEDULED_KEY) === 'yes'; |
354 | | - const CACHE_NAME_EVERYTHING = "everything"; |
355 | | - function _resetCacheIfNeeded() { |
356 | | - if(Phoenix.browser.isTauri) { |
357 | | - // no web cache in desktop builds |
358 | | - return; |
359 | | - } |
360 | | - const cacheKey = "browserCacheVersionKey"; |
361 | | - const newCacheVersion = "V16"; // just increment this number to V2, v3 etc. to force clear the cached content. |
362 | | - const lastClearedVersion = window.localStorage.getItem(cacheKey); |
363 | | - if(lastClearedVersion === null){ |
364 | | - // First load, no cache, return. |
365 | | - localStorage.setItem(cacheKey, newCacheVersion); |
| 352 | + async function _resetCacheIfNeeded() { |
| 353 | + if(Phoenix.browser.isTauri || Phoenix.isTestWindow) { |
| 354 | + // no web cache in desktop builds ot test windows |
366 | 355 | return; |
367 | 356 | } |
368 | 357 | if(!window.caches){ |
369 | | - console.error("CacheStorage Reset: API not supported by browser."); |
| 358 | + console.error("CacheStorage: API not supported by browser."); |
370 | 359 | } |
371 | | - if(lastClearedVersion !== newCacheVersion) { |
372 | | - window.cacheRefreshInProgress = true; |
373 | | - let openedCache; |
374 | | - console.log("CacheStorage Reset: Reset cache in progress.."); |
375 | | - caches.open(CACHE_NAME_EVERYTHING) |
376 | | - .then(cache => { |
377 | | - openedCache = cache; |
378 | | - return cache.keys(); |
379 | | - }) |
380 | | - .then(keys => { |
381 | | - let promises = [] |
382 | | - for(let key of keys){ |
383 | | - promises.push(openedCache.delete(key)); |
| 360 | + |
| 361 | + const LESS_REFRESH_SCHEDULED_KEY = "lessRefreshScheduled"; |
| 362 | + |
| 363 | + function _readFileSafe(readPath) { |
| 364 | + return new Promise(resolve =>{ |
| 365 | + fs.readFile(readPath, "utf8", (err, text)=>{ |
| 366 | + if(err){ |
| 367 | + console.error("Could not read", readPath) |
| 368 | + resolve(null); |
| 369 | + return; |
384 | 370 | } |
385 | | - console.log(`CacheStorage Reset: Deleting ${promises.length} cache entries from ${CACHE_NAME_EVERYTHING}`); |
386 | | - return Promise.all(promises); |
387 | | - }).then(() => { |
388 | | - console.log("CacheStorage Reset: Cache successfully reset"); |
389 | | - let totalWaitTime = 0, waitTime = 100, maxWaitTime = 3000; |
390 | | - let intervalTimer = setInterval(()=>{ |
391 | | - // wait for less to get loaded. less caches css in local storage in production urls |
392 | | - // and might not load new css classes if we don't reset. less doesn't cache in localhost. |
393 | | - totalWaitTime += waitTime; |
394 | | - if(window.less && less.refresh){ |
395 | | - localStorage.setItem(cacheKey, newCacheVersion); |
396 | | - localStorage.setItem(LESS_REFRESH_SCHEDULED_KEY, "yes"); |
397 | | - less.refresh(true).finally(()=>{ |
398 | | - localStorage.setItem(LESS_REFRESH_SCHEDULED_KEY, "no"); |
399 | | - location.reload(); |
400 | | - }); |
401 | | - clearInterval(intervalTimer); |
402 | | - } else if(totalWaitTime > maxWaitTime){ |
403 | | - // ignore less refresh, the app load itself is critical. less refresh we will try later |
404 | | - localStorage.setItem(cacheKey, newCacheVersion); |
405 | | - localStorage.setItem(LESS_REFRESH_SCHEDULED_KEY, "yes"); |
406 | | - location.reload(); |
407 | | - } |
408 | | - }, waitTime); |
409 | | - }).catch( e => { |
410 | | - console.error("Error while resetting cache", e); |
411 | | - window.cacheClearError = e; |
412 | | - window.cacheRefreshInProgress = false; |
413 | | - // try our luck loading phoenix as cache reset failed |
414 | | - if(window._loadPhoenixAfterSplashScreen) { |
415 | | - window._loadPhoenixAfterSplashScreen(); |
| 371 | + resolve(text); |
| 372 | + }); |
| 373 | + }); |
| 374 | + } |
| 375 | + |
| 376 | + function _writeFileSafe(writePath, text) { |
| 377 | + return new Promise(resolve =>{ |
| 378 | + fs.writeFile(writePath, text, "utf8", (err)=>{ |
| 379 | + if(err){ |
| 380 | + console.error("Could not written", writePath) |
416 | 381 | } |
417 | | - // throw again so that bugsnag can report if initialised. else bugsnag |
418 | | - // will report the error when it comes online via window.cacheClearError |
419 | | - throw e; |
| 382 | + resolve(err); |
420 | 383 | }); |
| 384 | + }); |
| 385 | + } |
| 386 | + |
| 387 | + const WEB_CACHE_FILE_PATH = "/webCacheVersion.txt"; |
| 388 | + /** |
| 389 | + * Clears legacy caches from the browser storage. This function is intended to be used |
| 390 | + * when migrating to a new cache management strategy. Safe to be deleted after sep-2024 |
| 391 | + * @return {Promise<void>} |
| 392 | + */ |
| 393 | + async function clearLegacyCache() { |
| 394 | + // as we switched to new versioned cache management, we will be clearing all the legacy cache. |
| 395 | + const legacyCacheName = "browserCacheVersionKey"; |
| 396 | + const lastClearedVersion = window.localStorage.getItem(legacyCacheName); |
| 397 | + if(lastClearedVersion){ |
| 398 | + // legacy cache detected |
| 399 | + console.log("Legacy cache detected, resetting..."); |
| 400 | + localStorage.removeItem(legacyCacheName); |
| 401 | + await window.caches.delete(legacyCacheName); |
| 402 | + localStorage.setItem(LESS_REFRESH_SCHEDULED_KEY, "yes"); |
| 403 | + if(window.fs){ |
| 404 | + await _writeFileSafe(WEB_CACHE_FILE_PATH, PHOENIX_APP_CACHE_VERSION); |
| 405 | + location.reload(); |
| 406 | + } else { |
| 407 | + location.reload(); |
| 408 | + } |
| 409 | + } |
421 | 410 | } |
| 411 | + await clearLegacyCache(); |
| 412 | + |
| 413 | + const currentCacheName = await _readFileSafe(WEB_CACHE_FILE_PATH); |
| 414 | + if(!currentCacheName) { |
| 415 | + // fresh install, no cache |
| 416 | + console.log("No cache detected, ignore if first boot or safari ITP."); |
| 417 | + await _writeFileSafe(WEB_CACHE_FILE_PATH, PHOENIX_APP_CACHE_VERSION); |
| 418 | + // on next reload, the new cache will be active and populated by service worker |
| 419 | + } else if(currentCacheName !== PHOENIX_APP_CACHE_VERSION) { |
| 420 | + // This is an upgrade we could in the future use the cacheManifest.json to increase update speed |
| 421 | + // by only selectively updating the changed files. |
| 422 | + console.log("Old version cache detected", currentCacheName, "purging and setting", PHOENIX_APP_CACHE_VERSION); |
| 423 | + await window.caches.delete(currentCacheName); |
| 424 | + await _writeFileSafe(WEB_CACHE_FILE_PATH, PHOENIX_APP_CACHE_VERSION); |
| 425 | + localStorage.setItem(LESS_REFRESH_SCHEDULED_KEY, "yes"); |
| 426 | + } |
| 427 | + |
| 428 | + const shouldRefreshLess = window.localStorage.getItem(LESS_REFRESH_SCHEDULED_KEY) === 'yes'; |
422 | 429 | if(shouldRefreshLess){ |
423 | 430 | let lessRefreshInterval = setInterval(()=>{ |
424 | 431 | // wait for less to get loaded. less caches css in local storage in production urls |
|
475 | 482 | document.body.classList.add('dark'); // This will later be overridden by the theme manager as required. |
476 | 483 | } |
477 | 484 | _removeSplashScreenIfNeeded(); |
478 | | - if(window.cacheRefreshInProgress){ |
479 | | - // We should not load anything while the cache is inconsistent. |
480 | | - // A page reload will be scheduled on successful clear. |
481 | | - return; |
482 | | - } |
483 | 485 | var loadJS = function(url, implementationCode, location, dataMainValue){ |
484 | 486 | //url is URL of external file, implementationCode is the code |
485 | 487 | //to be called from the file, location is the location to |
|
505 | 507 | }); |
506 | 508 | } else { |
507 | 509 | const interval = setInterval(()=>{ |
508 | | - if(PhStore){ |
| 510 | + if(window.PhStore){ |
509 | 511 | clearInterval(interval); |
510 | 512 | PhStore.storageReadyPromise |
511 | 513 | .finally(()=>{ |
|
528 | 530 | https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer |
529 | 531 | --> |
530 | 532 | <!-- Import the phoenix browser virtual file system --> |
531 | | - <script src="phoenix/virtualfs.js" defer></script> |
532 | 533 | <script src="phoenix/shell.js" type="module" defer></script> |
533 | 534 | <script src="phoenix/virtual-server-loader.js" type="module" defer></script> |
534 | 535 | <!-- node loader should come only after fs libs are loaded as we init fs libs with node fs urls--> |
|
0 commit comments