feat: add segment tracking to audiobook projects and update UI to display progress
This commit is contained in:
@@ -36,6 +36,8 @@ export interface AudiobookProject {
|
||||
script_config?: Record<string, unknown>
|
||||
created_at: string
|
||||
updated_at: string
|
||||
segment_total: number
|
||||
segment_done: number
|
||||
}
|
||||
|
||||
export interface AudiobookCharacter {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { toast } from 'sonner'
|
||||
import { Book, Plus, Trash2, RefreshCw, Download, ChevronDown, ChevronUp, Play, Square, Pencil, Check, X, Loader2, Zap, Settings2, PanelLeftClose, PanelLeftOpen, Wand2, Volume2, Bot, Flame } from 'lucide-react'
|
||||
import { Book, BookOpen, Plus, Trash2, RefreshCw, Download, ChevronDown, ChevronUp, Play, Square, Pencil, Check, X, Loader2, Zap, Settings2, PanelLeftClose, PanelLeftOpen, Wand2, Volume2, Bot, Flame } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
@@ -1062,25 +1062,48 @@ function ProjectListSidebar({
|
||||
) : projects.length === 0 ? (
|
||||
<div className="px-3 py-4 text-xs text-muted-foreground">{t('noProjects')}</div>
|
||||
) : (
|
||||
projects.map(p => (
|
||||
<button
|
||||
key={p.id}
|
||||
onClick={() => onSelect(p.id)}
|
||||
className={`w-full text-left rounded-lg border p-3 flex flex-col gap-1.5 transition-colors hover:bg-muted/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 ${
|
||||
selectedId === p.id
|
||||
? 'bg-background border-border shadow-sm'
|
||||
: 'bg-background/50 border-border/40'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-start gap-2">
|
||||
<Book className="h-3.5 w-3.5 shrink-0 mt-0.5 text-muted-foreground" />
|
||||
<span className="text-sm font-medium leading-snug break-words min-w-0 flex-1">{p.title}</span>
|
||||
</div>
|
||||
<Badge variant={(STATUS_COLORS[p.status] || 'secondary') as any} className="text-[10px] h-4 px-1 self-start ml-5">
|
||||
{t(`status.${p.status}`, { defaultValue: p.status })}
|
||||
</Badge>
|
||||
</button>
|
||||
))
|
||||
projects.map(p => {
|
||||
const isNsfw = p.source_type === 'ai_generated' && !!p.script_config?.nsfw_mode
|
||||
const ProjectIcon = p.source_type === 'epub'
|
||||
? BookOpen
|
||||
: isNsfw
|
||||
? Flame
|
||||
: p.source_type === 'ai_generated'
|
||||
? Wand2
|
||||
: Book
|
||||
const iconClass = isNsfw
|
||||
? 'h-3.5 w-3.5 shrink-0 mt-0.5 text-orange-500'
|
||||
: p.source_type === 'ai_generated'
|
||||
? 'h-3.5 w-3.5 shrink-0 mt-0.5 text-violet-500'
|
||||
: 'h-3.5 w-3.5 shrink-0 mt-0.5 text-muted-foreground'
|
||||
const showProgress = p.segment_total > 0 && ['processing', 'generating', 'done'].includes(p.status)
|
||||
return (
|
||||
<button
|
||||
key={p.id}
|
||||
onClick={() => onSelect(p.id)}
|
||||
className={`w-full text-left rounded-lg border p-3 flex flex-col gap-1.5 transition-colors hover:bg-muted/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 ${
|
||||
selectedId === p.id
|
||||
? 'bg-background border-border shadow-sm'
|
||||
: 'bg-background/50 border-border/40'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-start gap-2">
|
||||
<ProjectIcon className={iconClass} />
|
||||
<span className="text-sm font-medium leading-snug break-words min-w-0 flex-1">{p.title}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 ml-5">
|
||||
<Badge variant={(STATUS_COLORS[p.status] || 'secondary') as any} className="text-[10px] h-4 px-1">
|
||||
{t(`status.${p.status}`, { defaultValue: p.status })}
|
||||
</Badge>
|
||||
{showProgress && (
|
||||
<span className="text-[10px] text-muted-foreground tabular-nums">
|
||||
{p.segment_done}/{p.segment_total}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user