Files
hao-ai-lab-FastVideo/apps/dreamverse/web/src/components/devtools/DevtoolsShell.tsx
T
69a6215e7f [feat] Add Dreamverse multimodal inputs and H3 routing (#1835)
Co-authored-by: SolitaryThinker <wlsaidhi@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-07 01:30:26 -07:00

372 lines
13 KiB
TypeScript

'use client';
import React from 'react';
import SessionAlerts from '../shell/SessionAlerts';
import TopStatusBar from '../shell/TopStatusBar';
import WorkspaceShell from '../shell/WorkspaceShell';
import Workspace from '../Workspace';
import VideoPlayer from '../VideoPlayer';
import RewriteInspector from '../rewrite/RewriteInspector';
import DevtoolsComposer from './DevtoolsComposer';
import DevtoolsDrawer from './DevtoolsDrawer';
import { DEFAULT_GENERATION_MODE, GENERATION_MODES, type GenerationMode } from '@/lib/generationMode';
interface DevtoolsShellProps {
connected?: boolean;
gpuAssigned?: boolean;
sessionStarted?: boolean;
queuePosition?: number;
connecting?: boolean;
storyPresets?: Record<string, any>[];
selectedPresetId?: string;
enhancementEnabled?: boolean;
autoExtensionEnabled?: boolean;
loopGenerationEnabled?: boolean;
canJoinSession?: boolean;
canSubmitContinuation?: boolean;
editableMode?: boolean;
demoMode?: boolean;
editableCanJoin?: boolean;
curatedPromptLimit?: number;
maxCuratedPromptCount?: number;
generationMode?: GenerationMode;
supportedGenerationModes?: readonly GenerationMode[];
conditioningPanel?: React.ReactNode;
onGenerationModeChange?: (mode: GenerationMode) => void;
onPresetChange?: (e: React.ChangeEvent<HTMLSelectElement>) => void;
onEnhancementToggle?: (e: React.ChangeEvent<HTMLInputElement>) => void;
onCuratedPromptLimitChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
onAutoExtensionToggle?: (e: React.ChangeEvent<HTMLInputElement>) => void;
onLoopToggle?: (e: React.ChangeEvent<HTMLInputElement>) => void;
onJoin?: () => void;
onLeave?: () => void;
sessionNotice?: string;
generationCapReached?: boolean;
generationSegmentCap?: number;
onRestartGeneration?: () => void;
selectedPreset?: Record<string, any> | null;
editableSegments?: string[];
customPresetId?: string;
customPresetLabel?: string;
currentPromptWindowPrompts?: string[];
appendingPromptWindow?: boolean;
appendPromptWindowStatus?: string;
appendPromptWindowError?: string;
onCustomPresetIdInput?: (e: React.ChangeEvent<HTMLInputElement>) => void;
onCustomPresetLabelInput?: (e: React.ChangeEvent<HTMLInputElement>) => void;
onAddSegment?: () => void;
onResetToPreset?: () => void;
onExport?: () => void;
onAppendPromptWindowToJson?: () => void;
onRemoveSegment?: (index: number) => void;
onUpdateSegment?: (index: number, value: string) => void;
seedPrompts?: string[];
playingSeedPromptIndex?: number | null;
generatingSeedPromptIndex?: number | null;
livePromptDraft?: string;
livePromptRewriteMode?: boolean;
rewritingSeedPrompts?: boolean;
promptEvents?: Record<string, any>[];
onLivePromptInput?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
onLivePromptModeToggle?: (e: React.ChangeEvent<HTMLInputElement>) => void;
onLivePromptKeydown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
onSubmitLivePrompt?: () => void;
onSpeechTranscript?: (text: string) => void;
onSpeechInterimChange?: (text: string) => void;
promptConfigEditorOpen?: boolean;
promptConfigLoading?: boolean;
promptConfigSaving?: boolean;
promptConfigStatus?: string;
promptConfigError?: string;
nextSegmentPromptEditorOpen?: boolean;
autoExtensionPromptEditorOpen?: boolean;
rewriteWindowPromptEditorOpen?: boolean;
nextSegmentSystemPromptDraft?: string;
autoExtensionSystemPromptDraft?: string;
rewriteWindowSystemPromptDraft?: string;
onPromptConfigEditorToggle?: (e: React.SyntheticEvent<HTMLDetailsElement>) => void;
onReloadPromptConfig?: () => void;
onNextSegmentSystemPromptInput?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
onAutoExtensionSystemPromptInput?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
onRewriteWindowSystemPromptInput?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
onSavePromptConfig?: () => void;
autoExtensionTimeoutHint?: string;
activeClip?: Record<string, any> | null;
liveClipLabel?: string;
liveClipPrompt?: string;
galleryClips?: Record<string, any>[];
activeClipId?: string;
showLivePlayback?: boolean;
onSelectClip?: (id: string) => void;
avPlaybackStarted?: boolean;
mediaAppendError?: string | null;
timeLeft?: number | null;
ttffStartAtMs?: number | null;
ttffValueMs?: number | null;
timeBetweenVideosMs?: number | null;
loadingAnimation?: boolean;
formatTime?: (seconds: number) => string;
formatDurationMs?: (durationMs: number) => string;
onPlaying?: () => void;
videoRef?: React.RefCallback<HTMLVideoElement>;
archivedPlaybackRef?: React.RefCallback<HTMLVideoElement>;
}
export default function DevtoolsShell({
connected = false,
gpuAssigned = false,
sessionStarted = false,
queuePosition = 0,
connecting = false,
storyPresets = [],
selectedPresetId = '',
enhancementEnabled = true,
autoExtensionEnabled = false,
loopGenerationEnabled = false,
canJoinSession = false,
canSubmitContinuation = false,
editableMode = false,
demoMode = false,
editableCanJoin = false,
curatedPromptLimit = 0,
maxCuratedPromptCount = 0,
generationMode = DEFAULT_GENERATION_MODE,
supportedGenerationModes = GENERATION_MODES.map((mode) => mode.id),
conditioningPanel,
onGenerationModeChange = () => {},
onPresetChange = () => {},
onEnhancementToggle = () => {},
onCuratedPromptLimitChange = () => {},
onAutoExtensionToggle = () => {},
onLoopToggle = () => {},
onJoin = () => {},
onLeave = () => {},
sessionNotice = '',
selectedPreset = null,
editableSegments = [],
customPresetId = 'custom_editable',
customPresetLabel = 'Custom Editable Preset',
currentPromptWindowPrompts = [],
appendingPromptWindow = false,
appendPromptWindowStatus = '',
appendPromptWindowError = '',
onCustomPresetIdInput = () => {},
onCustomPresetLabelInput = () => {},
onAddSegment = () => {},
onResetToPreset = () => {},
onExport = () => {},
onAppendPromptWindowToJson = () => {},
onRemoveSegment = () => {},
onUpdateSegment = () => {},
seedPrompts = [],
playingSeedPromptIndex = null,
generatingSeedPromptIndex = null,
livePromptDraft = '',
livePromptRewriteMode = false,
rewritingSeedPrompts = false,
promptEvents = [],
onLivePromptInput = () => {},
onLivePromptModeToggle = () => {},
onLivePromptKeydown = () => {},
onSubmitLivePrompt = () => {},
onSpeechTranscript,
onSpeechInterimChange,
promptConfigEditorOpen = false,
promptConfigLoading = false,
promptConfigSaving = false,
promptConfigStatus = '',
promptConfigError = '',
nextSegmentPromptEditorOpen = false,
autoExtensionPromptEditorOpen = false,
rewriteWindowPromptEditorOpen = true,
nextSegmentSystemPromptDraft = '',
autoExtensionSystemPromptDraft = '',
rewriteWindowSystemPromptDraft = '',
onPromptConfigEditorToggle = () => {},
onReloadPromptConfig = () => {},
onNextSegmentSystemPromptInput = () => {},
onAutoExtensionSystemPromptInput = () => {},
onRewriteWindowSystemPromptInput = () => {},
onSavePromptConfig = () => {},
autoExtensionTimeoutHint = '',
activeClip = null,
showLivePlayback = true,
avPlaybackStarted = false,
mediaAppendError = null,
timeLeft = null,
ttffStartAtMs = null,
ttffValueMs = null,
timeBetweenVideosMs = null,
loadingAnimation = false,
formatTime = (seconds) => `${seconds}`,
formatDurationMs = (durationMs) => `${durationMs}`,
onPlaying = () => {},
videoRef,
archivedPlaybackRef,
}: DevtoolsShellProps) {
return (
<WorkspaceShell
devtools={true}
topbar={
<TopStatusBar
modeLabel="Devtools Mode"
title="Preset-driven video continuation"
connected={connected}
connecting={connecting}
sessionStarted={sessionStarted}
gpuAssigned={gpuAssigned}
queuePosition={queuePosition}
livePromptRewriteMode={livePromptRewriteMode}
rewritingSeedPrompts={rewritingSeedPrompts}
timeLeft={timeLeft}
ttffStartAtMs={ttffStartAtMs}
ttffValueMs={ttffValueMs}
videoGapMs={timeBetweenVideosMs}
formatTime={formatTime}
formatDurationMs={formatDurationMs}
/>
}
workspace={
<div className="flex flex-col gap-4">
<VideoPlayer
videoRef={videoRef}
archivedPlaybackRef={archivedPlaybackRef}
activeClip={activeClip}
sessionStarted={sessionStarted}
avPlaybackStarted={avPlaybackStarted}
mediaAppendError={mediaAppendError}
timeLeft={timeLeft}
gpuAssigned={gpuAssigned}
connected={connected}
queuePosition={queuePosition}
loadingAnimation={loadingAnimation}
showLivePlayback={showLivePlayback}
onPlaying={onPlaying}
/>
<Workspace
promptEvents={promptEvents}
sessionStarted={sessionStarted}
/>
</div>
}
sidebar={
<RewriteInspector
currentPromptWindowPrompts={currentPromptWindowPrompts}
promptEvents={promptEvents}
rewritingSeedPrompts={rewritingSeedPrompts}
rewriteWindowMode={livePromptRewriteMode}
/>
}
composer={
<DevtoolsComposer
connected={connected}
gpuAssigned={gpuAssigned}
sessionStarted={sessionStarted}
queuePosition={queuePosition}
connecting={connecting}
storyPresets={storyPresets}
selectedPresetId={selectedPresetId}
livePromptDraft={livePromptDraft}
canJoinSession={canJoinSession}
canSubmitContinuation={canSubmitContinuation}
editableMode={editableMode}
editableCanJoin={editableCanJoin}
demoMode={demoMode}
enhancementEnabled={enhancementEnabled}
autoExtensionEnabled={autoExtensionEnabled}
loopGenerationEnabled={loopGenerationEnabled}
curatedPromptLimit={curatedPromptLimit}
maxCuratedPromptCount={maxCuratedPromptCount}
generationMode={generationMode}
supportedGenerationModes={supportedGenerationModes}
conditioningPanel={conditioningPanel}
onGenerationModeChange={onGenerationModeChange}
rewriteWindowMode={livePromptRewriteMode}
rewritingSeedPrompts={rewritingSeedPrompts}
autoExtensionTimeoutHint={autoExtensionTimeoutHint}
onPresetChange={onPresetChange}
onLivePromptInput={onLivePromptInput}
onLivePromptKeydown={onLivePromptKeydown}
onJoin={onJoin}
onSubmitLivePrompt={onSubmitLivePrompt}
onLeave={onLeave}
onEnhancementToggle={onEnhancementToggle}
onCuratedPromptLimitChange={onCuratedPromptLimitChange}
onAutoExtensionToggle={onAutoExtensionToggle}
onLoopToggle={onLoopToggle}
onLivePromptModeToggle={onLivePromptModeToggle}
onSpeechTranscript={onSpeechTranscript}
onSpeechInterimChange={onSpeechInterimChange}
/>
}
alerts={<SessionAlerts sessionNotice={sessionNotice} />}
drawer={
<DevtoolsDrawer
editableMode={editableMode}
demoMode={demoMode}
sessionStarted={sessionStarted}
selectedPreset={selectedPreset}
editableSegments={editableSegments}
editableCanJoin={editableCanJoin}
customPresetId={customPresetId}
customPresetLabel={customPresetLabel}
currentPromptWindowPrompts={currentPromptWindowPrompts}
appendingPromptWindow={appendingPromptWindow}
appendPromptWindowStatus={appendPromptWindowStatus}
appendPromptWindowError={appendPromptWindowError}
onCustomPresetIdInput={onCustomPresetIdInput}
onCustomPresetLabelInput={onCustomPresetLabelInput}
onAddSegment={onAddSegment}
onResetToPreset={onResetToPreset}
onExport={onExport}
onAppendPromptWindowToJson={onAppendPromptWindowToJson}
onRemoveSegment={onRemoveSegment}
onUpdateSegment={onUpdateSegment}
seedPrompts={seedPrompts}
playingSeedPromptIndex={playingSeedPromptIndex}
generatingSeedPromptIndex={generatingSeedPromptIndex}
promptEvents={promptEvents}
promptConfigEditorOpen={promptConfigEditorOpen}
promptConfigLoading={promptConfigLoading}
promptConfigSaving={promptConfigSaving}
promptConfigStatus={promptConfigStatus}
promptConfigError={promptConfigError}
nextSegmentPromptEditorOpen={nextSegmentPromptEditorOpen}
autoExtensionPromptEditorOpen={autoExtensionPromptEditorOpen}
rewriteWindowPromptEditorOpen={rewriteWindowPromptEditorOpen}
nextSegmentSystemPromptDraft={nextSegmentSystemPromptDraft}
autoExtensionSystemPromptDraft={autoExtensionSystemPromptDraft}
rewriteWindowSystemPromptDraft={rewriteWindowSystemPromptDraft}
onPromptConfigEditorToggle={onPromptConfigEditorToggle}
onReloadPromptConfig={onReloadPromptConfig}
onNextSegmentSystemPromptInput={onNextSegmentSystemPromptInput}
onAutoExtensionSystemPromptInput={onAutoExtensionSystemPromptInput}
onRewriteWindowSystemPromptInput={onRewriteWindowSystemPromptInput}
onSavePromptConfig={onSavePromptConfig}
/>
}
/>
);
}