diff --git a/__brick__/web/flutter_bootstrap.js b/__brick__/web/flutter_bootstrap.js new file mode 100644 index 0000000..f69eace --- /dev/null +++ b/__brick__/web/flutter_bootstrap.js @@ -0,0 +1,89 @@ +{{=<% %>=}}{{flutter_js}}<%={{ }}=%> +{{=<% %>=}}{{flutter_build_config}}<%={{ }}=%> + +const progressBar = document.querySelector('#progress-bar'); +const progressText = document.querySelector('#progress-text'); +const progressIndicator = document.querySelector('#progress-indicator'); + +async function readAssets() { + // NOTE: AssetManifest.json will be deprecated in favour of AssetManifest.bin: + // https://github.com/VeryGoodOpenSource/flutter_web_preloader/issues/28 + const response = await fetch('assets/AssetManifest.json'); + const manifest = await response.json(); + const assets = Object.values(manifest) + .map((list) => list.map((url) => 'assets/' + url)) + .reduce((arr, curr) => [...arr, ...curr], []); + return assets; +} + +async function beginPreloading() { + const assets = await readAssets(); + + let totalAssets = assets.length; + if (totalAssets === 0) { + // No assets to load, so we can skip the loading process entirely. + return; + } + + let loadedAssets = 0; + const batchSize = {{batch_size}}; + + progressIndicator.style.width = '0%'; + progressText.textContent = `Loaded ${loadedAssets} of ${totalAssets} assets`; + + async function reportProgress() { + loadedAssets++; + + const value = Math.floor((loadedAssets / totalAssets) * 100) + '%'; + progressIndicator.style.width = value; + + progressText.textContent = `Loaded ${loadedAssets} of ${totalAssets} assets`; + } + + async function load(url) { + return new Promise((resolve, reject) => { + const req = new XMLHttpRequest(); + + req.onload = function() { + if (req.status >= 200 && req.status < 300) { + resolve(req.response); + } else { + reject(new Error(`Failed to load: ${req.status} ${req.statusText}`)); + } + }; + + req.onerror = function() { + reject(new Error('Network error')); + }; + + req.open('GET', url); + req.send(); + }); + } + + async function loadBatch(urls) { + const loadPromises = urls.map(url => load(url).then(reportProgress())); + try { + return await Promise.all(loadPromises); + } catch (error) { + console.error('Error loading one or more asset:', error); + } + } + + for (let i = 0; i < assets.length; i += batchSize) { + const batch = assets.slice(i, i + batchSize); + await loadBatch(batch); + } +} + +_flutter.loader.load({ + serviceWorkerSettings: { + serviceWorkerVersion: {{=<% %>=}}{{flutter_service_worker_version}}<%={{ }}=%>, + }, + onEntrypointLoaded: async function(engineInitializer) { + await Promise.all([ + beginPreloading(), + engineInitializer.initializeEngine(), + ]).then(([_, appRunner]) => appRunner.runApp()); + } +}); diff --git a/__brick__/web/index.html b/__brick__/web/index.html index 1413515..2ea2402 100644 --- a/__brick__/web/index.html +++ b/__brick__/web/index.html @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - {{project_title}} - - - - - - -
-
-
- + + + +
+
+
+
+
Initializing
+
+