feat: add confirmation dialog for chapter actions in ChaptersPanel
This commit is contained in:
@@ -1445,6 +1445,7 @@ function ChaptersPanel({
|
|||||||
const [regeneratingSegs, setRegeneratingSegs] = useState<Set<number>>(new Set())
|
const [regeneratingSegs, setRegeneratingSegs] = useState<Set<number>>(new Set())
|
||||||
const [audioVersions, setAudioVersions] = useState<Record<number, number>>({})
|
const [audioVersions, setAudioVersions] = useState<Record<number, number>>({})
|
||||||
const [chapterPlayerChIdx, setChapterPlayerChIdx] = useState<number | null>(null)
|
const [chapterPlayerChIdx, setChapterPlayerChIdx] = useState<number | null>(null)
|
||||||
|
const [confirmAction, setConfirmAction] = useState<{ label: string; onConfirm: () => void } | null>(null)
|
||||||
const prevSegStatusRef = useRef<Record<number, string>>({})
|
const prevSegStatusRef = useRef<Record<number, string>>({})
|
||||||
const initialExpandDoneRef = useRef(false)
|
const initialExpandDoneRef = useRef(false)
|
||||||
const segRefs = useRef<Record<number, HTMLDivElement | null>>({})
|
const segRefs = useRef<Record<number, HTMLDivElement | null>>({})
|
||||||
@@ -1577,6 +1578,19 @@ function ChaptersPanel({
|
|||||||
const hasChapters = detail && detail.chapters.length > 0 && ['analyzing', 'ready', 'generating', 'done'].includes(status)
|
const hasChapters = detail && detail.chapters.length > 0 && ['analyzing', 'ready', 'generating', 'done'].includes(status)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<Dialog open={!!confirmAction} onOpenChange={open => { if (!open) setConfirmAction(null) }}>
|
||||||
|
<DialogContent className="max-w-xs">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>确认操作</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<p className="text-sm text-muted-foreground">{confirmAction?.label}</p>
|
||||||
|
<div className="flex justify-end gap-2 mt-2">
|
||||||
|
<Button variant="ghost" size="sm" onClick={() => setConfirmAction(null)}>取消</Button>
|
||||||
|
<Button variant="destructive" size="sm" onClick={() => { confirmAction?.onConfirm(); setConfirmAction(null) }}>确认</Button>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
<div className="flex-1 flex flex-col bg-emerald-500/5 overflow-hidden">
|
<div className="flex-1 flex flex-col bg-emerald-500/5 overflow-hidden">
|
||||||
<div className="flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between px-3 py-2 shrink-0">
|
<div className="flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between px-3 py-2 shrink-0">
|
||||||
<span className="text-xs font-medium text-emerald-400/80">
|
<span className="text-xs font-medium text-emerald-400/80">
|
||||||
@@ -1668,7 +1682,7 @@ function ChaptersPanel({
|
|||||||
<Volume2 className="h-3 w-3 mr-1" />
|
<Volume2 className="h-3 w-3 mr-1" />
|
||||||
{t('projectCard.chapters.generate')}
|
{t('projectCard.chapters.generate')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="xs" variant="ghost" className="text-muted-foreground" disabled={loadingAction} onClick={() => onParseChapter(ch.id, ch.title)}>
|
<Button size="xs" variant="ghost" className="text-muted-foreground" disabled={loadingAction} onClick={() => setConfirmAction({ label: '重新解析将删除已有台词,确认继续?', onConfirm: () => onParseChapter(ch.id, ch.title) })}>
|
||||||
{isAIMode ? <Bot className="h-3 w-3 mr-1" /> : <Wand2 className="h-3 w-3 mr-1" />}
|
{isAIMode ? <Bot className="h-3 w-3 mr-1" /> : <Wand2 className="h-3 w-3 mr-1" />}
|
||||||
{t(isAIMode ? 'projectCard.chapters.reparseAI' : 'projectCard.chapters.reparse')}
|
{t(isAIMode ? 'projectCard.chapters.reparseAI' : 'projectCard.chapters.reparse')}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1682,10 +1696,7 @@ function ChaptersPanel({
|
|||||||
{(ch.status === 'done' || (ch.status === 'ready' && chAllDone)) && (
|
{(ch.status === 'done' || (ch.status === 'ready' && chAllDone)) && (
|
||||||
<>
|
<>
|
||||||
<span className="text-[11px] text-muted-foreground">{t('projectCard.chapters.doneBadge', { count: chDone })}</span>
|
<span className="text-[11px] text-muted-foreground">{t('projectCard.chapters.doneBadge', { count: chDone })}</span>
|
||||||
<Button size="xs" variant="ghost" className="text-muted-foreground" disabled={loadingAction} onClick={() => {
|
<Button size="xs" variant="ghost" className="text-muted-foreground" disabled={loadingAction} onClick={() => setConfirmAction({ label: '重新生成将覆盖已有音频,确认继续?', onConfirm: () => { setExpandedChapters(prev => { const n = new Set(prev); n.add(ch.id); return n }); onGenerate(ch.chapter_index, true) } })}>
|
||||||
setExpandedChapters(prev => { const n = new Set(prev); n.add(ch.id); return n })
|
|
||||||
onGenerate(ch.chapter_index, true)
|
|
||||||
}}>
|
|
||||||
<RefreshCw className="h-3 w-3 mr-0.5" /><Volume2 className="h-3 w-3 mr-1" />{t('projectCard.chapters.generate')}
|
<RefreshCw className="h-3 w-3 mr-0.5" /><Volume2 className="h-3 w-3 mr-1" />{t('projectCard.chapters.generate')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@@ -1700,6 +1711,10 @@ function ChaptersPanel({
|
|||||||
<Button size="icon" variant="ghost" className="h-6 w-6" onClick={() => onDownload(ch.chapter_index)} title={t('projectCard.downloadAll')}>
|
<Button size="icon" variant="ghost" className="h-6 w-6" onClick={() => onDownload(ch.chapter_index)} title={t('projectCard.downloadAll')}>
|
||||||
<Download className="h-3 w-3" />
|
<Download className="h-3 w-3" />
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button size="xs" variant="ghost" className="text-muted-foreground" disabled={loadingAction} onClick={() => setConfirmAction({ label: '重新解析将删除已有台词和音频,确认继续?', onConfirm: () => onParseChapter(ch.id, ch.title) })}>
|
||||||
|
{isAIMode ? <Bot className="h-3 w-3 mr-1" /> : <Wand2 className="h-3 w-3 mr-1" />}
|
||||||
|
{t(isAIMode ? 'projectCard.chapters.reparseAI' : 'projectCard.chapters.reparse')}
|
||||||
|
</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{ch.status === 'error' && (
|
{ch.status === 'error' && (
|
||||||
@@ -1868,6 +1883,7 @@ function ChaptersPanel({
|
|||||||
})()}
|
})()}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user