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:
@@ -1,4 +1,5 @@
|
||||
import { useCallback, useEffect, useLayoutEffect, useRef, useState, type ReactElement } from 'react'
|
||||
import { DialoguePreview } from './narrative'
|
||||
|
||||
type Utterer = 'npc' | 'player'
|
||||
type Utterance = {
|
||||
@@ -34,8 +35,9 @@ export function UtteranceCanvas({ nodeId, nodeLabel, terminals, onClose, setStat
|
||||
const cardRefs = useRef(new Map<string, HTMLDivElement>())
|
||||
const [heights, setHeights] = useState<Record<string, number>>({})
|
||||
|
||||
const [revision, setRevision] = useState(0)
|
||||
const reload = useCallback(async () => {
|
||||
try { setUtterances(await api<Utterance[]>(`/api/admin/story-nodes/${nodeId}/utterances`, 'GET')) }
|
||||
try { setUtterances(await api<Utterance[]>(`/api/admin/story-nodes/${nodeId}/utterances`, 'GET')); setRevision(r => r + 1) }
|
||||
catch (error) { setStatus(String((error as Error).message || error)) }
|
||||
}, [nodeId, setStatus])
|
||||
useEffect(() => { void reload(); api<Npc[]>('/api/admin/npcs', 'GET').then(setNpcs).catch(() => {}) }, [reload])
|
||||
@@ -205,6 +207,9 @@ export function UtteranceCanvas({ nodeId, nodeLabel, terminals, onClose, setStat
|
||||
</div>)}
|
||||
</div>
|
||||
{utterances.length === 0 && <div className="graph-empty">No utterances yet — add an NPC line or player choice.</div>}
|
||||
<div className="utterance-preview-dock" onPointerDown={event => event.stopPropagation()}>
|
||||
<DialoguePreview nodeId={nodeId} revision={revision} startId={selected ? (selected.utterer === 'player' ? selected.parentUtteranceId : selected.id) : null} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{selected && <aside className="graph-inspector">
|
||||
|
||||
Reference in New Issue
Block a user