forked from 77media/video-flow
- [x] 触发自动剪辑中,小剪刀 不要出来
Chatbox 快捷指令简化
This commit is contained in:
parent
adb6f97366
commit
254b226c6e
@ -1,20 +1,22 @@
|
||||
import React, { useRef, useCallback } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
||||
import { ChevronLeft, ChevronRight, Cloudy, UserRound, PersonStanding, Shirt, Smile, RefreshCcw } from 'lucide-react';
|
||||
|
||||
/** 快捷操作标签的数据结构 */
|
||||
export interface QuickAction {
|
||||
id: string;
|
||||
label: string;
|
||||
icon: any;
|
||||
}
|
||||
|
||||
/** 预设的快捷操作标签 */
|
||||
export const DEFAULT_QUICK_ACTIONS: QuickAction[] = [
|
||||
{ id: 'weather', label: 'Change video scene weather' },
|
||||
{ id: 'character', label: 'Change a character in the video' },
|
||||
{ id: 'costume', label: 'Change the clothing of a character in the video' },
|
||||
{ id: 'scene', label: 'Change video scene background' },
|
||||
{ id: 'action', label: 'Change character action' }
|
||||
{ id: 'weather', label: 'change weather', icon: Cloudy },
|
||||
{ id: 'character', label: 'change character', icon: UserRound },
|
||||
{ id: 'costume', label: 'change clothing', icon: Shirt },
|
||||
{ id: 'action', label: 'change action', icon: PersonStanding },
|
||||
{ id: 'emotion', label: 'change emotion', icon: Smile },
|
||||
{ id: 'retry', label: 'retry failed video', icon: RefreshCcw }
|
||||
];
|
||||
|
||||
interface QuickActionTagsProps {
|
||||
@ -48,10 +50,10 @@ export function QuickActionTags({ actions = DEFAULT_QUICK_ACTIONS, onTagClick }:
|
||||
return (
|
||||
<div
|
||||
data-alt="quick-action-tags"
|
||||
className="relative flex items-center px-3 py-2 group"
|
||||
className="relative flex items-center px-3 py-2 group bg-gradient-to-r from-black/20 to-transparent"
|
||||
>
|
||||
{/* 左侧渐变遮罩 */}
|
||||
<div className="absolute left-0 top-0 bottom-0 w-12 bg-gradient-to-r from-black/20 to-transparent pointer-events-none z-10" />
|
||||
{/* <div className="absolute left-0 top-0 bottom-0 w-12 bg-gradient-to-r from-black/20 to-transparent pointer-events-none z-10" /> */}
|
||||
|
||||
{/* 左滚动按钮 */}
|
||||
<motion.button
|
||||
@ -81,20 +83,21 @@ export function QuickActionTags({ actions = DEFAULT_QUICK_ACTIONS, onTagClick }:
|
||||
onClick={() => onTagClick(action)}
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
className="flex-none px-[8px] py-[3px] rounded-full text-[10px] text-white/80
|
||||
className="flex items-center flex-shrink-0 gap-1 px-[8px] py-[3px] rounded-full text-[10px] text-white/80
|
||||
backdrop-blur-md bg-white/10 border border-white/20
|
||||
hover:bg-white/20 hover:text-white
|
||||
transition-colors duration-200
|
||||
shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-1px_rgba(0,0,0,0.06)]"
|
||||
data-alt={`quick-action-${action.id}`}
|
||||
>
|
||||
{action.icon && <action.icon className="w-3 h-3" />}
|
||||
{action.label}
|
||||
</motion.button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 右侧渐变遮罩 */}
|
||||
<div className="absolute right-0 top-0 bottom-0 w-12 bg-gradient-to-l from-black/20 to-transparent pointer-events-none z-10" />
|
||||
{/* <div className="absolute right-0 top-0 bottom-0 w-12 bg-gradient-to-l from-black/20 to-transparent pointer-events-none z-10" /> */}
|
||||
|
||||
{/* 右滚动按钮 */}
|
||||
<motion.button
|
||||
|
||||
@ -40,6 +40,7 @@ const WorkFlow = React.memo(function WorkFlow() {
|
||||
const [isHovered, setIsHovered] = React.useState(false);
|
||||
const [aiEditingResult, setAiEditingResult] = React.useState<any>(null);
|
||||
const aiEditingButtonRef = useRef<{ handleAIEditing: () => Promise<void> }>(null);
|
||||
const [editingStatus, setEditingStatus] = React.useState<'initial' | 'idle' | 'success' | 'error'>('initial');
|
||||
|
||||
const searchParams = useSearchParams();
|
||||
const episodeId = searchParams.get('episodeId') || '';
|
||||
@ -53,6 +54,7 @@ const WorkFlow = React.memo(function WorkFlow() {
|
||||
const handleEditPlanGenerated = useCallback(() => {
|
||||
console.log('✨ 编辑计划生成完成,开始AI剪辑');
|
||||
setIsHandleEdit(true);
|
||||
setEditingStatus('idle');
|
||||
aiEditingButtonRef.current?.handleAIEditing();
|
||||
editingNotificationKey.current = `editing-${Date.now()}`;
|
||||
showEditingNotification({
|
||||
@ -65,6 +67,7 @@ const WorkFlow = React.memo(function WorkFlow() {
|
||||
console.log('Editing failed');
|
||||
// 清缓存 生成计划 视频重新分析
|
||||
localStorage.removeItem(`isLoaded_plan_${episodeId}`);
|
||||
setEditingStatus('error');
|
||||
// 3秒后关闭通知
|
||||
setTimeout(() => {
|
||||
if (editingNotificationKey.current) {
|
||||
@ -82,9 +85,7 @@ const WorkFlow = React.memo(function WorkFlow() {
|
||||
isLoading,
|
||||
currentSketchIndex,
|
||||
currentLoadingText,
|
||||
dataLoadError,
|
||||
setCurrentSketchIndex,
|
||||
retryLoadData,
|
||||
isPauseWorkFlow,
|
||||
mode,
|
||||
setIsPauseWorkFlow,
|
||||
@ -122,6 +123,7 @@ const WorkFlow = React.memo(function WorkFlow() {
|
||||
onComplete: () => {
|
||||
console.log('Editing successful');
|
||||
localStorage.setItem(`isLoaded_plan_${episodeId}`, 'true');
|
||||
setEditingStatus('success');
|
||||
// 3秒后关闭通知
|
||||
setTimeout(() => {
|
||||
if (editingNotificationKey.current) {
|
||||
@ -200,7 +202,7 @@ const WorkFlow = React.memo(function WorkFlow() {
|
||||
currentLoadingText={currentLoadingText}
|
||||
roles={taskObject.roles.data}
|
||||
isPauseWorkFlow={isPauseWorkFlow}
|
||||
showGotoCutButton={showGotoCutButton}
|
||||
showGotoCutButton={showGotoCutButton || editingStatus !== 'idle'}
|
||||
onGotoCut={generateEditPlan}
|
||||
setIsPauseWorkFlow={setIsPauseWorkFlow}
|
||||
/>
|
||||
@ -232,7 +234,7 @@ const WorkFlow = React.memo(function WorkFlow() {
|
||||
setPreviewVideoUrl(url);
|
||||
setPreviewVideoId(id);
|
||||
}}
|
||||
showGotoCutButton={showGotoCutButton}
|
||||
showGotoCutButton={showGotoCutButton || editingStatus !== 'idle'}
|
||||
onGotoCut={generateEditPlan}
|
||||
isSmartChatBoxOpen={isSmartChatBoxOpen}
|
||||
onRetryVideo={(video_id) => handleRetryVideo(video_id)}
|
||||
|
||||
@ -148,8 +148,8 @@ export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps =
|
||||
showEditingNotification({
|
||||
key: notificationKey,
|
||||
description: 'Generating intelligent editing plan...',
|
||||
successDescription: 'Generating successful',
|
||||
timeoutDescription: 'Generating failed, please try again',
|
||||
successDescription: '剪辑计划生成完成',
|
||||
timeoutDescription: '剪辑计划生成失败,请重试',
|
||||
timeout: 3 * 60 * 1000
|
||||
});
|
||||
// 先停止轮询
|
||||
@ -168,8 +168,8 @@ export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps =
|
||||
showEditingNotification({
|
||||
key: notificationKey,
|
||||
isCompleted: true,
|
||||
description: 'Generating intelligent editing plan...',
|
||||
successDescription: 'Generating successful',
|
||||
description: '正在生成剪辑计划...',
|
||||
successDescription: '剪辑计划生成完成',
|
||||
timeout: 3000
|
||||
});
|
||||
setTimeout(() => {
|
||||
@ -186,8 +186,8 @@ export function useWorkflowData({ onEditPlanGenerated }: UseWorkflowDataProps =
|
||||
// 显示失败通知3秒
|
||||
showEditingNotification({
|
||||
key: notificationKey,
|
||||
description: 'Generating intelligent editing plan...',
|
||||
timeoutDescription: 'Generating failed, please try again',
|
||||
description: '正在生成剪辑计划...',
|
||||
timeoutDescription: '剪辑计划生成失败,请重试',
|
||||
timeout: 3000
|
||||
});
|
||||
setTimeout(() => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user