Files
gnommoplayer/slide-preview-integration.md
2026-04-11 09:21:22 +02:00

293 lines
6.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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}`.