92 lines
3.1 KiB
TypeScript
92 lines
3.1 KiB
TypeScript
import { useState } from 'react'
|
|
import { imageGenerationService } from '@/lib/services/imageGeneration'
|
|
import { useToast } from '@/components/shared/Toast'
|
|
import type { Flashcard } from '@/lib/services/flashcards'
|
|
|
|
interface UseFlashcardImageGenerationReturn {
|
|
generatingCards: Set<string>
|
|
generationProgress: { [cardId: string]: string }
|
|
generateImage: (card: Flashcard, onComplete?: () => void) => Promise<void>
|
|
}
|
|
|
|
export const useFlashcardImageGeneration = (): UseFlashcardImageGenerationReturn => {
|
|
const toast = useToast()
|
|
const [generatingCards, setGeneratingCards] = useState<Set<string>>(new Set())
|
|
const [generationProgress, setGenerationProgress] = useState<{ [cardId: string]: string }>({})
|
|
|
|
const generateImage = async (card: Flashcard, onComplete?: () => void) => {
|
|
try {
|
|
// 檢查是否已在生成中
|
|
if (generatingCards.has(card.id)) {
|
|
toast.error('該詞卡正在生成圖片中,請稍候...')
|
|
return
|
|
}
|
|
|
|
// 標記為生成中
|
|
setGeneratingCards(prev => new Set([...prev, card.id]))
|
|
setGenerationProgress(prev => ({ ...prev, [card.id]: '啟動生成中...' }))
|
|
|
|
toast.info(`開始為「${card.word}」生成例句圖片...`)
|
|
|
|
// 1. 啟動圖片生成
|
|
const generateResult = await imageGenerationService.generateImage(card.id)
|
|
|
|
if (!generateResult.success || !generateResult.data) {
|
|
throw new Error(generateResult.error || '啟動生成失敗')
|
|
}
|
|
|
|
const requestId = generateResult.data.requestId
|
|
setGenerationProgress(prev => ({ ...prev, [card.id]: 'Gemini 生成描述中...' }))
|
|
|
|
// 2. 輪詢生成進度
|
|
const finalStatus = await imageGenerationService.pollUntilComplete(
|
|
requestId,
|
|
(status) => {
|
|
// 更新進度顯示
|
|
const stage = status.stages.gemini.status === 'completed'
|
|
? 'Replicate 生成圖片中...'
|
|
: 'Gemini 生成描述中...'
|
|
|
|
setGenerationProgress(prev => ({ ...prev, [card.id]: stage }))
|
|
},
|
|
5 // 5分鐘超時
|
|
)
|
|
|
|
// 3. 生成成功,刷新資料
|
|
if (finalStatus.overallStatus === 'completed') {
|
|
setGenerationProgress(prev => ({ ...prev, [card.id]: '生成完成,載入中...' }))
|
|
|
|
// 通知父組件刷新數據
|
|
if (onComplete) {
|
|
await onComplete()
|
|
}
|
|
|
|
toast.success(`「${card.word}」的例句圖片生成完成!`)
|
|
} else {
|
|
throw new Error('圖片生成未完成')
|
|
}
|
|
|
|
} catch (error: any) {
|
|
console.error('圖片生成失敗:', error)
|
|
toast.error(`圖片生成失敗: ${error.message || '未知錯誤'}`)
|
|
} finally {
|
|
// 清理狀態
|
|
setGeneratingCards(prev => {
|
|
const newSet = new Set(prev)
|
|
newSet.delete(card.id)
|
|
return newSet
|
|
})
|
|
setGenerationProgress(prev => {
|
|
const newProgress = { ...prev }
|
|
delete newProgress[card.id]
|
|
return newProgress
|
|
})
|
|
}
|
|
}
|
|
|
|
return {
|
|
generatingCards,
|
|
generationProgress,
|
|
generateImage
|
|
}
|
|
} |