feat: add regenerate all previews functionality and update localization strings
This commit is contained in:
@@ -85,7 +85,12 @@
|
||||
"voiceDesign": "Voice #{{id}}",
|
||||
"noVoice": "Unassigned",
|
||||
"editTitle": "Edit Character: {{name}}",
|
||||
"savedSuccess": "Character saved"
|
||||
"savedSuccess": "Character saved",
|
||||
"regeneratingPreview": "Regenerating...",
|
||||
"regeneratePreview": "Regenerate Preview",
|
||||
"regenerateAll": "Regenerate All Previews",
|
||||
"regenerateAllDone": "All previews regenerated",
|
||||
"previewNotReady": "Collecting preview..."
|
||||
},
|
||||
|
||||
"confirm": {
|
||||
|
||||
@@ -84,7 +84,12 @@
|
||||
"voiceDesign": "音声 #{{id}}",
|
||||
"noVoice": "未割り当て",
|
||||
"editTitle": "キャラクターを編集:{{name}}",
|
||||
"savedSuccess": "キャラクターを保存しました"
|
||||
"savedSuccess": "キャラクターを保存しました",
|
||||
"regeneratingPreview": "試聴を再生成中...",
|
||||
"regeneratePreview": "試聴を再生成",
|
||||
"regenerateAll": "試聴を一括再生成",
|
||||
"regenerateAllDone": "すべての試聴を再生成しました",
|
||||
"previewNotReady": "試聴を収集中..."
|
||||
},
|
||||
|
||||
"confirm": {
|
||||
|
||||
@@ -84,7 +84,12 @@
|
||||
"voiceDesign": "음성 #{{id}}",
|
||||
"noVoice": "미할당",
|
||||
"editTitle": "캐릭터 편집: {{name}}",
|
||||
"savedSuccess": "캐릭터가 저장되었습니다"
|
||||
"savedSuccess": "캐릭터가 저장되었습니다",
|
||||
"regeneratingPreview": "미리듣기 재생성 중...",
|
||||
"regeneratePreview": "미리듣기 재생성",
|
||||
"regenerateAll": "미리듣기 일괄 재생성",
|
||||
"regenerateAllDone": "모든 미리듣기가 재생성되었습니다",
|
||||
"previewNotReady": "미리듣기 수집 중..."
|
||||
},
|
||||
|
||||
"confirm": {
|
||||
|
||||
@@ -88,6 +88,8 @@
|
||||
"savedSuccess": "角色已保存",
|
||||
"regeneratingPreview": "重新生成试听中...",
|
||||
"regeneratePreview": "重生试听",
|
||||
"regenerateAll": "一键重新生成试听",
|
||||
"regenerateAllDone": "所有试听已重新生成",
|
||||
"previewNotReady": "试听收集中..."
|
||||
},
|
||||
|
||||
|
||||
@@ -84,7 +84,12 @@
|
||||
"voiceDesign": "音色 #{{id}}",
|
||||
"noVoice": "未分配",
|
||||
"editTitle": "編輯角色:{{name}}",
|
||||
"savedSuccess": "角色已儲存"
|
||||
"savedSuccess": "角色已儲存",
|
||||
"regeneratingPreview": "重新生成試聽中...",
|
||||
"regeneratePreview": "重生試聽",
|
||||
"regenerateAll": "一鍵重新生成試聽",
|
||||
"regenerateAllDone": "所有試聽已重新生成",
|
||||
"previewNotReady": "試聽收集中..."
|
||||
},
|
||||
|
||||
"confirm": {
|
||||
|
||||
@@ -1190,6 +1190,24 @@ function CharactersPanel({
|
||||
}
|
||||
}
|
||||
|
||||
const handleRegenerateAllPreviews = async () => {
|
||||
const charsWithVoice = detail?.characters.filter(c => c.voice_design_id) ?? []
|
||||
if (charsWithVoice.length === 0) return
|
||||
const ids = charsWithVoice.map(c => c.id)
|
||||
setRegeneratingVoices(new Set(ids))
|
||||
for (const id of ids) {
|
||||
try {
|
||||
await audiobookApi.regenerateCharacterPreview(project.id, id)
|
||||
setVoiceKeys(prev => ({ ...prev, [id]: (prev[id] || 0) + 1 }))
|
||||
} catch (e: any) {
|
||||
toast.error(`${detail?.characters.find(c => c.id === id)?.name}: ${formatApiError(e)}`)
|
||||
} finally {
|
||||
setRegeneratingVoices(prev => { const n = new Set(prev); n.delete(id); return n })
|
||||
}
|
||||
}
|
||||
toast.success(t('projectCard.characters.regenerateAllDone'))
|
||||
}
|
||||
|
||||
|
||||
const charCount = detail?.characters.length ?? 0
|
||||
const hasChaptersOutline = (detail?.chapters.length ?? 0) > 0
|
||||
@@ -1237,6 +1255,20 @@ function CharactersPanel({
|
||||
{t('projectCard.reanalyze')}
|
||||
</Button>
|
||||
)}
|
||||
{!isActive && status === 'characters_ready' && (detail?.characters.some(c => c.voice_design_id) ?? false) && (
|
||||
<Button
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
className="text-muted-foreground"
|
||||
onClick={handleRegenerateAllPreviews}
|
||||
disabled={regeneratingVoices.size > 0}
|
||||
>
|
||||
{regeneratingVoices.size > 0
|
||||
? <><Loader2 className="h-3 w-3 mr-1 animate-spin" />{t('projectCard.characters.regeneratingPreview')}</>
|
||||
: <><RefreshCw className="h-3 w-3 mr-1" />{t('projectCard.characters.regenerateAll')}</>
|
||||
}
|
||||
</Button>
|
||||
)}
|
||||
{hasChaptersOutline && (
|
||||
<Button size="icon" variant="ghost" className="h-6 w-6" onClick={onToggle}>
|
||||
<PanelLeftClose className="h-3.5 w-3.5" />
|
||||
|
||||
Reference in New Issue
Block a user