From 94cbf5e43d98c6142ed7de7d5b85a971d25127fa Mon Sep 17 00:00:00 2001 From: sua yoo Date: Tue, 11 Feb 2025 23:17:01 -0800 Subject: [PATCH] fix: Loading indicator fixes (#398) Resolves https://github.com/webrecorder/replayweb.page/issues/397 ## Changes - Uses animated logo when loading - Show non-animated logo for error and other states where user action is required. - Only shows progress bar if progress is >0 - Fixes WARC progress bar percentage lagging behind displayed "Loaded" values - Fixes "Cancel" not redirecting back to initial view - Removes extra spacing from logo image file --------- Co-authored-by: Henry Wilkinson Co-authored-by: Ilya Kreymer --- CHANGES.md | 5 + src/appmain.ts | 7 ++ .../replaywebpage-icon-color-animated.svg | 3 + src/assets/brand/replaywebpage-icon-color.svg | 2 +- src/loader.ts | 103 +++++++++++++----- 5 files changed, 91 insertions(+), 29 deletions(-) create mode 100644 src/assets/brand/replaywebpage-icon-color-animated.svg diff --git a/CHANGES.md b/CHANGES.md index d704497..b131a40 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,7 +2,12 @@ ## CHANGES +v2.3.0 + +- UI: Add animating spinner for loading, show progress bar only when progress is available + v2.2.5 + - Branding: Update Site Links and Branding by @Shrinks99 in https://github.com/webrecorder/replayweb.page/pull/375 - CI: Bump macos version to 13 and node to 20 in CI by @emma-sg in https://github.com/webrecorder/replayweb.page/pull/386 - CI: Rename exported `Embed` to `ReplayWebPage`, and export `EmbedReplayEvent` type by @emma-sg in https://github.com/webrecorder/replayweb.page/pull/384 diff --git a/src/appmain.ts b/src/appmain.ts index 403fa1c..09a902b 100644 --- a/src/appmain.ts +++ b/src/appmain.ts @@ -403,6 +403,7 @@ export class ReplayWebApp extends LitElement { @replay-favicons=${this.onFavIcons} @update-title=${this.onTitle} @coll-loaded=${this.onCollLoaded} + @coll-load-cancel=${this.onCollLoadCancel} @about-show=${() => (this.showAbout = true)} >`; } @@ -691,6 +692,12 @@ export class ReplayWebApp extends LitElement { } } + private onCollLoadCancel() { + this.sourceUrl = null; + this.loadInfo = null; + window.history.pushState({}, "", new URL(window.location.href).origin); + } + // @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'event' implicitly has an 'any' type. onTitle(event) { if (event.detail.title) { diff --git a/src/assets/brand/replaywebpage-icon-color-animated.svg b/src/assets/brand/replaywebpage-icon-color-animated.svg new file mode 100644 index 0000000..9d163fa --- /dev/null +++ b/src/assets/brand/replaywebpage-icon-color-animated.svg @@ -0,0 +1,3 @@ + diff --git a/src/assets/brand/replaywebpage-icon-color.svg b/src/assets/brand/replaywebpage-icon-color.svg index a5a9509..ad2e69f 100644 --- a/src/assets/brand/replaywebpage-icon-color.svg +++ b/src/assets/brand/replaywebpage-icon-color.svg @@ -1 +1 @@ - + diff --git a/src/loader.ts b/src/loader.ts index 829315e..3c7e38e 100644 --- a/src/loader.ts +++ b/src/loader.ts @@ -1,18 +1,36 @@ -import { LitElement, html, css, type PropertyValues } from "lit"; +import { LitElement, html, css, type PropertyValues, nothing } from "lit"; import { wrapCss } from "./misc"; import rwpLogo from "~assets/brand/replaywebpage-icon-color.svg"; +import rwpLogoAnimated from "~assets/brand/replaywebpage-icon-color-animated.svg"; import prettyBytes from "pretty-bytes"; import { parseURLSchemeHostPath } from "./pageutils"; import { property } from "lit/decorators.js"; import type { LoadInfo } from "./item"; +import { ifDefined } from "lit/directives/if-defined.js"; // =========================================================================== +/** + * @fires coll-load-cancel + */ +type LoadingState = + | "started" + | "waiting" + | "googledrive" + | "errored" + | "permission_needed"; + +const NO_ANIM_STATES: LoadingState[] = [ + "errored", + "googledrive", + "permission_needed", +]; + class Loader extends LitElement { @property({ type: String }) sourceUrl?: string; @property({ type: Object }) loadInfo: LoadInfo | null = null; - @property({ type: String }) state = "waiting"; + @property({ type: String }) state: LoadingState = "waiting"; @property({ type: Number }) progress = 0; @property({ type: Number }) percent = 0; @property({ type: Number }) currentSize = 0; @@ -259,7 +277,7 @@ You can select a file to upload from the main page by clicking the 'Choose File. } } - onCancel() { + async onCancel() { if (!this.worker) { return; } @@ -268,6 +286,16 @@ You can select a file to upload from the main page by clicking the 'Choose File. if (!this.noWebWorker) { this.worker.postMessage(msg); + + await this.updateComplete; + + this.dispatchEvent( + new CustomEvent("coll-load-cancel", { + bubbles: true, + composed: true, + }), + ); + return; } @@ -339,7 +367,9 @@ You can select a file to upload from the main page by clicking the 'Choose File. @@ -368,26 +398,7 @@ You can select a file to upload from the main page by clicking the 'Choose File. case "started": return html`
- - - - ${this.currentSize && this.totalSize - ? html`
- Loaded - ${prettyBytes(this.currentSize)} - of - - ${prettyBytes(this.totalSize)} - - ${this.extraMsg && - html`

(${this.extraMsg})

`} -
` - : html``} + ${!this.currentSize ? nothing : this.renderProgressBar()} ${!this.embed ? html`