refactor(frontend): adopt the lifecycle and the notification surface
The remaining views, brought onto the two mechanisms added earlier in this series. The lifecycle: every cached primary view moves its document listeners, intervals and event subscriptions off connect/disconnect and onto `viewActivated`/`viewDeactivated`, so `autotag-view` stops fielding keystrokes from Settings, `downloads-view`'s 30 s clock stops ticking for the session, and an off-screen view stops rendering on every search keystroke. `autotag-view` keeps a document listener only for Escape, whose dialogs Phase 5 migrates to wa-dialog anyway. The voice: the silent failures now speak — scan and full rescan (with a guard against the double-click the coalescing window allowed), job pause/resume/cancel, playlist delete, download request pause/remove/ clear, add and rename library, add-to-playlist, playlist track removal, autotag's dialogs and its apply, and favourite reverts. Both private toasts are gone, along with their CSS and keyframes. Playlist delete (single and the multi-select loop), download-request removal, download-client removal and a queue clear over 20 tracks ask first. Loading, empty and failed become three states rather than one, in `track-list` and `genre-details` — the first is on the first screen a new user ever sees — and the Settings index panel seeds itself with `GetIndexStatus()` instead of waiting forever for a change event. `smart-playlist-editor` and `download-picker` take the request-version guard `explore-view` already had. `track-details` loads through one memoised dynamic import in all ten openers, which is what takes its 42 kB out of the startup chunk: an un-upgraded custom element is a real HTMLElement on which `?.show()` throws, so each opener awaits it before touching the element its template already rendered.
This commit is contained in:
@@ -10,6 +10,7 @@ import { libraryStore } from '@store/library-store';
|
||||
import { EventsOn } from '@runtime/runtime';
|
||||
import { Events } from '../../events';
|
||||
import { designTokens } from '../../styles/tokens.css';
|
||||
import { ViewLifecycleMixin } from '../../utils/view-lifecycle';
|
||||
|
||||
type Shelf = home.Shelf;
|
||||
|
||||
@@ -36,7 +37,7 @@ const KIND_ICONS: Record<string, string> = {
|
||||
* cover do the two things a cover should: open the album, or play it.
|
||||
*/
|
||||
@customElement('home-view')
|
||||
export class HomeView extends LitElement {
|
||||
export class HomeView extends ViewLifecycleMixin(LitElement) {
|
||||
@state() private shelves: Shelf[] = [];
|
||||
|
||||
@state() private loading = true;
|
||||
@@ -194,8 +195,10 @@ export class HomeView extends LitElement {
|
||||
`,
|
||||
];
|
||||
|
||||
override connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
protected override onViewActivate(): void {
|
||||
// Reloaded on arrival rather than kept live: the shelves are a
|
||||
// judgement about the whole library, so the answer while the
|
||||
// page is off screen is of no interest to anyone.
|
||||
void this.load();
|
||||
|
||||
// A finished scan changes what every shelf would say, and the
|
||||
@@ -204,12 +207,10 @@ export class HomeView extends LitElement {
|
||||
this.unsubScan = EventsOn(Events.LibraryScanComplete, () => {
|
||||
void this.load();
|
||||
});
|
||||
}
|
||||
|
||||
override disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
this.unsubScan?.();
|
||||
this.unsubScan = undefined;
|
||||
this.whileActive(() => {
|
||||
this.unsubScan?.();
|
||||
this.unsubScan = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user