File size: 3,280 Bytes
046ca57 ca67cfa 046ca57 ca67cfa 046ca57 ca67cfa 046ca57 ca67cfa 046ca57 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
import React, { createContext, useContext, useState, useCallback } from 'react'
import { ImageExample } from '../types'
interface ImageClassificationConfig {
top_k: number
}
interface ImageClassificationContextType {
examples: ImageExample[]
selectedExample: ImageExample | null
setSelectedExample: (example: ImageExample | null) => void
addExample: (file: File) => void
removeExample: (id: string) => void
updateExample: (id: string, updates: Partial<ImageExample>) => void
clearExamples: () => void
config: ImageClassificationConfig
setConfig: React.Dispatch<React.SetStateAction<ImageClassificationConfig>>
}
const ImageClassificationContext = createContext<
ImageClassificationContextType | undefined
>(undefined)
export function useImageClassification() {
const context = useContext(ImageClassificationContext)
if (context === undefined) {
throw new Error(
'useImageClassification must be used within an ImageClassificationProvider'
)
}
return context
}
interface ImageClassificationProviderProps {
children: React.ReactNode
}
export function ImageClassificationProvider({
children
}: ImageClassificationProviderProps) {
const [examples, setExamples] = useState<ImageExample[]>([])
const [selectedExample, setSelectedExample] = useState<ImageExample | null>(
null
)
const [config, setConfig] = useState<ImageClassificationConfig>({
top_k: 5
})
const addExample = useCallback((file: File) => {
const id = Math.random().toString(36).substr(2, 9)
const url = URL.createObjectURL(file)
const newExample: ImageExample = {
id,
name: file.name,
url,
file,
predictions: undefined,
isLoading: false
}
setExamples((prev) => [...prev, newExample])
}, [])
const removeExample = useCallback((id: string) => {
setExamples((prev) => {
const updated = prev.filter((ex) => ex.id !== id)
// Clean up object URL to prevent memory leaks
const example = prev.find((ex) => ex.id === id)
if (example?.url) {
URL.revokeObjectURL(example.url)
}
return updated
})
// Clear selection if the selected example was removed
setSelectedExample((prev) => (prev?.id === id ? null : prev))
}, [])
const updateExample = useCallback(
(id: string, updates: Partial<ImageExample>) => {
setExamples((prev) =>
prev.map((ex) => (ex.id === id ? { ...ex, ...updates } : ex))
)
// Update selected example if it's the one being updated
setSelectedExample((prev) =>
prev?.id === id ? { ...prev, ...updates } : prev
)
},
[]
)
const clearExamples = useCallback(() => {
// Clean up all object URLs to prevent memory leaks
examples.forEach((example) => {
if (example.url) {
URL.revokeObjectURL(example.url)
}
})
setExamples([])
setSelectedExample(null)
}, [examples])
const value: ImageClassificationContextType = {
examples,
selectedExample,
setSelectedExample,
addExample,
removeExample,
updateExample,
clearExamples,
config,
setConfig
}
return (
<ImageClassificationContext.Provider value={value}>
{children}
</ImageClassificationContext.Provider>
)
}
|