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:
@@ -27,6 +27,7 @@ import { libraryStore } from '../../store/library-store';
|
||||
import { downloadStore } from '../../store/download-store';
|
||||
import '@awesome.me/webawesome/dist/components/button/button.js';
|
||||
import { trackLink, exploreLinkStyles } from '../../utils/explore-link';
|
||||
import { describeError } from '../../utils/describe-error';
|
||||
import { GetAlbumsByArtist } from '@go/library/Library';
|
||||
import { EventsOn } from '@runtime/runtime';
|
||||
import { Events } from '../../events';
|
||||
@@ -1014,9 +1015,6 @@ export class ExploreArtistDetails extends LitElement {
|
||||
|
||||
// Local-only artist (no MBID) — populate from library store.
|
||||
if (!mbid && this.localArtistId) {
|
||||
console.log(
|
||||
`[explore-artist] loading local-only: "${this.artistName}" (id=${this.localArtistId})`,
|
||||
);
|
||||
|
||||
this.loadingArtist = false;
|
||||
this.loadingTracks = false;
|
||||
@@ -1027,16 +1025,10 @@ export class ExploreArtistDetails extends LitElement {
|
||||
|
||||
this.hydrateLocalOnly();
|
||||
|
||||
console.log(
|
||||
`[explore-artist] loaded (local-only): "${this.artistName}"`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[explore-artist] loading: "${this.artistName}" (${mbid})`,
|
||||
);
|
||||
|
||||
// Phase 0: hydrate from caches (instant, no Go calls).
|
||||
this.hydrateFromCache(mbid);
|
||||
@@ -1068,9 +1060,6 @@ export class ExploreArtistDetails extends LitElement {
|
||||
|
||||
// checkLibrary now runs from fetchReleaseGroups when data arrives.
|
||||
|
||||
console.log(
|
||||
`[explore-artist] data requests fired: "${this.artistName}" (${mbid})`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1290,9 +1279,11 @@ export class ExploreArtistDetails extends LitElement {
|
||||
try {
|
||||
this.artist = await LookupArtist(mbid);
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
this.errorArtist = msg;
|
||||
console.error(`[explore-artist] LookupArtist error: ${msg}`);
|
||||
console.error('[explore-artist] LookupArtist error', err);
|
||||
this.errorArtist = describeError(
|
||||
err,
|
||||
'The catalog did not answer.',
|
||||
);
|
||||
} finally {
|
||||
this.loadingArtist = false;
|
||||
}
|
||||
@@ -1326,10 +1317,7 @@ export class ExploreArtistDetails extends LitElement {
|
||||
|
||||
void this.batchResolveTrackThumbnails(tracks, mapping);
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
console.error(
|
||||
`[explore-artist] TopRecordingsForArtist error: ${msg}`,
|
||||
);
|
||||
console.error('[explore-artist] TopRecordingsForArtist error', err);
|
||||
} finally {
|
||||
// An empty first pass may mean a background discography fetch
|
||||
// is still in flight (the artist wasn't indexed yet). Keep
|
||||
@@ -1419,10 +1407,7 @@ export class ExploreArtistDetails extends LitElement {
|
||||
// are the most likely to be clicked from the artist page.
|
||||
this.prefetchReleases(rgs?.map((r) => r.releaseGroupMbid) ?? []);
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
console.error(
|
||||
`[explore-artist] TopReleaseGroupsForArtist error: ${msg}`,
|
||||
);
|
||||
console.error('[explore-artist] TopReleaseGroupsForArtist error', err);
|
||||
this.topReleaseGroups = [];
|
||||
} finally {
|
||||
// See fetchTopTracks: hold the spinner while a background
|
||||
@@ -1462,12 +1447,12 @@ export class ExploreArtistDetails extends LitElement {
|
||||
// one from here is instant instead of a cold MB browse.
|
||||
this.prefetchReleases(rgs?.map((r) => r.mbid) ?? []);
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
this.errorReleases = msg;
|
||||
this.catalogPending = false;
|
||||
console.error(
|
||||
`[explore-artist] BrowseReleaseGroups error: ${msg}`,
|
||||
console.error('[explore-artist] BrowseReleaseGroups error', err);
|
||||
this.errorReleases = describeError(
|
||||
err,
|
||||
'The catalog did not answer for this artist\u2019s albums.',
|
||||
);
|
||||
this.catalogPending = false;
|
||||
} finally {
|
||||
// BrowseReleaseGroups is index-first + async: an empty result on
|
||||
// a cold artist means the discography is still being fetched in
|
||||
@@ -1498,10 +1483,7 @@ export class ExploreArtistDetails extends LitElement {
|
||||
this.similarArtists = artists ?? [];
|
||||
} catch (err) {
|
||||
// D024: graceful degradation — silently omit similar artists on failure.
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
console.error(
|
||||
`[explore-artist] SimilarArtists error: ${msg}`,
|
||||
);
|
||||
console.error('[explore-artist] SimilarArtists error', err);
|
||||
this.similarArtists = [];
|
||||
} finally {
|
||||
// SimilarArtists is DB-first + async: an empty result on the
|
||||
|
||||
Reference in New Issue
Block a user