Files

293 lines
6.8 KiB
Markdown
Raw Permalink Normal View History

2026-04-11 09:21:22 +02:00
# Slide Preview Integration Guide
This guide is for integrating an authoritative slide preview into another React + Vite UI, using the real `GlitchPlayer` runtime rather than a custom thumbnail or placeholder renderer.
## Goal
When the editor user selects a slide, the preview should be:
- the real `GlitchPlayer`
- moved to the selected slide
- paused on that slide
- rendered with the same layout, video, timing, and slide runtime as the final presentation
This is the correct preview surface when fidelity matters more than efficiency.
## Use This, Not A Custom Thumbnail
For the main preview panel:
- use `GlitchPlayer`
- with `mode="slide-preview"`
- and `targetSlideId`
Do not use:
- `GlitchSlideThumbnail`
- `GlitchSlideRenderer`
- a hand-built editor preview
Those are useful for slide lists and lightweight surfaces, but not for the authoritative preview.
## Built Files To Consume
If the integration agent is only allowed to fetch built artifacts from this repo, use:
- [dist/vendor/gnommoplayer.js](/Users/jenstandstad/Projects/gnommoplayer/dist/vendor/gnommoplayer.js)
- [dist/vendor/gnommoplayer.css](/Users/jenstandstad/Projects/gnommoplayer/dist/vendor/gnommoplayer.css)
Build them with:
```bash
npm run build
```
That command now produces both the demo app build and the vendor bundle.
## What To Import
From `gnommoplayer.js`, the preview integration should import:
- `GlitchPlayer`
- `defaultSlideRegistry`
From `gnommoplayer.css`, import the player stylesheet once near the app root.
Example:
```tsx
import "../vendor/gnommoplayer/gnommoplayer.css";
import {
GlitchPlayer,
defaultSlideRegistry,
} from "../vendor/gnommoplayer/gnommoplayer.js";
```
## Required Data
The preview must receive a full presentation object, not just one slide.
That presentation should include:
- `id`
- `title`
- `version`
- `durationSec`
- `segments`
- `slides`
Why:
- the player needs the full timeline
- the player needs the talking-head video segments
- the player derives the active slide from presentation timing
- the player must match the final runtime, not a simplified editor view
## Preview Contract
The preview panel should render the player like this:
```tsx
<GlitchPlayer
presentation={presentation}
slideRegistry={defaultSlideRegistry}
mode="slide-preview"
targetSlideId={selectedSlideId}
initialSessionId={`editor-preview-${presentation.id}`}
/>
```
Behavior of this mode:
- the player jumps to the targeted slides `startTimeSec`
- playback starts paused
- the real player UI and layout are used
- the talking-head video is still part of the runtime surface
## Recommended Host Component
The host app should wrap this in a dedicated preview component.
Example:
```tsx
import { useEffect, useState } from "react";
import "../vendor/gnommoplayer/gnommoplayer.css";
import {
GlitchPlayer,
defaultSlideRegistry,
} from "../vendor/gnommoplayer/gnommoplayer.js";
export function SlidePreviewPanel({
presentationId,
selectedSlideId,
}: {
presentationId: string;
selectedSlideId: string | null;
}) {
const [presentation, setPresentation] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
let cancelled = false;
fetch(`/api/videos/${presentationId}/export`)
.then((response) => {
if (!response.ok) {
throw new Error(`Preview fetch failed: ${response.status}`);
}
return response.json();
})
.then((data) => {
if (!cancelled) {
setPresentation(data);
setError(null);
}
})
.catch((caughtError) => {
if (!cancelled) {
setError(String(caughtError));
}
});
return () => {
cancelled = true;
};
}, [presentationId]);
if (error) {
return <div>Preview error: {error}</div>;
}
if (!presentation || !selectedSlideId) {
return <div>Select a slide to preview.</div>;
}
return (
<div style={{ width: "100%", height: "100%" }}>
<GlitchPlayer
presentation={presentation}
slideRegistry={defaultSlideRegistry}
mode="slide-preview"
targetSlideId={selectedSlideId}
initialSessionId={`editor-preview-${presentation.id}`}
/>
</div>
);
}
```
## How The Editor Should Drive It
The editor should keep one piece of selection state:
- `selectedSlideId`
When the user clicks a slide in the editor:
1. update `selectedSlideId`
2. keep the same `presentation`
3. re-render `GlitchPlayer` with the new `targetSlideId`
That is enough for the player to move to the correct slide.
## Important Implementation Notes
### 1. Use The Full Presentation
Do not try to construct a fake one-slide presentation for preview.
That creates drift in:
- timing
- fullscreen transitions
- video positioning
- segment masking
- variant behavior
The preview should be the real timeline.
### 2. It Is Fine If The Video Loads Again
That is an acceptable tradeoff for now.
The goal of the editor preview is correctness:
- same player
- same slide runtime
- same layout
Not maximum efficiency.
### 3. Keep Thumbnails Separate
This preview guide is only for the main preview panel.
For slide list cards:
- `GlitchSlideThumbnail` is still appropriate
For the large “truth” preview:
- use `GlitchPlayer`
### 4. Prefer Stable Slide Ids
The editor should pass a stable `selectedSlideId`, ideally the same id used in the exported presentation payload.
The preview mechanism depends on exact id matching:
```tsx
targetSlideId={selectedSlideId}
```
### 5. Do Not Replace The Players Internal Registry Logic
Use:
```tsx
slideRegistry={defaultSlideRegistry}
```
unless the host intentionally provides a superset registry.
The preview should not invent its own runtime component resolution.
## When To Use `GlitchSlideThumbnail` Instead
Use `GlitchSlideThumbnail` only for:
- slide list rows
- compact cards
- mini previews in inspector sidebars
Do not use it as a substitute for the main preview panel.
## Recommended Replacement Strategy
If the current editor preview is “kind of not working,” replace it with this sequence:
1. Keep the slide list as-is for now
2. Remove the custom preview widget
3. Add a dedicated preview panel component
4. Fetch the full exported presentation JSON
5. Render:
```tsx
<GlitchPlayer
presentation={presentation}
slideRegistry={defaultSlideRegistry}
mode="slide-preview"
targetSlideId={selectedSlideId}
/>
```
That gives you a preview surface that is as close to final runtime as possible.
## Short Handoff Note
If you need the shortest possible instruction for the other agent, use this:
Use the real player for slide preview, not the thumbnail renderer. Import `GlitchPlayer` and `defaultSlideRegistry` from `dist/vendor/gnommoplayer.js`, import `dist/vendor/gnommoplayer.css`, fetch the full presentation JSON, and render `GlitchPlayer` with `mode="slide-preview"` and `targetSlideId={selectedSlideId}`.