Initial commit after recreate
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
# 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 slide’s `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 Player’s 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}`.
|
||||
Reference in New Issue
Block a user