forked from Keelrleek/SoulStream
Phase 2C WIP: PreviewOverlay modal + root integration (reel centering bug)
Working: - PreviewOverlay.svelte mounted at app root; opens over a fixture manifest (window.__previewFixture(n) in dev), inert background, player bar hidden, focus trap, keyboard nav, F3 rail, T3 swaps, R1b capsule, accent extraction. - previewSession.svelte.js: store + service wiring (production + fixture). - Root integration in App.svelte; revision-gateway bumps + notePlaybackGeneration threaded through state.svelte.js player entry points; api.win guarded so plain vite browser mounts. - Launcher on the artist page builds a real artist manifest and opens the modal with a play-full starter. - 70 JS tests still green. Two bugs found and fixed during bring-up: - effect_update_depth_exceeded: bleed-crossfade and bump effects read AND wrote the same $state; wrapped writes in untrack(). This loop was breaking Svelte's scheduler globally (even ui.* stopped reacting). - accentFromImage now sets crossOrigin for remote covers. KNOWN BROKEN (handoff): reel vertical centering. The active card stays centred at index 0 but drifts by one stride per step. Root cause isolated — see TODO-Feature-Docs/scrollable-track-previews/HANDOFF-PHASE2C.md.
This commit is contained in:
1 parent
8cb3cd593b
commit
d051f0db28
7 files changed
+1492
-16
No files matched your search
@@ -33,6 +33,8 @@
|
||||
} from "../lib/state.svelte.js";
|
||||
import * as api from "../lib/api.js";
|
||||
import { accentFromImage } from "../lib/color.js";
|
||||
import { buildArtistManifest } from "../lib/preview/manifest.js";
|
||||
import { openPreview } from "../lib/preview/previewSession.svelte.js";
|
||||
import { traceToSvg, svgDataUrl } from "../lib/trace.js";
|
||||
import Icon from "../components/Icon.svelte";
|
||||
import HeroGpuCanvas from "../components/HeroGpuCanvas.svelte";
|
||||
@@ -537,8 +539,6 @@
|
||||
// state cannot occur here: the whole action row is gated on
|
||||
// popularTracks.length, so by the time this control exists the tracks (and
|
||||
// therefore their preview fields) have landed.
|
||||
// TODO(previews): openPreviews() opens the scrollable preview modal —
|
||||
// TODO-Feature-Docs/scrollable-track-previews. Placement-only for now.
|
||||
const previewableCount = $derived(allPopular.filter((track) => track.preview).length);
|
||||
const previewState = $derived(
|
||||
previewableCount === 0
|
||||
@@ -554,7 +554,31 @@
|
||||
? `Preview tracks — ${previewableCount} of ${allPopular.length} available`
|
||||
: "Preview tracks",
|
||||
);
|
||||
function openPreviews() {}
|
||||
/** Open the preview modal over the COMPLETE ranked top-track payload —
|
||||
* never just the rendered rows (design §13, artist adapter). The manifest
|
||||
* is a snapshot: later staged-page rebuilds cannot rewrite an open
|
||||
* session. Play-full hands the active item to the ordinary resolver
|
||||
* pipeline via the same path the Popular rows use. */
|
||||
function openPreviews() {
|
||||
if (!page?.popular_tracks?.length) return;
|
||||
const snapshotTracks = page.popular_tracks.slice(0, 10);
|
||||
const byProviderId = new Map(snapshotTracks.map((t) => [String(t.id), t]));
|
||||
const manifest = buildArtistManifest({
|
||||
artist: {
|
||||
id: page.artist.id,
|
||||
name: page.artist.name,
|
||||
picture: page.artist.picture ?? null,
|
||||
},
|
||||
popularTracks: snapshotTracks,
|
||||
createdAtMs: Date.now(),
|
||||
});
|
||||
void openPreview(manifest, {
|
||||
playFull: (item) => {
|
||||
const track = byProviderId.get(item.sources[0]?.providerTrackId);
|
||||
if (track) playPopular(track);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Instant-shell seed: the search portrait the user clicked, shown as a
|
||||
// heavily-blurred colour field behind the hero until the real photo
|
||||
|
||||
Reference in new issue
Block a user