import { Eye, Pause, Play, RotateCcw, Square, X } from 'lucide-react' import { useRef, useState } from 'react' import { Avatar, type AvatarController, type AvatarRuntimeError } from '@bible-strong/avatar-react' import type { AnimationKey, AvatarDefinition, ExpressionKey } from '@bible-strong/avatar-core' import { Button } from '@/components/ui/button' import { Dialog, DialogClose, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from '@/components/ui/dialog' import { useStudioLanguage } from '@/i18n' type PlaybackStatus = 'playing' | 'paused' | 'stopped' type PreviewTarget = { type: 'animation'; key: AnimationKey } | { type: 'expression'; key: ExpressionKey } function RuntimePreviewContent({ definition: inputDefinition, initialAnimation, }: { definition: AvatarDefinition initialAnimation?: AnimationKey }) { const { t } = useStudioLanguage() const [definition] = useState(inputDefinition) const controller = useRef(null) const firstAnimation = initialAnimation ?? definition.animationOrder[0] const [target, setTarget] = useState( firstAnimation ? { type: 'animation', key: firstAnimation } : { type: 'expression', key: 'neutral' } ) const [activeAnimation, setActiveAnimation] = useState(firstAnimation) const [activeExpression, setActiveExpression] = useState( firstAnimation ? (definition.animations[firstAnimation]?.steps[0]?.expression ?? 'neutral') : 'neutral' ) const [status, setStatus] = useState(firstAnimation ? 'playing' : 'stopped') const [error, setError] = useState(null) const reportResult = (result: ReturnType) => { if (result.ok) setError(null) else setError(result.error) return result.ok } const playAnimation = (animation: AnimationKey) => { if (!controller.current || !reportResult(controller.current.play(animation))) return setTarget({ type: 'animation', key: animation }) setActiveAnimation(animation) setStatus('playing') } const showExpression = (expression: ExpressionKey) => { if (!controller.current || !reportResult(controller.current.setExpression(expression))) return setTarget({ type: 'expression', key: expression }) setActiveAnimation(undefined) setActiveExpression(expression) setStatus('stopped') } const restart = () => { if (target.type === 'animation') playAnimation(target.key) else showExpression(target.key) } const pause = () => { controller.current?.pause() if (activeAnimation) setStatus('paused') } const stop = () => { controller.current?.stop() setActiveAnimation(undefined) setActiveExpression('neutral') setStatus('stopped') } const statusLabel = status === 'playing' ? t('En lecture') : status === 'paused' ? t('En pause') : t('Arrêté') return (
{t('Définition exportée')} {definition.name ?? t('Avatar')}
{ setActiveAnimation(undefined) setStatus('stopped') }} onExpressionChange={setActiveExpression} onError={setError} />
{t('Animation active')} {activeAnimation ?? '—'}
{t('Expression active')} {activeExpression}
{error && (

{error.message}

)}
) } export function RuntimePreviewDialog({ definition, initialAnimation, onOpenChange, open, }: { definition: AvatarDefinition | null initialAnimation?: AnimationKey onOpenChange: (open: boolean) => void open: boolean }) { const { t } = useStudioLanguage() return (
{t('Preview')}
{t('Preview de la définition exportée')} {t( 'Teste les animations et expressions réellement présentes dans le fichier .avatar.json.' )} } />
{open && definition && ( )}
) }