Live dialogue preview in the editors (reuses the real DialoguePlayer)

- DialoguePlayer gains an `inline` mode (fills its container, no window key
  capture) and a `startId` to jump the walk to a given utterance.
- New DialoguePreview: a scaled-down mini player that fetches the resolved tree
  from GET /api/admin/story-nodes/:id/dialogue (same resolver as playback).
- Mystery graph: preview appears next to a selected dialogue node.
- Utterance editor: docked preview that jumps to the clicked/selected utterance
  and refreshes after each edit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 19:24:03 +02:00
co-authored by Claude Opus 4.8
parent f10d7584d2
commit 0b1e5e7fc7
6 changed files with 59 additions and 6 deletions
+5 -1
View File
@@ -1,6 +1,6 @@
import { useCallback, useEffect, useRef, useState } from 'react'
import { UtteranceCanvas } from './utteranceCanvas'
import { CUTSCENE_COMPONENT_KEYS } from './narrative'
import { CUTSCENE_COMPONENT_KEYS, DialoguePreview } from './narrative'
type StoryNodeType = 'cutscene' | 'dialogue' | 'level' | 'det_gate' | 'llm_gate'
type Terminal = { id: string; terminalKey: string; label: string; toNodeId: string | null; sortOrder: number }
@@ -140,6 +140,10 @@ export function MysteryGraphEditor({ mysteryId, title, onClose, setStatus }: { m
</div>)}
</div>
</div>)}
{selected && (selected.nodeType === 'dialogue' || selected.hasUtterances) &&
<div className="graph-node-preview" style={{ left: selected.xpos + NODE_W + 28, top: selected.ypos }} onClick={event => event.stopPropagation()}>
<DialoguePreview nodeId={selected.id} />
</div>}
</div>
{graph.nodes.length === 0 && <div className="graph-empty">Empty graph add a node to begin.</div>}
</div>