From 4940c2e99d6a7cadae46dbac3318baf2e4b79d0d Mon Sep 17 00:00:00 2001 From: Cera Samson Date: Fri, 15 Jul 2022 20:28:44 -0700 Subject: [PATCH] Improve Default Blazor WebAssembly Loading Experience (#42548) * Added loader SVG and CSS styling * Add WebAssemblyProgressService, WebAssemblyProgressReporter * Add styling for setProgress, fix resourcesTotal * Implement singleton pattern, fix CSS styling * Convert % text to SVG * Add WebAssemblyProgressService as IBlazor global export * Modify CSS classes, added TSDoc to public methods * Modify CSS element names * Update src/Components/Web.JS/src/Boot.WebAssembly.ts * Co-authored-by: Tanay Parikh * Update src/Components/Web.JS/src/Platform/WebAssemblyProgressReporter.ts * Co-authored-by: Tanay Parikh * Check for additional resources; percentage styling * Update app.css * Create global SetProgress, pass in ProgressService * Vertically center loading circle * Update Boot.WebAssembly.ts * Update src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts * Co-authored-by: Tanay Parikh * Fix possible undefined wasmLoadingSetProgress * Remove setProgressFunction from GlobalExports * Update blazor.server.js * Update src/Components/Web.JS/src/Platform/WebAssemblyProgressReporter.ts * Co-authored-by: Tanay Parikh * Update src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts * Co-authored-by: Tanay Parikh * Update src/Components/Web.JS/src/Platform/WebAssemblyStartOptions.ts * Co-authored-by: Tanay Parikh * Remove progress ring transition duration * Update src/Components/Web.JS/src/Platform/WebAssemblyStartOptions.ts * (WIP) Bring all .ts changes to MonoPlatform.ts * Remove reporter/service classes, update loading styling * Center percentage text * Update app.css * Add additional checks for element types * Prevent exception by changing to div id = "app" * Update src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts * Co-authored-by: Tanay Parikh * WIP remove CSS id * Concat promises for setProgress function * Update src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts * Co-authored-by: Tanay Parikh * Update src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts * Co-authored-by: Tanay Parikh * CSS updates * Update src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/wwwroot/css/app.css * Co-authored-by: Steve Sanderson * Update src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts * Co-authored-by: Tanay Parikh * Update src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/wwwroot/css/app.css * Co-authored-by: Steve Sanderson * Add default "Loading" test * Update Templates.Blazor.WebAssembly.Tests.csproj * Update Templates.Blazor.WebAssembly.Tests.csproj Co-authored-by: Tanay Parikh Co-authored-by: Steve Sanderson --- .../Web.JS/src/Platform/Mono/MonoPlatform.ts | 14 ++++++++ .../Client/wwwroot/css/app.css | 35 ++++++++++++++++++- .../Client/wwwroot/index.html | 8 ++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts index 0aa9efa09d7e..cea18bf7f37f 100644 --- a/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts +++ b/src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts @@ -249,6 +249,14 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc const existingPostRun = moduleConfig.postRun || []; (moduleConfig as any).preloadPlugins = []; + let resourcesLoaded = 0; + function setProgress(){ + resourcesLoaded++; + const percentage = resourcesLoaded / totalResources.length * 100; + document.documentElement.style.setProperty('--blazor-load-percentage', `${percentage}%`); + document.documentElement.style.setProperty('--blazor-load-percentage-text', `"${Math.floor(percentage)}%"`); + } + // Begin loading the .dll/.pdb/.wasm files, but don't block here. Let other loading processes run in parallel. const dotnetWasmResourceName = 'dotnet.wasm'; const assembliesBeingLoaded = resourceLoader.loadResources(resources.assembly, filename => `_framework/${filename}`, 'assembly'); @@ -259,6 +267,8 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc /* hash */ resourceLoader.bootConfig.resources.runtime[dotnetWasmResourceName], /* type */ 'dotnetwasm' ); + const totalResources = assembliesBeingLoaded.concat(pdbsBeingLoaded, wasmBeingLoaded); + totalResources.forEach(loadingResource => loadingResource.response.then(_ => setProgress())); const dotnetTimeZoneResourceName = 'dotnet.timezones.blat'; let timeZoneResource: LoadingResource | undefined; @@ -269,6 +279,8 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc resourceLoader.bootConfig.resources.runtime[dotnetTimeZoneResourceName], 'globalization' ); + totalResources.push(timeZoneResource); + timeZoneResource.response.then(_ => setProgress()); } let icuDataResource: LoadingResource | undefined; @@ -281,6 +293,8 @@ async function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourc resourceLoader.bootConfig.resources.runtime[icuDataResourceName], 'globalization' ); + totalResources.push(icuDataResource); + icuDataResource.response.then(_ => setProgress()); } const createDotnetRuntime = await dotnetJsBeingLoaded; diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/wwwroot/css/app.css b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/wwwroot/css/app.css index 9cd148f7d532..443d784c4d14 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/wwwroot/css/app.css +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/wwwroot/css/app.css @@ -1,4 +1,4 @@ -@import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); +@import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); html, body { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; @@ -62,3 +62,36 @@ a, .btn-link { .blazor-error-boundary::after { content: "An error has occurred." } + +.loading-progress { + position: relative; + display: block; + width: 8rem; + height: 8rem; + margin: 20vh auto 1rem auto; +} + + .loading-progress circle { + fill: none; + stroke: #e0e0e0; + stroke-width: 0.6rem; + transform-origin: 50% 50%; + transform: rotate(-90deg); + } + + .loading-progress circle:last-child { + stroke: #1b6ec2; + stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%; + transition: stroke-dasharray 0.05s ease-in-out; + } + +.loading-progress-text { + position: absolute; + text-align: center; + font-weight: bold; + inset: calc(20vh + 3.25rem) 0 auto 0.2rem; +} + + .loading-progress-text:after { + content: var(--blazor-load-percentage-text, "Loading"); + } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/wwwroot/index.html b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/wwwroot/index.html index eeae5479bcbb..4d7c7088ad90 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/wwwroot/index.html +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/wwwroot/index.html @@ -22,7 +22,13 @@ -
Loading...
+
+ + + + +
+
An unhandled error has occurred.